package com.qs.mp.web.controller.api.channel.mall;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qs.mp.admin.domain.Goods;
import com.qs.mp.admin.domain.GoodsSku;
import com.qs.mp.admin.domain.vo.ShippingTemplateCalculateVO;
import com.qs.mp.admin.service.IGoodsService;
import com.qs.mp.admin.service.IGoodsSkuService;
import com.qs.mp.channel.domain.Channel;
import com.qs.mp.channel.domain.ChannelGoods;
import com.qs.mp.channel.domain.ChannelGoodsOrder;
import com.qs.mp.channel.domain.ChannelGoodsOrderItem;
import com.qs.mp.channel.domain.param.ChannelGoodsOrderParam;
import com.qs.mp.channel.domain.param.OrderPayParam;
import com.qs.mp.channel.domain.vo.ChannelGoodsOrderInfoVO;
import com.qs.mp.channel.domain.vo.ChannelGoodsOrderItemVO;
import com.qs.mp.channel.domain.vo.ChannelGoodsOrderSettleVO;
import com.qs.mp.channel.domain.vo.ChannelGoodsOrderVO;
import com.qs.mp.channel.service.IChannelGoodsOrderItemService;
import com.qs.mp.channel.service.IChannelGoodsOrderService;
import com.qs.mp.channel.service.IChannelService;
import com.qs.mp.common.core.domain.AjaxResult;
import com.qs.mp.common.core.page.TableDataInfo;
import com.qs.mp.common.core.redis.RedisCache;
import com.qs.mp.common.domain.DeliveryCompany;
import com.qs.mp.common.enums.*;
import com.qs.mp.common.exception.ServiceException;
import com.qs.mp.common.service.IDeliveryCompanyService;
import com.qs.mp.common.service.IShippingTemplateRuleService;
import com.qs.mp.common.service.IShippingTemplateService;
import com.qs.mp.common.utils.LogUtil;
import com.qs.mp.common.utils.StringUtils;
import com.qs.mp.framework.redis.RedisKey;
import com.qs.mp.pay.service.IWalletService;
import com.qs.mp.system.domain.SysUser;
import com.qs.mp.system.service.ISysUserService;
import com.qs.mp.user.domain.UserAddr;
import com.qs.mp.user.service.IUserAddrService;
import com.qs.mp.utils.SecurityUtils;
import com.qs.mp.web.controller.common.BaseApiController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import ma.glasnost.orika.MapperFacade;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author zhangkaikai
 * @create 2023-06-02 3:08 PM
 **/
@Api(tags = "门店采购商品订单管理")
@RestController
@RequestMapping("/api/v1/mp/channel/mall")
public class ChannelGoodsOrderController extends BaseApiController {


    @Autowired
    private IChannelGoodsOrderService channelGoodsOrderService;

    @Autowired
    private IChannelGoodsOrderItemService channelGoodsOrderItemService;

    @Autowired
    private IChannelService channelService;

    @Autowired
    private IUserAddrService userAddrService;

    @Autowired
    private IShippingTemplateRuleService shippingTemplateRuleService;

    @Autowired
    private IShippingTemplateService shippingTemplateService;

    @Autowired
    private IGoodsService goodsService;

    @Autowired
    private IGoodsSkuService goodsSkuService;

    @Autowired
    private IDeliveryCompanyService deliveryCompanyService;

    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private IWalletService walletService;

    @Autowired
    private RedisCache redisCache;

    @Value("${shipping.channel}")
    public Long shippingTemplateId;

    @Autowired
    private MapperFacade mapperFacade;


