package com.willalp.canteen.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.willalp.canteen.domain.*;
import com.willalp.canteen.domain.resp.CustomGetOrderResp;
import com.willalp.canteen.domain.vo.CustomGetOrderVo;
import com.willalp.canteen.domain.vo.HsCanteenOrderInfoVo;
import com.willalp.canteen.domain.vo.LiveUseMoneyMonthStatExcel;
import com.willalp.canteen.domain.vo.MenuCountVo;
import com.willalp.canteen.mapper.HsCanteenOrderMapper;
import com.willalp.canteen.service.IHsCanteenDiningPlaceService;
import com.willalp.canteen.service.IHsCanteenMenuService;
import com.willalp.canteen.service.IHsCanteenOrderDetailService;
import com.willalp.canteen.service.IHsCanteenOrderService;
import com.willalp.common.core.domain.AjaxResult;
import com.willalp.common.enums.ConsumeChangeEnum;
import com.willalp.common.enums.NumberRuleEnum;
import com.willalp.common.enums.SysOrgCodeEnum;
import com.willalp.common.exception.base.BaseException;
import com.willalp.common.utils.DateUtils;
import com.willalp.common.utils.SecurityUtils;
import com.willalp.common.utils.StringUtils;
import com.willalp.common.utils.bean.BeanUtils;
import com.willalp.integral.domain.Integral;
import com.willalp.integral.service.IIntegralService;
import com.willalp.number.domain.req.NumberRuleReq;
import com.willalp.number.service.IHsSysNumberRuleService;
import com.willalp.system.domain.SysUserOrganization;
import com.willalp.system.service.ISysConfigService;
import com.willalp.system.service.ISysUserOrganizationService;
import com.willalp.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 食堂订单Service业务层处理
 *
 * @author songyu
 * @date 2021-12-03
 */
@Service
public class HsCanteenOrderServiceImpl extends ServiceImpl<HsCanteenOrderMapper, HsCanteenOrder> implements IHsCanteenOrderService {
    @Autowired
    private HsCanteenOrderMapper hsCanteenOrderMapper;

    @Resource
    private IHsCanteenOrderDetailService codService;

    @Autowired
    ISysUserService sysUserService;

    @Autowired
    IHsSysNumberRuleService hsSysNumberRuleService;

    @Autowired
    IIntegralService integralService;

    @Autowired
    ISysUserOrganizationService sysUserOrganizationService;

    @Resource
    private IHsCanteenMenuService menuService;

    @Resource
    private IHsCanteenDiningPlaceService diningPlaceService;

