package com.yc.ship.module.trade.service.supplier.impl;


import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.yc.ship.module.trade.controller.admin.supplier.vo.SupplierRespVO;
import com.yc.ship.module.trade.controller.app.ota.vo.OtaInnerRefundVoucherVO;
import com.yc.ship.module.trade.controller.app.ota.vo.OtaVoucherVO;
import com.yc.ship.module.trade.dal.dataobject.order.TradeDetailBaseDO;
import com.yc.ship.module.trade.dal.dataobject.order.TradeDetailDO;
import com.yc.ship.module.trade.dal.dataobject.order.TradeVisitorDO;
import com.yc.ship.module.trade.dal.dataobject.refund.RefundDetailBaseDO;
import com.yc.ship.module.trade.dal.dataobject.supplier.SupplierRefundDO;
import com.yc.ship.module.trade.dal.dataobject.supplier.SupplierRetryRecordDO;
import com.yc.ship.module.trade.dal.dataobject.supplier.TradeSupplierOrderDO;
import com.yc.ship.module.trade.dal.mysql.order.TradeDetailBaseMapper;
import com.yc.ship.module.trade.dal.mysql.order.TradeVisitorMapper;
import com.yc.ship.module.trade.dal.mysql.refund.RefundDetailBaseMapper;
import com.yc.ship.module.trade.dal.mysql.supplier.SupplierRefundMapper;
import com.yc.ship.module.trade.dal.mysql.supplier.SupplierRetryRecordMapper;
import com.yc.ship.module.trade.dal.mysql.supplier.TradeSupplierOrderMapper;
import com.yc.ship.module.trade.enums.TradeOrderStatusEnum;
import com.yc.ship.module.trade.service.order.bo.TradeOrderDetailBaseBO;
import com.yc.ship.module.trade.service.order.bo.TradeVisitorBO;
import com.yc.ship.module.trade.service.refund.bo.TradeSupplierRefundBaseBO;
import com.yc.ship.module.trade.service.supplier.TradeSupplierOrderRepositoryService;
import com.yc.ship.module.trade.service.supplier.bo.SupplierTradeOrderPayRespBO;
import com.yc.ship.module.trade.service.supplier.bo.TradeSupplierOrderBO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.yc.ship.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.yc.ship.module.trade.enums.ApiConstants.INIT;
import static com.yc.ship.module.trade.enums.ErrorCodeConstants.ORDER_SAVE_EXCEPTION;
import static com.yc.ship.module.trade.enums.ErrorCodeConstants.VOUCHER_CODE_CREDENTIAL_NO_NOT_MATCH;
import static com.yc.ship.module.trade.enums.TravelhubDictTypeConstants.YES;


/**
 * &#064;Description ：订单service实现
 * &#064;Author ：qsl
 * &#064;Date ：2025/6/4 16:18
 */
@Service
@Slf4j
public class TradeSupplierOrderRepositoryServiceImpl implements TradeSupplierOrderRepositoryService {

    @Resource
    private TradeDetailBaseMapper tradeDetailBaseMapper;
    @Resource
    private TradeSupplierOrderMapper tradeSupplierOrderMapper;
    @Resource
    private TradeVisitorMapper tradeVisitorMapper;
    @Resource
    private SupplierRefundMapper supplierRefundMapper;
    @Resource
    private RefundDetailBaseMapper refundDetailBaseMapper;
    @Resource
    private SupplierRetryRecordMapper supplierRetryRecordMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveOrder(List<TradeSupplierOrderBO> tradeSupplierOrderBOList) {
        try {
            //创建分销订单
            tradeSupplierOrderBOList.forEach(tradeSupplierOrderBO -> {
                tradeSupplierOrderMapper.insert(tradeSupplierOrderBO.getTradeSupplierOrderDO());
                //更新
                List<TradeDetailBaseDO> updateDetailBaseList = tradeSupplierOrderBO.getTradeDetailBaseDOList().stream().map(tradeDetailBaseDO -> {
                    TradeDetailBaseDO detailBaseDO = new TradeDetailBaseDO();
                    detailBaseDO.setId(tradeDetailBaseDO.getId());
                    detailBaseDO.setPlatSupplierOrderId(tradeSupplierOrderBO.getTradeSupplierOrderDO().getId());
                    return detailBaseDO;
                }).collect(Collectors.toList());

                tradeDetailBaseMapper.updateBatch(updateDetailBaseList);
            });

        }catch (Exception e){
            log.error("供应商订单保存异常",e);
            throw exception(ORDER_SAVE_EXCEPTION);
        }
    }