    @ApiOperation("采购商品订单列表")
    @PostMapping("/goods/order/list")
    @ApiResponses(
            @ApiResponse(code = 200, message = "成功", response = ChannelGoodsOrderVO.class)
    )
    public TableDataInfo goodsOrderList(@RequestBody JSONObject param) {
        Long channelId = SecurityUtils.getLoginUser().getChannelId();
        Integer status = param.getInteger("status");
        startPage();
        List<ChannelGoodsOrder> channelGoodsOrders = channelGoodsOrderService.list(
                new LambdaQueryWrapper<ChannelGoodsOrder>().eq(ChannelGoodsOrder::getChannelId, channelId)
                        .eq(null != status, ChannelGoodsOrder::getStatus, status)
                        .orderByDesc(ChannelGoodsOrder::getCreatedTime));
        List<ChannelGoodsOrderVO> channelGoodsOrderVOList = mapperFacade.mapAsList(channelGoodsOrders, ChannelGoodsOrderVO.class);
        for (ChannelGoodsOrderVO channelGoodsOrderVO : channelGoodsOrderVOList) {
            QueryWrapper<ChannelGoodsOrderItem> goodsOrderItemQueryWrapper = new QueryWrapper<>();
            goodsOrderItemQueryWrapper.eq("t1.order_id", channelGoodsOrderVO.getOrderId());
            List<ChannelGoodsOrderItemVO> goodsOrderItem = channelGoodsOrderItemService.selectChannelGoodsOrderItemVOList(goodsOrderItemQueryWrapper);
            channelGoodsOrderVO.setItems(goodsOrderItem);
        }
        TableDataInfo rspData = getDataTable(channelGoodsOrders);
        rspData.setRows(channelGoodsOrderVOList);
        return rspData;
    }


    @ApiOperation("采购商品订单详情")
    @PostMapping("/goods/order/detail")
    @ApiResponses(
            @ApiResponse(code = 200, message = "成功", response = ChannelGoodsOrderInfoVO.class)
    )
    public AjaxResult goodsOrderDetail(@RequestBody ChannelGoodsOrder goodsOrder) {
        Long channelId = SecurityUtils.getLoginUser().getChannelId();
        ChannelGoodsOrder channelGoodsOrder = channelGoodsOrderService.getOne(new LambdaQueryWrapper<ChannelGoodsOrder>().eq(ChannelGoodsOrder::getChannelId, channelId)
                .eq(ChannelGoodsOrder::getOrderId, goodsOrder.getOrderId()));
        ChannelGoodsOrderInfoVO goodsOrderInfoVO = mapperFacade.map(channelGoodsOrder, ChannelGoodsOrderInfoVO.class);
        // 设置自动确认收货的时间;
        if (goodsOrderInfoVO != null && Objects.nonNull(goodsOrderInfoVO.getDeliveryTime())) {
            Date deliveryTime = goodsOrderInfoVO.getDeliveryTime();
            LocalDateTime autoConfirmTime = LocalDateTimeUtil.of(deliveryTime).plusDays(15);
            Duration between = LocalDateTimeUtil.between(LocalDateTime.now(), autoConfirmTime);
            long hours = between.toHours();
            long day = hours / 24;
            long hour = hours % 24;
            goodsOrderInfoVO.setAutoConfirmTime(day + "天" + hour + "小时");
        }

        if(null != goodsOrderInfoVO && null != goodsOrderInfoVO.getDeliveryId()) {
            DeliveryCompany deliveryCompany = deliveryCompanyService.getById(goodsOrderInfoVO.getDeliveryId());
            goodsOrderInfoVO.setDeliveryCompany(deliveryCompany);
        }
        QueryWrapper<ChannelGoodsOrderItem> goodsOrderItemQueryWrapper = new QueryWrapper<>();
        goodsOrderItemQueryWrapper.eq("t1.order_id", goodsOrder.getOrderId());
        List<ChannelGoodsOrderItemVO> goodsOrderItem = channelGoodsOrderItemService.selectChannelGoodsOrderItemVOList(goodsOrderItemQueryWrapper);
        goodsOrderInfoVO.setItems(goodsOrderItem);

        return AjaxResult.success(goodsOrderInfoVO);

    }



