package com.yiqi.admin.controller.core;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.yiqi.app.domain.AppUser;
import com.yiqi.app.service.IAppUserService;
import com.yiqi.common.enums.*;
import com.yiqi.common.exception.ServiceException;
import com.yiqi.common.config.SystemEnvConfig;
import com.yiqi.common.constant.UrlConstants;
import com.yiqi.common.core.controller.BaseController;
import com.yiqi.common.core.domain.R;
import com.yiqi.common.utils.DateUtils;
import com.yiqi.common.utils.SecurityUtils;
import com.yiqi.common.utils.StringUtils;
import com.yiqi.core.domain.dto.wx.*;
import com.yiqi.core.domain.vo.wx.*;
import com.yiqi.core.service.ISysStoreIntracityExpressService;
import com.yiqi.order.domain.OrderCloth;
import com.yiqi.order.domain.OrderDelivery;
import com.yiqi.order.service.IOrderClothService;
import com.yiqi.order.service.IOrderDeliveryService;
import com.yiqi.system.domain.SysStore;
import com.yiqi.system.service.ISysStoreService;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

/**
 * @author xiaohei
 * @date 2024/2/1
 */
@RestController
@RequestMapping(value = UrlConstants.managerApi + "/store/intracity/express")
public class SysStoreIntracityExpressController extends BaseController {

    @Autowired
    private ISysStoreIntracityExpressService sysStoreIntracityExpressService;
    @Autowired
    private ISysStoreService sysStoreService;
    @Autowired
    private IOrderClothService orderClothService;
    @Autowired
    private IOrderDeliveryService orderDeliveryService;
    @Autowired
    private IAppUserService appUserService;

    /**
     * 创建微信同城配送门店
     *
     * @param intracityExpressCreateStoreRequest
     * @return
     * @throws Exception
     */
    @ApiOperation("创建微信同城配送门店")
    @PostMapping(value = "createStore")
    public R<IntracityExpressCreateStoreResult> createStore(@RequestBody IntracityExpressCreateStoreRequest intracityExpressCreateStoreRequest)
            throws Exception {
        return R.ok(sysStoreIntracityExpressService.createStore(intracityExpressCreateStoreRequest));
    }


    /**
     * 获取微信同城配送门店详情
     *
     * @param intracityExpressStoreInfoRequest
     * @return
     * @throws Exception
     */
    @ApiOperation("获取微信同城配送门店详情")
    @PostMapping(value = "getStoreInfo")
    public R<IntracityExpressStoreInfoResult> getStoreInfo(@RequestBody IntracityExpressStoreInfoRequest intracityExpressStoreInfoRequest)
            throws Exception {
        return R.ok(sysStoreIntracityExpressService.getStoreInfo(intracityExpressStoreInfoRequest));
    }

    /**
     * 修改微信同城配送门店信息
     *
     * @param intracityExpressStoreUpdateRequest
     * @return
     * @throws Exception
     */
    @ApiOperation("修改微信同城配送门店信息")
    @PostMapping(value = "updateStore")
    public R<IntracityExpressBaseResult> updateStore(@RequestBody IntracityExpressStoreUpdateRequest intracityExpressStoreUpdateRequest)
            throws Exception {
        return R.ok(sysStoreIntracityExpressService.updateStore(intracityExpressStoreUpdateRequest));
    }

    @ApiOperation("查询门店余额")
    @GetMapping(value = "getStoreBalance")
    public R<IntracityExpressStoreBalanceInfoResult> getStoreBalance() throws Exception {
        SysStore sysStore = sysStoreService.getById(SecurityUtils.getLoginUser().getOrgId());
        if (sysStore == null) {
            throw new ServiceException("未查询到门店");
        }
        if (StringUtils.isEmpty(sysStore.getWxStoreId())) {
            throw new ServiceException("未配置微信门店，请联系管理员进行配置");
        }
        IntracityExpressStoreBalanceInfoRequest request = new IntracityExpressStoreBalanceInfoRequest();
        request.setWx_store_id(sysStore.getWxStoreId());
        return R.ok(sysStoreIntracityExpressService.getStoreBalance(request));
    }

//    @ApiOperation("门店充值余额")
//    @PostMapping(value = "storeBalanceCharge")
//    public R<IntracityExpressStoreBalanceChargeResult> storeBalanceCharge(@RequestBody IntracityExpressStoreBalanceChargeRequest request) throws Exception{
//        return R.ok(sysStoreIntracityExpressService.storeBalanceCharge(request));
//    }