    @Resource
    private ISysUserOrganizationService userOrganizationService;


    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean payMiwp(HsCanteenOrder order) {
        if (ObjectUtil.isEmpty(order)) {
            throw new BaseException("没有订单信息");
        }
        List<String> loginName = order.getLoginName();
        List<HsCanteenCuisine> list = order.getList();
        String menuNumber = order.getMenuNumber();
        String placeNumber = order.getPlaceNumber();
        BigDecimal orderTotal = order.getOrderTotal();
        if (StringUtils.isBlank(menuNumber)) {
            throw new BaseException("请选择菜单");
        }
        if (0 == list.size()) {
            throw new BaseException("请选择菜品");
        }
        if (0 == loginName.size()) {
            throw new BaseException("请选择用户");
        }
        if (StringUtils.isBlank(placeNumber)) {
            throw new BaseException("请选择就餐地");
        }
        Date date = new Date();
        List<HsCanteenOrder> oSaveList = new ArrayList<>();
        List<HsCanteenOrderDetail> oDSaveList = new ArrayList<>();

        loginName.forEach(item -> {
            String jgid = order.getJgid();
            SysUserOrganization uo = new SysUserOrganization();
            String[] split = item.split(",");
            if (0 < split.length && split.length <= 2) {
                uo.setLoginName(split[0]);
            } else {
                throw new BaseException("用户异常请重新选择");
            }
            uo.setOrganizationCode(jgid);
            List<SysUserOrganization> uoDB = sysUserOrganizationService.selectSysUserOrganizationList(uo);
            SysUserOrganization sysUserOrganization = uoDB.get(0);
            BigDecimal integral = sysUserOrganization.getIntegral();
            if (integral.compareTo(orderTotal) > 0) {
                BigDecimal subtract = integral.subtract(orderTotal);
                sysUserOrganization.setIntegral(subtract);
                if (!sysUserOrganizationService.updateById(sysUserOrganization)) {
                    throw new BaseException("积分更新失败，请重试");
                }
            } else {
                throw new BaseException(split[1] + " - 积分不足");
            }
            HsCanteenOrder canteenOrder = new HsCanteenOrder();
            //支付时间
            canteenOrder.setPaytime(date);
            //获取编号
            NumberRuleReq numberRuleReq = new NumberRuleReq();
            numberRuleReq.setRuleId(NumberRuleEnum.ORDER.getValue());
            numberRuleReq.setInput(String.valueOf(DateUtil.year(canteenOrder.getPaytime())).substring(2, 4));
            String number = hsSysNumberRuleService.getNumber(numberRuleReq);
            canteenOrder.setOrderNumber(number);
            canteenOrder.setUserNumber(split[0]);
            canteenOrder.setOrderTotal(orderTotal);
            canteenOrder.setMenuNumber(menuNumber);
            canteenOrder.setPlaceNumber(placeNumber);
            canteenOrder.setPlaceName(order.getPlaceName());
            canteenOrder.setZfbz(0);
            canteenOrder.setConsumeSign(0);
            canteenOrder.setNickName(order.getNickName());
            canteenOrder.setJgid(jgid);
            oSaveList.add(canteenOrder);
            list.forEach(cItem -> {
                HsCanteenOrderDetail cod = new HsCanteenOrderDetail();
                BeanUtils.copyProperties(cItem, cod);
                cod.setMenuNumber(menuNumber);
                cod.setOrderNumber(number);
                cod.setPrice(cItem.getCuisinePrice());
                cod.setAmount(1);
                cod.setTotal(orderTotal);
                oDSaveList.add(cod);
            });
        });
        if (0 != oSaveList.size()) {
            if (!saveBatch(oSaveList)) {
                throw new BaseException("订单生成失败");
            }
        }
        if (0 != oDSaveList.size()) {
            if (!codService.saveBatch(oDSaveList)) {
                throw new BaseException("订单详情生成失败");
            }
        }
        return true;
    }

    @Override
    public Object jcdStat(String menuCode) {
        if (StringUtils.isBlank(menuCode)) {
            throw new BaseException("菜单编号不能为空");
        }
        Map<String, Object> map = new HashMap<>();
        HsCanteenMenu canteenMenu = menuService.getBaseMapper().selectOne(new QueryWrapper<HsCanteenMenu>().eq("menu_number", menuCode));
        map.put("menuName", canteenMenu.getMenuName());
        List<HsCanteenOrder> orders = baseMapper.selectList(new QueryWrapper<HsCanteenOrder>().eq("menu_number", menuCode));
        return jcdTj(map, orders);
    }

    @Override
    public Object jcdMonthStat(int year, int month) {
        Map<String, Object> map = new HashMap<>();
        List<HsCanteenOrder> orders = baseMapper.selectList(new QueryWrapper<HsCanteenOrder>()
                .eq("YEAR(paytime) ", year)
                .eq("MONTH(paytime)", month));
        return jcdTj(map, orders);
    }

    @Override
    public List<LiveUseMoneyMonthStatExcel> liveUseMoneyMonthStat(int year, int month) {
        //获取现场消费订单信息
        List<LiveUseMoneyMonthStatExcel> orders = baseMapper.getOrderDataBasedOnMenuAndMonthStat(
                sysConfigService.selectConfigByKey("live_use_money_number_key"), year, month);
        return orders;
    }