    @Override
    public void updateOrderStatus(TradeSupplierOrderDO tradeSupplierOrderDO) {
        //订单状态
        LambdaUpdateWrapper<TradeSupplierOrderDO> orderUpdateWrapper = new LambdaUpdateWrapper<TradeSupplierOrderDO>()
                .set(TradeSupplierOrderDO::getOrderStatus,tradeSupplierOrderDO.getOrderStatus())
                .eq(TradeSupplierOrderDO::getId,tradeSupplierOrderDO.getId());
        tradeSupplierOrderMapper.update(orderUpdateWrapper);
    }

    @Override
    public void updateAfterOrderSuccess(TradeSupplierOrderDO tradeSupplierOrderDO) {
        LambdaUpdateWrapper<TradeSupplierOrderDO> orderUpdateWrapper = new LambdaUpdateWrapper<TradeSupplierOrderDO>()
                .set(TradeSupplierOrderDO::getOrderStatus,tradeSupplierOrderDO.getOrderStatus())
                .set(TradeSupplierOrderDO::getSupplierOrderNo,tradeSupplierOrderDO.getSupplierOrderNo())
                .eq(TradeSupplierOrderDO::getId,tradeSupplierOrderDO.getId());
        tradeSupplierOrderMapper.update(orderUpdateWrapper);
    }

    @Override
    public List<TradeVisitorDO> getVisitorListBySupplierOrder(Long platSupplierOrderId) {

        return tradeVisitorMapper.selectVisitorListBySupplierOrder(platSupplierOrderId);
    }

    @Override
    public List<TradeOrderDetailBaseBO> getNeedSupplierOrderList(Long orderId) {
        return tradeDetailBaseMapper.selectNeedSupplierOrderList(orderId);
    }

    @Override
    public List<TradeDetailBaseDO> getBaseListFromOrder(Long orderId, TradeOrderDetailBaseBO baseBO) {
        return tradeDetailBaseMapper.selectBaseListFromOrder(orderId,baseBO);
    }

    @Override
    public List<TradeDetailBaseDO> getDistinctBaseListBySupplierOrderId(Long platSupplierOrderId) {
        return tradeDetailBaseMapper.selectDistinctBaseListBySupplierOrderId(platSupplierOrderId);
    }

    @Override
    public List<TradeDetailBaseDO> selectBaseListBySupplierOrderNo(String platSupplierOrderNo) {
        return tradeDetailBaseMapper.selectBaseListBySupplierOrderNo(platSupplierOrderNo);
    }

    @Override
    public List<TradeDetailDO> getDistinctDetailListBySupplierOrderId(Long platSupplierOrderId) {
        return tradeDetailBaseMapper.getDistinctDetailListBySupplierOrderId(platSupplierOrderId);
    }

    @Override
    public List<TradeVisitorDO> getVisitorListBySpecType(Long platSupplierOrderId, String specType, List<Long> baseList) {
        return tradeVisitorMapper.selectVisitorListBySpecType(platSupplierOrderId,specType,baseList);
    }