    @ApiOperation("门店流水查询")
    @GetMapping(value = "queryFlow")
    public R<IntracityExpressQueryFlowResult> queryFlow(@RequestParam @ApiParam("1:充值流水， 2:消费流水，3:退款流水") Integer flow_type
            , @RequestParam @ApiParam("查询日期") String searchDate) throws Exception {
        SysStore sysStore = sysStoreService.getById(SecurityUtils.getLoginUser().getOrgId());
        if (sysStore == null) {
            throw new ServiceException("未查询到门店");
        }
        if (StringUtils.isEmpty(sysStore.getWxStoreId())) {
            throw new ServiceException("未配置微信门店，请联系管理员进行配置");
        }
        IntracityExpressQueryFlowRequest request = new IntracityExpressQueryFlowRequest();
        request.setWx_store_id(sysStore.getWxStoreId());
        request.setFlow_type(flow_type);
        request.setBegin_time((int) (DateUtils.strToDate(searchDate).getTime() / 1000));
        request.setEnd_time((int) (DateUtils.strToDate(searchDate).getTime() / 1000 + 24 * 3600));
        return R.ok(sysStoreIntracityExpressService.queryFlow(request));
    }

    @ApiOperation("充值余额")
    @GetMapping(value = "chargeBalance")
    public R<IntracityExpressStoreBalanceChargeResult> chargeBalance(@RequestParam String service_trans_id
            , @RequestParam Integer amount) throws Exception {
        SysStore sysStore = sysStoreService.getById(SecurityUtils.getLoginUser().getOrgId());
        if (sysStore == null) {
            throw new ServiceException("未查询到门店");
        }
        if (StringUtils.isEmpty(sysStore.getWxStoreId())) {
            throw new ServiceException("未配置微信门店，请联系管理员进行配置");
        }
        IntracityExpressStoreBalanceChargeRequest request = new IntracityExpressStoreBalanceChargeRequest();
        request.setWx_store_id(sysStore.getWxStoreId());
        request.setService_trans_id(service_trans_id);
        request.setAmount(amount * 100);
        return R.ok(sysStoreIntracityExpressService.storeBalanceCharge(request));
    }

    @ApiOperation("查询支持同城配送的城市")
    @PostMapping(value = "getCity")
    public R<IntracityExpressGetCityResult> getCity(@RequestBody IntracityExpressGetCityRequest request) throws Exception {
        return R.ok(sysStoreIntracityExpressService.getCity(request));
    }

    @ApiOperation("获取同城配送预估价格")
    @GetMapping(value = "getExpressPrice")
    public R getExpressPrice(@RequestParam @ApiParam("订单编号") String orderNo) throws Exception {
        SysStore sysStore = sysStoreService.getById(SecurityUtils.getLoginUser().getOrgId());
        if (sysStore == null) {
            throw new ServiceException("未查询到门店");
        }
        if (StringUtils.isEmpty(sysStore.getWxStoreId())) {
            throw new ServiceException("未配置微信门店，请联系管理员进行配置");
        }
        OrderCloth orderCloth = orderClothService.getOne(new QueryWrapper<OrderCloth>().lambda()
                .eq(OrderCloth::getOrderNo, orderNo)
                .eq(OrderCloth::getOrgId, SecurityUtils.getLoginUser().getOrgId())
                .eq(OrderCloth::getSourceType, SecurityUtils.getLoginUser().getSourceType()));
        if (orderCloth == null) {
            throw new ServiceException("未查询到订单");
        }

        IntracityExpressPreAddOrderRequest request = new IntracityExpressPreAddOrderRequest();
        request.setCargo_name("衣物");
        request.setCargo(new IntracityExpressPreAddOrderRequest
                .CargoInfo("衣物", orderCloth.getAppointmentCount() / 5 + 1
                , 1000, orderCloth.getAppointmentCount()));
        request.setUser_sandbox(SystemEnv.PROD.getCode().equals(SystemEnvConfig.env) ? 0 : 1);

        if (orderCloth.getOrderStatus().equals(ClothOrderStatusType.APPOINTMENT.getCode())) {
            throw new ServiceException("同城配送暂不支持上门取件");
        } else if (orderCloth.getOrderStatus().equals(ClothOrderStatusType.WAITING_TO_SEND.getCode())) {
            //同城配送订单只能由商家地址发货
            OrderDelivery orderDelivery
                    = orderDeliveryService.getOne(new QueryWrapper<OrderDelivery>().lambda()
                    .eq(OrderDelivery::getOrderSn, orderNo)
                    .eq(OrderDelivery::getClothOrderType, ClothOrderDeliveryType.collectCloth.getCode()));
            if (orderDelivery == null) {
                throw new ServiceException("未查询到收衣配送信息");
            }
            request.setWx_store_id(sysStore.getWxStoreId());
            // 查询顾客信息
            AppUser appUser = appUserService.getOne(new QueryWrapper<AppUser>().lambda().eq(AppUser::getId, orderDelivery.getAppUserId()));
            request.setUser_name(appUser.getNickName());
            request.setUser_phone(orderDelivery.getUserPhone());
            request.setUser_address(orderDelivery.getUserAddress());
            request.setUser_lat(Double.parseDouble(orderDelivery.getUserLat()));
            request.setUser_lng(Double.parseDouble(orderDelivery.getUserLng()));
            return R.ok(sysStoreIntracityExpressService.preAddOrder(request));
        } else {
            throw new ServiceException("订单状态不正确");
        }
    }