    /**
     * 订单结算，每次更换地址时需重新请求此接口
     */
    @ApiOperation("采购商品订单结算")
    @PostMapping("/goods/order/settle")
    @ApiResponses(
            @ApiResponse(code = 200, message = "成功", response = ChannelGoodsOrderSettleVO.class)
    )
    public AjaxResult goodsOrderSettle(@Valid @RequestBody ChannelGoodsOrderParam param) {
        Long userId = SecurityUtils.getLoginUser().getUserId();
        Long channelId = SecurityUtils.getLoginUser().getChannelId();
        Channel channel = channelService.getById(channelId);
        if (channel.getStatus() == ChannelStatusEnum.OFF) {
            return AjaxResult.error("账号异常");
        }

        ChannelGoodsOrderSettleVO orderSettleVO = new ChannelGoodsOrderSettleVO();
        // 收货地址，如果用户选了地址，则此处不做处理
        if (null == param.getAddrId() || 0 == param.getAddrId()) {
            //读取默认地址
            UserAddr addr = userAddrService.getDefaultChannelAddr(userId);
            if (null != addr) {
                orderSettleVO.setAddr(addr);
            }
        }

        Goods goods = goodsService.getById(param.getGoodsId());
        GoodsSku sku = goodsSkuService.getById(param.getSkuId());

        // 订单金额计算
        orderSettleVO.setGoodsId(goods.getGoodsId());
        orderSettleVO.setOrderNum(param.getOrderNum());
        orderSettleVO.setOrderAmt(goods.getPurchasePrice() * param.getOrderNum());

        // 结算商品信息
        List<ChannelGoods> goodsList = new ArrayList<>();
        ChannelGoods channelGoods = new ChannelGoods();
        channelGoods.setTitle(goods.getTitle());
        channelGoods.setQuantity(param.getOrderNum());
        channelGoods.setPicUrl(goods.getPicUrl());
        channelGoods.setPurchasePrice(goods.getPurchasePrice());
        channelGoods.setPurchaseCost(goods.getPurchaseCost());
        if (Objects.nonNull(sku)) {
            channelGoods.setSkuId(sku.getSkuId());
            channelGoods.setProperties(sku.getProperties());
            channelGoods.setPicUrl(sku.getPicUrl());
            channelGoods.setPurchasePrice(sku.getPurchasePrice());
            channelGoods.setPurchaseCost(sku.getPurchaseCost());
            orderSettleVO.setOrderAmt(sku.getPurchasePrice() * param.getOrderNum());
        }
        goodsList.add(channelGoods);
        orderSettleVO.setItems(goodsList);

        // 运费计算
        Integer freightAmt = 0;
        // 计算运费
        UserAddr userAddr = orderSettleVO.getAddr();
        if (Objects.nonNull(userAddr)) {
            // TODO: 4L上线需要调整,后期放开就是取的商品里配的运费模板id
            ShippingTemplateCalculateVO shippingTemplateCalculateVO = shippingTemplateRuleService.getShippingTemplateRuleByTemplateIdAndAreaInfo(shippingTemplateId, userAddr.getProvinceId(), userAddr.getCityId());
            // 无法查到运费模板则默认为0
            if (Objects.nonNull(shippingTemplateCalculateVO)) {

                orderSettleVO.setFreightRemark(shippingTemplateCalculateVO.getRemark());
                orderSettleVO.setFreightType(shippingTemplateCalculateVO.getType());

                if (ShippingTemplateRuleTypeEnum.SHIP.getValue().equals(shippingTemplateCalculateVO.getType())) {
                    // 运费计算
                    freightAmt = shippingTemplateService.calculateFreightAmt(param.getOrderNum(), shippingTemplateCalculateVO);
                }
            }
        }

        orderSettleVO.setFreightAmt(freightAmt);
        orderSettleVO.setPayAmt(orderSettleVO.getOrderAmt() + freightAmt);

        // 缓存商品订单
        redisCache.setCacheObject(RedisKey.build(RedisKey.CHANNEL_GOODS_ORDER_KEY, channelId), orderSettleVO, 10,
                TimeUnit.MINUTES);
        return AjaxResult.success(orderSettleVO);
    }