    @Override
    public Integer getCountBySpecType(Long platSupplierOrderId, String specType) {
        return tradeDetailBaseMapper.selectCountBySpecType(platSupplierOrderId,specType);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateAfterPaySuccess(SupplierTradeOrderPayRespBO respBO, TradeSupplierOrderDO tradeSupplierOrderDO) {
        //更新供应商订单为出票成功，基础票更新供应商券码
        tradeSupplierOrderDO.setOrderStatus(TradeOrderStatusEnum.UNUSED.getStatus());
        if(StrUtil.isBlank(tradeSupplierOrderDO.getSupplierOrderNo())){
            //如果下单没返回供应商订单号，支付的时候保存
            tradeSupplierOrderDO.setSupplierOrderNo(respBO.getSupplierOrderNo());
            updateAfterOrderSuccess(tradeSupplierOrderDO);
        }else {
            updateOrderStatus(tradeSupplierOrderDO);
        }

        //更新券码
        ///实名，根据身份证、或者otaDetailId匹配
        if(tradeSupplierOrderDO.getUseRealName() == YES){
            List<TradeVisitorDO> tradeVisitorDOList = getVisitorListBySupplierOrder(tradeSupplierOrderDO.getId());
            Map<Long,List<TradeVisitorDO>> groupMap;
            if(tradeSupplierOrderDO.getQuantityOfOne() > 1){
                //一票多人,任意匹配
                groupMap = tradeVisitorDOList.stream().collect(Collectors.groupingBy(TradeVisitorDO::getDetailId));

            } else {
                groupMap = new HashMap<>();
            }
            List<OtaVoucherVO> voucherVOList = respBO.getVoucherList();
            voucherVOList.forEach(voucher->{
                if(StrUtil.isNotBlank(voucher.getOtaDetailId())){
                    //根据otaDetailId匹配
                    updateDetailBaseVoucher(voucher.getVoucherCode(),Long.parseLong(voucher.getOtaDetailId()),tradeSupplierOrderDO.getId());
                }else{
                    //根据证件匹配
                    if(tradeSupplierOrderDO.getQuantityOfOne() > 1){
                        //一票多人,任意匹配
                        Map.Entry<Long, List<TradeVisitorDO>> first = groupMap.entrySet().stream().filter(map -> {
                            return map.getValue().stream().anyMatch(item -> ObjectUtil.equal(item.getCredentialNo(), voucher.getCredentialNo()));
                        }).findFirst().orElseThrow(()-> exception(VOUCHER_CODE_CREDENTIAL_NO_NOT_MATCH,voucher.getVoucherCode(),voucher.getCredentialNo()));

                        updateDetailBaseVoucher(voucher.getVoucherCode(),first.getKey(), tradeSupplierOrderDO.getId());
                        groupMap.remove(first.getKey());
                    }else{
                        TradeVisitorDO first = tradeVisitorDOList.stream().filter(item -> ObjectUtil.equal(item.getCredentialNo(), voucher.getCredentialNo()))
                                .findFirst().orElseThrow(()-> exception(VOUCHER_CODE_CREDENTIAL_NO_NOT_MATCH,voucher.getVoucherCode(),voucher.getCredentialNo()));
                        updateDetailBaseVoucher(voucher.getVoucherCode(),first.getDetailId(), tradeSupplierOrderDO.getId());
                        tradeVisitorDOList.remove(first);
                    }
                }
            });
        }else{
            //非实名
            List<OtaVoucherVO> voucherVOList = respBO.getVoucherList();
            boolean hasOtaDetailId = voucherVOList.stream().allMatch(item->StrUtil.isNotBlank(item.getOtaDetailId()));
            if(hasOtaDetailId){
                //根据otaDetailId匹配
                voucherVOList.forEach(voucher->{
                    if(StrUtil.isNotBlank(voucher.getOtaDetailId())){
                        //根据otaDetailId匹配
                        updateDetailBaseVoucher(voucher.getVoucherCode(),Long.parseLong(voucher.getOtaDetailId()),tradeSupplierOrderDO.getId());
                    }
                });
            }else{
                //随机分配
                List<Long> detailIdList = tradeDetailBaseMapper.selectDetailIdByPlatSupplierId(tradeSupplierOrderDO.getId());
                for (int i = 0; i < detailIdList.size(); i++) {
                    updateDetailBaseVoucher(respBO.getVoucherList().get(i).getVoucherCode(),detailIdList.get(i),tradeSupplierOrderDO.getId());
                }
            }

        }
    }

    /**
     * 获取供应商订单列表
     * @param orderId
     * @return
     */
    @Override
    public List<TradeSupplierOrderDO> getTradeSupplierOrderList(Long orderId) {
        return tradeSupplierOrderMapper.selectList(TradeSupplierOrderDO::getOrderId,orderId);
    }

    @Override
    public List<SupplierRefundDO> getSupplierOrderToCreateRefund(Long refundId, Integer supplierOrderStatus) {
        return supplierRefundMapper.selectSupplierOrderToCreateRefund(refundId,supplierOrderStatus);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveSupplierRefundOrder(List<SupplierRefundDO> supplierRefundDOList) {
        supplierRefundMapper.insertBatch(supplierRefundDOList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateSupplierRefundDetailBase(List<SupplierRefundDO> supplierRefundDOList) {
        for (SupplierRefundDO supplierRefundDO : supplierRefundDOList) {
            LambdaUpdateWrapper<RefundDetailBaseDO> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.set(RefundDetailBaseDO::getPlatSupplierRefundId,supplierRefundDO.getId())
                    .eq(RefundDetailBaseDO::getRefundId,supplierRefundDO.getRefundId())
                    .eq(RefundDetailBaseDO::getPlatSupplierOrderId,supplierRefundDO.getPlatSupplierOrderId());
            refundDetailBaseMapper.update(updateWrapper);
        }
    }

    @Override
    public List<String> getVoucherListByPlatSupplierRefundId(Long platSupplierRefundId) {
        List<RefundDetailBaseDO> refundDetailBaseDOList = refundDetailBaseMapper.selectList(RefundDetailBaseDO::getPlatSupplierRefundId, platSupplierRefundId);
        return refundDetailBaseDOList.stream().map(RefundDetailBaseDO::getSupplierVoucherCode).distinct().collect(Collectors.toList());
    }

    @Override
    public List<OtaInnerRefundVoucherVO> getVoucherAndBaseListByPlatSupplierRefundId(Long platSupplierRefundId) {
        return refundDetailBaseMapper.selectPlatSupplierRefundVoucherList(platSupplierRefundId);
    }

    @Override
    public void updateRefundStatus(SupplierRefundDO refundDO) {
        LambdaUpdateWrapper<SupplierRefundDO> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(SupplierRefundDO::getRefundStatus,refundDO.getRefundStatus())
                .eq(SupplierRefundDO::getId,refundDO.getId());
        if(refundDO.getRefundTime() !=null){
            updateWrapper.set(SupplierRefundDO::getRefundTime,refundDO.getRefundTime());
        }
        if(StrUtil.isNotBlank(refundDO.getSupplierRefundNo())){
            updateWrapper.set(SupplierRefundDO::getSupplierRefundNo,refundDO.getSupplierRefundNo());
        }
        if(StrUtil.isNotBlank(refundDO.getErrorMsg())){
            updateWrapper.set(SupplierRefundDO::getErrorMsg,refundDO.getErrorMsg());
        }
        if(refundDO.getRetryCount() !=null ){
            updateWrapper.set(SupplierRefundDO::getRetryCount,refundDO.getRetryCount());
        }
        supplierRefundMapper.update(updateWrapper);
    }

    @Override
    public TradeSupplierOrderDO getById(Long supplierOrderId) {
        return tradeSupplierOrderMapper.selectById(supplierOrderId);
    }

    @Override
    public SupplierRetryRecordDO addRetryRecord(Long bizId, Integer bizType) {
        SupplierRetryRecordDO supplierRetryRecordDO = new SupplierRetryRecordDO();
        supplierRetryRecordDO.setId(IdWorker.getId());
        supplierRetryRecordDO.setSupplierBizId(bizId);
        supplierRetryRecordDO.setBizType(bizType);
        supplierRetryRecordDO.setStatus(INIT);
        supplierRetryRecordMapper.insert(supplierRetryRecordDO);

        return supplierRetryRecordDO;
    }

    @Override
    public void updateRetryRecord(SupplierRetryRecordDO supplierRetryRecordDO) {
        supplierRetryRecordMapper.updateById(supplierRetryRecordDO);
    }

    @Override
    public SupplierRefundDO getSupplierRefundById(Long supplierRefundId) {
        return supplierRefundMapper.selectById(supplierRefundId);
    }

    @Override
    public Map<String, Long> getSupplierOrderSuccessCount(Long orderId) {
        return tradeSupplierOrderMapper.selectSupplierOrderSuccessCount(orderId);
    }

    @Override
    public List<TradeSupplierOrderDO> getUnPaySuccessOrder(Long orderId) {
        LambdaQueryWrapper<TradeSupplierOrderDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(TradeSupplierOrderDO::getOrderStatus,TradeOrderStatusEnum.UNPAID.getStatus(),TradeOrderStatusEnum.PROCESS_FAIL.getStatus());
        queryWrapper.eq(TradeSupplierOrderDO::getOrderId,orderId);
        return tradeSupplierOrderMapper.selectList(queryWrapper);
    }

    @Override
    public List<TradeSupplierOrderDO> getSupplierOrderIdBySupplierOrderNo(String supplierOrderNo) {
        LambdaQueryWrapper<TradeSupplierOrderDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TradeSupplierOrderDO::getSupplierOrderNo,supplierOrderNo);
        return tradeSupplierOrderMapper.selectList(queryWrapper);
    }

    @Override
    public List<TradeVisitorBO> getSupplierVisitor(Long platSupplierOrderId, List<Long> visitorIdList) {
        return tradeVisitorMapper.selectSupplierVisitor(platSupplierOrderId,visitorIdList);
    }

    @Override
    public List<Map<String, Object>> getPlatformOrderList(Long orderId) {
        return tradeSupplierOrderMapper.getPlatformOrderList(orderId);
    }

    private void updateDetailBaseVoucher(String voucherCode,Long detailId,Long platSupplierOrderId){
        LambdaUpdateWrapper<TradeDetailBaseDO> updateWrapper = new LambdaUpdateWrapper<TradeDetailBaseDO>()
                .set(TradeDetailBaseDO::getSupplierVoucherCode,voucherCode)
                .eq(TradeDetailBaseDO::getDetailId,detailId)
                .eq(TradeDetailBaseDO::getPlatSupplierOrderId,platSupplierOrderId);
        tradeDetailBaseMapper.update(updateWrapper);
    }


    @Override
    public List<TradeDetailBaseDO> getTradeBaseListByPlatSupplierOrderId(Long platSupplierOrderId) {
        LambdaQueryWrapper<TradeDetailBaseDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TradeDetailBaseDO::getPlatSupplierOrderId,platSupplierOrderId);
        return tradeDetailBaseMapper.selectList(queryWrapper);
    }


    @Override
    public List<TradeSupplierRefundBaseBO> getRefundDetailBaseBOList(Long supplierRefundId){
        return refundDetailBaseMapper.selectRefundDetailBaseBOList(supplierRefundId);
    }

    @Override
    public void updateOrderPayStatus(TradeSupplierOrderDO tradeSupplierOrderDO) {
        //订单状态
        LambdaUpdateWrapper<TradeSupplierOrderDO> orderUpdateWrapper = new LambdaUpdateWrapper<TradeSupplierOrderDO>()
                .set(TradeSupplierOrderDO::getPayStatus,tradeSupplierOrderDO.getPayStatus())
                .eq(TradeSupplierOrderDO::getId,tradeSupplierOrderDO.getId());
        tradeSupplierOrderMapper.update(orderUpdateWrapper);
    }

    @Override
    public TradeSupplierOrderDO getSupplierOrderByChange(Long orderId, String supplierProductId, Long supplierId) {
        LambdaQueryWrapper<TradeSupplierOrderDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TradeSupplierOrderDO::getOrderId,orderId);
        queryWrapper.eq(TradeSupplierOrderDO::getSupplierProductId,supplierProductId);
        queryWrapper.eq(TradeSupplierOrderDO::getSupplierId,supplierId);
        return tradeSupplierOrderMapper.selectOne(queryWrapper);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateAddSupplierOrder(TradeSupplierOrderDO tradeSupplierOrderDO, TradeSupplierOrderDO mainSupplierOrderDO){
        LambdaUpdateWrapper<TradeDetailBaseDO> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(TradeDetailBaseDO::getPlatSupplierOrderId,tradeSupplierOrderDO.getId());
        updateWrapper.set(TradeDetailBaseDO::getPlatSupplierOrderId,mainSupplierOrderDO.getId());
        tradeDetailBaseMapper.update(updateWrapper);

        LambdaUpdateWrapper<TradeSupplierOrderDO> updateSupplierWrapper = new LambdaUpdateWrapper<>();
        updateSupplierWrapper.eq(TradeSupplierOrderDO::getId,mainSupplierOrderDO.getId());
        updateSupplierWrapper.set(TradeSupplierOrderDO::getAmount,mainSupplierOrderDO.getAmount().add(tradeSupplierOrderDO.getAmount()));
        updateSupplierWrapper.set(TradeSupplierOrderDO::getQuantity, NumberUtil.add(tradeSupplierOrderDO.getQuantity(),mainSupplierOrderDO.getQuantity()));
        tradeSupplierOrderMapper.update(updateSupplierWrapper);

        tradeSupplierOrderMapper.deleteOrderById(tradeSupplierOrderDO.getId());
    }

    @Override
    public List<SupplierRefundDO> getSupplierRefundListByRefundId(Long refundId) {
        LambdaQueryWrapper<SupplierRefundDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SupplierRefundDO::getRefundId,refundId);
        return supplierRefundMapper.selectList(queryWrapper);
    }
    @Override
    public List<SupplierRespVO> selectSupplierByUserId(Long userId) {
        return tradeSupplierOrderMapper.selectSupplierByUserId(userId);
    }
}