    @ApiOperation("取消订单")
    @GetMapping(value = "cancel")
    public R cancel(@RequestParam String orderNo) throws Exception {
        SysStore sysStore = sysStoreService.getById(SecurityUtils.getLoginUser().getOrgId());
        if (sysStore == null) {
            throw new ServiceException("未查询到门店");
        }
        if (StringUtils.isEmpty(sysStore.getWxStoreId())) {
            throw new ServiceException("未配置微信门店，请联系管理员进行配置");
        }
        IntracityExpressCancelOrderRequest request = new IntracityExpressCancelOrderRequest();
        request.setWx_store_id(sysStore.getWxStoreId());
        request.setStore_order_id(orderNo);
        return R.ok(sysStoreIntracityExpressService.cancelOrder(request));
    }

    @ApiOperation("获取配送单明细")
    @GetMapping(value = "getOrderInfo")
    public R<IntracityExpressOrderInfoResult> getOrderInfo(@RequestParam @ApiParam("订单编号") String orderNo
            , @RequestParam @ApiParam("0:收衣，1：取衣") String deliveryType) throws Exception {
        SysStore sysStore = sysStoreService.getById(SecurityUtils.getLoginUser().getOrgId());
        if (sysStore == null) {
            throw new ServiceException("未查询到门店");
        }
        if (StringUtils.isEmpty(sysStore.getWxStoreId())) {
            throw new ServiceException("未配置微信门店，请联系管理员进行配置");
        }
        OrderCloth orderCloth = orderClothService.getOne(new QueryWrapper<OrderCloth>().lambda()
                .eq(OrderCloth::getOrderNo, orderNo)
                .eq(OrderCloth::getOrgId, SecurityUtils.getLoginUser().getOrgId())
                .eq(OrderCloth::getSourceType, SecurityUtils.getLoginUser().getSourceType()));
        if (orderCloth == null) {
            throw new ServiceException("未查询到订单");
        }

        OrderDelivery orderDelivery = orderDeliveryService.getOne(
                new QueryWrapper<OrderDelivery>().lambda()
                        .eq(OrderDelivery::getOrderSn, orderCloth.getOrderNo())
                        .eq(OrderDelivery::getClothOrderType, deliveryType));
        if (orderDelivery == null) {
            throw new ServiceException("未查询到配送订单");
        }
        if (!orderDelivery.getDeliveryWay().equals(ClothOrderDeliveryWay.intracityExpress.getCode())) {
            throw new ServiceException("该配送不是同城配送，无法查询");
        }
        IntracityExpressOrderInfoRequest request = new IntracityExpressOrderInfoRequest();
        request.setWx_store_id(sysStore.getWxStoreId());
        request.setStore_order_id(orderDelivery.getDeliverySn());
        IntracityExpressOrderInfoResult result = sysStoreIntracityExpressService.getOrderInfo(request);
        return R.ok(result);
    }

    @ApiOperation("模拟订单状态回调")
    @PostMapping(value = "mocknotify")
    public R<IntracityExpressBaseResult> mocknotify(IntracityExpressMockNotifyRequest request) throws Exception {
        return R.ok(sysStoreIntracityExpressService.mocknotify(request));
    }