    /**
     * 提交订单
     */
    @ApiOperation("采购商品订单提交")
    @PostMapping("/goods/order/submit")
    public AjaxResult goodsOrderSubmit(@RequestBody ChannelGoodsOrder goodsOrder) {
        Long channelId = SecurityUtils.getLoginUser().getChannelId();
        Channel channel = channelService.getById(channelId);
        if (channel.getCertifyStatus() != ChannelCertifyStatusEnum.CERTIFIED) {
            LogUtil.info(logger, "账号未补充。channelId:{0}", channelId);
            return AjaxResult.error(ErrorCodeEnum.ERROR_CODE_1016);
        }
        ChannelGoodsOrderSettleVO orderSettleVO = redisCache.getCacheObject(RedisKey.build(RedisKey.CHANNEL_GOODS_ORDER_KEY, channelId));
        if (null == orderSettleVO) {
            return AjaxResult.error("订单已过期，请重新下单");
        }
        if (null == orderSettleVO.getAddr()) {
            return AjaxResult.error("收货地址缺失，请重新下单");
        }
        String orderId = channelGoodsOrderService.submitOrder(channelId, goodsOrder.getMemo(), orderSettleVO);

        // 清除缓存的订单
        redisCache.deleteObject(RedisKey.build(RedisKey.CHANNEL_GOODS_ORDER_KEY, channelId));

        return AjaxResult.success(orderId);
    }


    /**
     * 取消订单
     */
    @ApiOperation("采购商品订单取消")
    @PostMapping("/goods/order/cancel")
    public AjaxResult goodsOrderCancel(@RequestBody ChannelGoodsOrder goodsOrder) {
        Long channelId = SecurityUtils.getLoginUser().getChannelId();
        channelGoodsOrderService.cancelOrder(channelId, goodsOrder.getOrderId());
        return AjaxResult.success("取消成功");
    }


    @ApiOperation("采购商品订单支付")
    @PostMapping("/goods/order/pay")
    public AjaxResult goodsOrderPay(@Valid @RequestBody OrderPayParam param) {
        Long userId = SecurityUtils.getLoginUser().getUserId();
        SysUser sysUser = sysUserService.selectUserById(userId);
        String channelOpenId = "";
        if (StringUtils.isNotBlank(param.getOpenId())) {
            channelOpenId = param.getOpenId();
        } else {
            channelOpenId = sysUser.getChannelOpenId();
        }
        if (StringUtils.isBlank(channelOpenId)) {
            return AjaxResult.error(ErrorCodeEnum.ERROR_CODE_1005);
        }

        ChannelGoodsOrder channelGoodsOrder = channelGoodsOrderService.getById(param.getOrderId());
        JSONObject jsonObject;
        try {
            jsonObject = walletService.pay(BizTypeEnum.CHANNEL_GOODS_ORDER, param.getOrderId(), channelOpenId, channelGoodsOrder.getPayAmt(), channelGoodsOrder.getTitle(), AppSourceEnum.CHANNEL.getValue());
        } catch (ServiceException e) {
            LogUtil.error(logger, e, "门店采购商品订单创建支付单失败。userId:{0},orderId:{1}", new Object[]{userId, param.getOrderId()});
            return AjaxResult.error(e.getMessage());
        }
        return AjaxResult.success(jsonObject);
    }


    @ApiOperation("采购商品订单确认收货")
    @PostMapping("/goods/order/confirm")
    public AjaxResult goodsOrderConfirm(@RequestBody ChannelGoodsOrder goodsOrder) {
        Long channelId = SecurityUtils.getLoginUser().getChannelId();
        ChannelGoodsOrder channelGoodsOrder = channelGoodsOrderService.getById(goodsOrder.getOrderId());
        if (Objects.isNull(channelGoodsOrder)) {
            return AjaxResult.error("订单不存在");
        }
        if (!ChannelGoodsOrderStatusEnum.NOT_CONFIRM.equals(channelGoodsOrder.getStatus())) {
            return AjaxResult.error("订单状态不是待收货");
        }
        if (!channelId.equals(channelGoodsOrder.getChannelId())) {
            return AjaxResult.error("非法操作他人订单");
        }
        channelGoodsOrderService.confirmOrder(channelGoodsOrder);
        return AjaxResult.success("确认收货成功");

    }
}