    @Resource
    private ISysConfigService sysConfigService;

    private Map<String, Object> jcdTj(Map<String, Object> map, List<HsCanteenOrder> orders) {
        if (0 == orders.size()) {
            throw new BaseException("暂无统计数据");
        }
        List<HsCanteenDiningPlace> hsCanteenDiningPlaces = diningPlaceService.getBaseMapper().selectList(
                new QueryWrapper<HsCanteenDiningPlace>()
                        .eq("jgid", SysOrgCodeEnum.MLHuiZhuLi.getCode())
                        .eq("parent_id", sysConfigService.selectConfigByKey("REPAST_PLACE_CONFIG_KEY")));
        if (0 == hsCanteenDiningPlaces.size()) {
            throw new BaseException("暂无统计数据");
        }
        List<SysUserOrganization> sysUserOrganizations = userOrganizationService.getBaseMapper().selectList(
                new QueryWrapper<SysUserOrganization>().eq("organization_code", SysOrgCodeEnum.MLHuiZhuLi.getCode()));
        if (0 == sysUserOrganizations.size()) {
            throw new BaseException("暂无统计数据");
        }
        List<Object> list = new ArrayList<>();
        for (HsCanteenDiningPlace hsCanteenDiningPlace : hsCanteenDiningPlaces) {
            Map<String, Object> mapJcd = new HashMap<>();
            mapJcd.put("placeName", hsCanteenDiningPlace.getPlaceName());
            //就餐地总数
            List<HsCanteenOrder> jdcSumList = orders.stream().filter(o ->
                    null != o.getPlaceNumber() &&
                            o.getZfbz() != 1 &&
                            o.getPlaceNumber().equals(hsCanteenDiningPlace.getPlaceNumber())).collect(Collectors.toList());
            mapJcd.put("count", jdcSumList.size());
            //用户类型计算
            int sybq = 0;
            int fsybq = 0;
            int dsflwwb = 0;
            for (HsCanteenOrder hsCanteenOrder : jdcSumList) {
                for (SysUserOrganization userOrganization : sysUserOrganizations) {
                    if (hsCanteenOrder.getUserNumber().equals(userOrganization.getLoginName()) &&
                            hsCanteenOrder.getZfbz() != 1) {
                        switch (userOrganization.getUserType()) {
                            case "1":
                                //事业编群
                                sybq++;
                                break;
                            case "2":
                                //非事业编群
                                fsybq++;
                                break;
                            case "3":
                            case "4":
                                //第三方劳务外包
                                dsflwwb++;
                                break;
                            default:
                                break;
                        }
                    }
                }
            }
            mapJcd.put("sybq", sybq);
            mapJcd.put("fsybq", fsybq);
            mapJcd.put("dsflwwb", dsflwwb);
            list.add(mapJcd);
        }
        map.put("place", list);
        return map;
    }