    @ApiOperation("配送订单状态通知回调")
    @PostMapping(value = "statusChange")
    public IntracityExpressOrderStatusChangeVO statusChange(
            @RequestBody IntracityExpressOrderStatusChangeDTO intracityExpressOrderStatusChangeDTO) throws Exception {
        logger.info("api statusChange");
        logger.info("params:" + JSON.toJSONString(intracityExpressOrderStatusChangeDTO));
        OrderDelivery orderDelivery = orderDeliveryService.getOne(
                new QueryWrapper<OrderDelivery>().lambda()
                        .eq(OrderDelivery::getTransOrderId, intracityExpressOrderStatusChangeDTO.getStore_order_id()));
        if (orderDelivery == null) {
            throw new ServiceException("未查询到配送信息");
        }
        OrderCloth orderCloth = orderClothService.getOne(
                new QueryWrapper<OrderCloth>().lambda().eq(OrderCloth::getOrderNo, orderDelivery.getOrderSn()));
        if (orderCloth == null) {
            throw new ServiceException("未查询到洗衣订单");
        }
        switch (intracityExpressOrderStatusChangeDTO.getOrder_status()) {
            case 10000:
                // 订单创建成功
                this.updateSending(orderCloth, orderDelivery);
                orderDelivery.setDeliveryStatus(OrderDeliveryStatusEnum.CREATE_ORDER_SUCCESS.getCode());
                break;
            case 20000:
                // 商家取消订单
                this.updateCancel(orderCloth, orderDelivery);
                orderDelivery.setDeliveryStatus(OrderDeliveryStatusEnum.STORE_CANCEL.getCode());
                break;
            case 20001:
                // 配送方取消订单
                this.updateCancel(orderCloth, orderDelivery);
                orderDelivery.setDeliveryStatus(OrderDeliveryStatusEnum.DELIVERY_CANCEL.getCode());
                break;
            case 30000:
                // 配送员接单
                this.updateSending(orderCloth, orderDelivery);
                orderDelivery.setDeliveryStatus(OrderDeliveryStatusEnum.RECEIVE_ORDER.getCode());
                break;
            case 40000:
                // 配送员到店
                this.updateSending(orderCloth, orderDelivery);
                orderDelivery.setDeliveryStatus(OrderDeliveryStatusEnum.SENDING.getCode());
                break;
            case 50000:
                // 配送中
                this.updateSending(orderCloth, orderDelivery);
                orderDelivery.setDeliveryStatus(OrderDeliveryStatusEnum.SENDING.getCode());
                break;
            case 60000:
                // 配送员撤单
                this.updateCancel(orderCloth, orderDelivery);
                orderDelivery.setDeliveryStatus(OrderDeliveryStatusEnum.SENDER_CANCEL.getCode());
                break;
            case 70000:
                // 配送完成
                this.updateSuccess(orderCloth, orderDelivery);
                orderDelivery.setDeliveryStatus(OrderDeliveryStatusEnum.SEND_FINISH.getCode());
                break;
            case 90000:
                // 配送异常
                break;
        }
        orderDelivery.setDeliveryStatusMsg(OrderDeliveryStatusEnum.getLabelByCode(String.valueOf(intracityExpressOrderStatusChangeDTO.getOrder_status())));
        orderDeliveryService.updateById(orderDelivery);
        return new IntracityExpressOrderStatusChangeVO();
    }

    private void updateCancel(OrderCloth orderCloth, OrderDelivery orderDelivery) {
        if (orderCloth.getOrderStatus().equals(ClothOrderStatusType.SENDING.getCode())) {
            orderClothService.update(new UpdateWrapper<OrderCloth>().lambda()
                    .set(OrderCloth::getOrderStatus, ClothOrderStatusType.WAITING_TO_SEND.getCode())
                    .eq(OrderCloth::getId, orderCloth.getId()));
        }
    }

    private void updateSuccess(OrderCloth orderCloth, OrderDelivery orderDelivery) {
        if (orderDelivery.getClothOrderType().equals(ClothOrderDeliveryType.takeCloth.getCode())
                && orderCloth.getOrderStatus().equals(ClothOrderStatusType.SENDING.getCode())) {
            orderClothService.update(new UpdateWrapper<OrderCloth>().lambda()
                    .set(OrderCloth::getOrderStatus, ClothOrderStatusType.FINISH.getCode())
                    .eq(OrderCloth::getId, orderCloth.getId()));
        }
    }

    private void updateSending(OrderCloth orderCloth, OrderDelivery orderDelivery) {
        if (orderDelivery.getClothOrderType().equals(ClothOrderDeliveryType.takeCloth.getCode())
                && orderCloth.getOrderStatus().equals(ClothOrderStatusType.WAITING_TO_SEND.getCode())) {
            orderClothService.update(new UpdateWrapper<OrderCloth>().lambda()
                    .set(OrderCloth::getOrderStatus, ClothOrderStatusType.SENDING.getCode())
                    .eq(OrderCloth::getId, orderCloth.getId()));
        }
    }
}