    @Override
    public List<MenuCountVo> getTheMenuItemsAndQuantitiesPerPerson(String menuCode) {
        if (StringUtils.isBlank(menuCode)) {
            throw new BaseException("菜单编号不能为空");
        }
        List<HsCanteenOrderInfoVo> orderDataBasedOnMenu = hsCanteenOrderMapper.getOrderDataBasedOnMenu(menuCode);
        if (0 == orderDataBasedOnMenu.size()) {
            throw new BaseException("该菜单下没有可用订单");
        }
        //提取用户 使用map分组
        Map<String, List<HsCanteenOrderInfoVo>> mapOs = new HashMap<>();
        orderDataBasedOnMenu.forEach(o -> {
            String userNumber = o.getUserNumber();
            if (StringUtils.isNotBlank(userNumber) && null == mapOs.get(userNumber)) {
                mapOs.put(userNumber, new ArrayList<>());
            }
        });
        //寻找每个用户的菜品
        mapOs.forEach((k, v) -> v.addAll(orderDataBasedOnMenu.stream().filter(o -> k.equals(o.getUserNumber())).collect(Collectors.toList())));
        List<MenuCountVo> mvs = new ArrayList<>();
        //拼接菜品信息
        mapOs.forEach((k, v) -> {
            StringBuilder foodInformation = new StringBuilder();
            for (HsCanteenOrderInfoVo xv : v) {
                String cuisineName = xv.getCuisineName();
                if (foodInformation.toString().contains(cuisineName)) {
                    break;
                }
                //获取每个菜品的数量
                int i = (int) v.stream().filter(xv1 -> StringUtils.isNotBlank(cuisineName) && cuisineName.contentEquals(xv1.getCuisineName())).count();
                //拼接单个菜品信息
                foodInformation.append("[ ").append(cuisineName).append(" * ").append(i).append(" ] ");
            }
            MenuCountVo mv = new MenuCountVo(v.get(0).getNickName(), k, foodInformation.toString(), v.get(0).getPlaceName());
            mvs.add(mv);
        });
        return mvs;
    }


    /**
     * 查询食堂订单
     *
     * @param orderId 食堂订单主键
     * @return 食堂订单
     */
    @Override
    public HsCanteenOrder selectHsCanteenOrderByOrderId(String orderId) {
        return hsCanteenOrderMapper.selectHsCanteenOrderByOrderId(orderId);
    }

    /**
     * 查询食堂订单列表
     *
     * @param hsCanteenOrder 食堂订单
     * @return 食堂订单
     */
    @Override
    public List<HsCanteenOrder> selectHsCanteenOrderList(HsCanteenOrder hsCanteenOrder) {
        return hsCanteenOrderMapper.selectHsCanteenOrderList(hsCanteenOrder);
    }

    /**
     * 作废食堂订单
     *
     * @param hsCanteenOrder
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult getBack(HsCanteenOrder hsCanteenOrder) {
        BigDecimal total = hsCanteenOrder.getOrderTotal();
        if (hsCanteenOrder.getZfbz() == 1) {
            return AjaxResult.error("该订单已作废，不可重复作废");
        }
        if (StrUtil.isBlank(hsCanteenOrder.getUserNumber())) {
            return AjaxResult.error("用户编号为空，请联系管理员");
        }
        if (hsCanteenOrder.getZfbz() == 3) {
            return AjaxResult.error("因错退还订单不可作废");
        }
        try {
            SysUserOrganization user = new SysUserOrganization();
            user.setLoginName(hsCanteenOrder.getUserNumber());
            user.setOrganizationCode(hsCanteenOrder.getJgid());
            List<SysUserOrganization> userList = sysUserOrganizationService.selectSysUserOrganizationList(user);
            if (userList.size() == 0) {
                return AjaxResult.error("用户信息不存在");
            }
            user = userList.get(0);
            //消费记录
            Integral integral = new Integral();
            integral.setId(IdWorker.getIdStr());//积分主键
            integral.setMoneyType(Integer.valueOf(ConsumeChangeEnum.REFUND.getValue()));//退还
            integral.setRechargeEquipmentCode(hsCanteenOrder.getDeviceNumber());//设备编号
            integral.setRechargeEquipmentName(hsCanteenOrder.getDeviceName());//设备名称
            integral.setLoginName(hsCanteenOrder.getUserNumber());//账号编号
            integral.setRechargeIntegral(hsCanteenOrder.getOrderTotal());//积分(负数)
            integral.setIsDelete(0);//有效标志
            integral.setNickName(user.getNickName());
            integral.setOrganizationCode(hsCanteenOrder.getJgid());//机构代码
            integral.setOrderNumber(hsCanteenOrder.getOrderNumber());
            integral.setRechargeId(SecurityUtils.getLoginUser().getUserId());
            integral.setRechargeTime(DateUtils.getNowDate());
            if (hsCanteenOrder.getConsumeSign() == 0) {//积分
                user.setIntegral(user.getIntegral().add(hsCanteenOrder.getOrderTotal()));
            } else {//记账额度
                user.setQuota(user.getQuota().add(hsCanteenOrder.getOrderTotal()));
            }
            integralService.save(integral);
            sysUserOrganizationService.updateById(user);
            hsCanteenOrderMapper.updateCanteenOrderZfpb(hsCanteenOrder.getJgid(), hsCanteenOrder.getOrderId());//更新订单主表作废判别
        } catch (Exception e) {
            throw new BaseException("作废失败");
        }
        return AjaxResult.success();
    }

    /**
     * 待取餐订单
     *
     * @param customGetOrderVo
     * @return
     */
    @Override
    public List<CustomGetOrderResp> getOrderNow(CustomGetOrderVo customGetOrderVo) {
        return hsCanteenOrderMapper.getOrderNow(customGetOrderVo);
    }

    @Override
    public CustomGetOrderResp getMenuNow(CustomGetOrderVo customGetOrderVo) {
        return hsCanteenOrderMapper.getMenuNow(customGetOrderVo);
    }


    /**
     * 近一月订单量
     *
     * @param hsCanteenOrder
     * @return
     */
    @Override
    public List<HsCanteenOrder> selectHsCanteenOrderLists(HsCanteenOrder hsCanteenOrder) {
        return hsCanteenOrderMapper.selectHsCanteenOrderLists(hsCanteenOrder);
    }

    /**
     * 首页金额总额
     *
     * @param hsCanteenOrder
     * @return
     */
    @Override
    public String getSumpay(HsCanteenOrder hsCanteenOrder) {
        return hsCanteenOrderMapper.getSumpay(hsCanteenOrder);
    }

    /**
     * 首页订单总数
     *
     * @param hsCanteenOrder
     * @return
     */
    @Override
    public String getSumOrderNum(HsCanteenOrder hsCanteenOrder) {
        return hsCanteenOrderMapper.getSumOrderNum(hsCanteenOrder);
    }

    @Override
    public void checkOrderTotal(HsCanteenOrder hsCanteenOrder) {
        if (hsCanteenOrder.getZfbz() == 1) {
            throw new BaseException("该订单已作废，不可退还");
        } else if (hsCanteenOrder.getZfbz() == 3) {
            throw new BaseException("该订单为因错退还，不可再次退还");
        }
        List<Map<String, Object>> zforderlist = hsCanteenOrderMapper.checkSfzf(hsCanteenOrder);
        BigDecimal totalpay = new BigDecimal(zforderlist.get(0).get("order_total") + "");
        BigDecimal partpay = BigDecimal.ZERO;
        if (zforderlist.get(1).size() > 0) {
            partpay = new BigDecimal(zforderlist.get(1).get("order_total") + "").add(hsCanteenOrder.getOrderTotal());
        }
        if (totalpay.compareTo(partpay) < 0) {
            throw new BaseException("已超出最大退还金额，不可退还");
        }
        //积分退还
        SysUserOrganization user = new SysUserOrganization();
        user.setLoginName(hsCanteenOrder.getUserNumber());
        user.setOrganizationCode(hsCanteenOrder.getJgid());
        List<SysUserOrganization> userList = sysUserOrganizationService.selectSysUserOrganizationList(user);
        if (userList.size() == 0) {
            throw new BaseException("用户信息不存在");
        }
        user = userList.get(0);
        user.setIntegral(user.getIntegral().add(hsCanteenOrder.getOrderTotal()));
        sysUserOrganizationService.updateById(user);
    }

    @Override
    public List<Map<String, Object>> getConsumeReport(Map<String, Object> params) {
        return hsCanteenOrderMapper.getConsumeReport(params);
    }

    @Override
    public List<HsCanteenOrder> todayNotOrderUser() {
        return hsCanteenOrderMapper.todayNotOrderUser();
    }
}
