package com.sckw.payment.service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sckw.core.exception.BusinessException;
import com.sckw.core.model.vo.TableTop;
import com.sckw.core.utils.StringTimeUtil;
import com.sckw.core.web.context.LoginUserHolder;
import com.sckw.payment.dao.KwpSettlementLogisticsMapper;
import com.sckw.payment.model.KwpSettlementLogistics;
import com.sckw.payment.model.constant.LogisticsUnitType;
import com.sckw.payment.model.constant.SettlementEnum;
import com.sckw.payment.model.dto.SettlementLogisticsDto;
import com.sckw.payment.model.vo.req.SettlementReq;
import com.sckw.payment.model.vo.res.SettlementLogisticsStatusCountVo;
import com.sckw.payment.model.vo.res.SettlementLogisticsSumVo;
import com.sckw.payment.utils.CommonValidator;
import com.sckw.payment.utils.PageMoreRes;
import com.sckw.system.api.RemoteSystemService;
import com.sckw.system.api.model.dto.res.UserCacheResDto;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

/**
 * @author Aick Spt
 * @date 2023-07-10 16:38:36
 */
@AllArgsConstructor
@Service
@Slf4j
public class KwpSettlementLogisticsService {
    @DubboReference(version = "2.0.0", group = "design", check = false)
    private RemoteSystemService remoteSystemService;
    private final KwpSettlementLogisticsMapper settlementLogisticsMapper;

    public void save(KwpSettlementLogistics settlementLogistics) {
        settlementLogisticsMapper.insert(settlementLogistics);
    }

    /**
     * 运费收款-物流订单各状态列表总数
     *
     * @author Aick Spt
     * @date 2023-07-24 16:21
     */
    public List<TableTop> getCountListCollection(SettlementReq settlementReq) {
        settlementReq.setUnitType(LogisticsUnitType.SHIPPER);
        return getCountList(settlementReq);
    }

    /**
     * 运费付款-物流订单各状态列表总数
     *
     * @author Aick Spt
     * @date 2023-07-24 16:23
     */
    public List<TableTop> getCountListPayment(SettlementReq settlementReq) {
        settlementReq.setUnitType(LogisticsUnitType.CARRIER);
        return getCountList(settlementReq);
    }

    /**
     * 运费收款-物流订单列表
     *
     * @author Aick Spt
     * @date 2023-07-24 16:21
     */
    public PageMoreRes<SettlementLogisticsDto> pageSelectCollection(SettlementReq settlementReq) {
        settlementReq.setUnitType(LogisticsUnitType.SHIPPER);
        return pageSelect(settlementReq);
    }

    /**
     * 运费付款-物流订单列表
     *
     * @author Aick Spt
     * @date 2023-07-24 16:23
     */
    public PageMoreRes<SettlementLogisticsDto> pageSelectPayment(SettlementReq settlementReq) {
        settlementReq.setUnitType(LogisticsUnitType.CARRIER);
        return pageSelect(settlementReq);
    }

    /**
     * 运费收款-物流订单详情
     *
     * @author Aick Spt
     * @date 2023-07-24 16:22
     */
    public SettlementLogisticsDto detailCollection(Long id) {
        if (id == null) {
            throw new BusinessException("结算单ID必传");
        }
        return detail(id, LogisticsUnitType.SHIPPER);
    }

    /**
     * 运费付款-物流订单详情
     *
     * @author Aick Spt
     * @date 2023-07-24 16:24
     */
    public SettlementLogisticsDto detailPayment(Long id) {
        return detail(id, LogisticsUnitType.CARRIER);
    }

    /**
     * 根据条件查物流结算订单-导出
     *
     * @author Aick Spt
     * @date 2023-07-21 16:16
     */
    public List<SettlementLogisticsDto> selectList(SettlementReq settlementReq) {
        validSettlementReq(settlementReq);
        return settlementLogisticsMapper.selectLogisticsList(settlementReq, settlementReq.getIdList());
    }

    /**
     * 验证过滤信息
     *
     * @param settlementReq
     * @author Aick Spt
     * @date 2023-08-01 10:45
     */
    private void validSettlementReq(SettlementReq settlementReq) {
        //判断时间是否成对
        CommonValidator.isValidCoexisting(settlementReq.getStartCreateTime(), settlementReq.getEndCreateTime(), "");
        CommonValidator.isValidCoexisting(settlementReq.getStartReceiptTime(), settlementReq.getEndReceiptTime(), "预计付款开始和结束时间");
        //补全时间信息
        if (StringUtils.isNotBlank(settlementReq.getStartCreateTime())) {
            settlementReq.setStartCreateTime(StringTimeUtil.fillStart(settlementReq.getStartCreateTime()));
        }
        if (StringUtils.isNotBlank(settlementReq.getEndCreateTime())) {
            settlementReq.setEndCreateTime(StringTimeUtil.fillEnd(settlementReq.getEndCreateTime()));
        }
        //加上当前登录者顶级企业id用于过滤数据
        settlementReq.setEntId(LoginUserHolder.getEntId());
    }

    /**
     * 分页查询结算物流(运费)相关订单数据，并查询出对应合计
     *
     * @author Aick Spt
     * @date 2023-08-03 10:29
     */
    private PageMoreRes<SettlementLogisticsDto> pageSelect(SettlementReq settlementReq) {
        //验证相关参数
        validSettlementReq(settlementReq);
        //添加默认分页数据
        PageHelper.startPage(settlementReq.getPage(), settlementReq.getPageSize());
        //查询分页数据
        List<SettlementLogisticsDto> kwpLedgerLogisticsList = settlementLogisticsMapper.pageSelect(settlementReq);
        //查询同样条件下的合计
        SettlementLogisticsSumVo settlementLogisticsSum = settlementLogisticsMapper.selectSum(settlementReq);

        // 对查询结果进行处理，转换 status 等状态值为对应中文描述
        return new PageMoreRes<>(getSettlementLogisticsDtoPageRes(kwpLedgerLogisticsList), settlementLogisticsSum);
    }

    /**
     * 对查询结果进行处理，转换 status 等状态值为对应中文描述
     *
     * @author Aick Spt
     * @date 2023-08-03 10:44
     */
    private PageInfo<SettlementLogisticsDto> getSettlementLogisticsDtoPageRes(List<SettlementLogisticsDto> kwpLedgerLogisticsList) {
        for (SettlementLogisticsDto entity : kwpLedgerLogisticsList) {
            setDetailDesc(entity);
        }
        return new PageInfo<>(kwpLedgerLogisticsList);
    }

    /**
     * 根据条件获取列表头部汇总数据
     *
     * @author Aick Spt
     * @date 2023-08-03 10:44
     */
    public List<TableTop> getCountList(SettlementReq settlementReq) {
        validSettlementReq(settlementReq);
        SettlementLogisticsStatusCountVo settlementLogisticsStatusCountVos = new SettlementLogisticsStatusCountVo();

        //加上当前登录者顶级企业id用于过滤数据
        settlementReq.setEntId(LoginUserHolder.getEntId());

        List<TableTop> tableTops = new ArrayList<>();
        TableTop tableTop = new TableTop();
        //总
        settlementReq.setStatus(null);
        settlementLogisticsStatusCountVos.setAllCount(settlementLogisticsMapper.getCountList(settlementReq));
        tableTop.setName("全部").setValue(settlementReq.getStatus()).setTotal(Math.toIntExact(settlementLogisticsStatusCountVos.getAllCount()));
        tableTops.add(tableTop);

        //待结算
        settlementReq.setStatus(SettlementEnum.WAITING_PAYMENT.getStatus());
//        settlementLogisticsStatusCountVos.setWaitingPaymentCount(settlementLogisticsMapper.getCountList(settlementReq));
        Long a = settlementLogisticsMapper.getCountList(settlementReq);
        settlementLogisticsStatusCountVos.setWaitingPaymentCount(a);
        TableTop tableTop1 = new TableTop();
        tableTop1.setName("待结算").setValue(SettlementEnum.WAITING_PAYMENT.getStatus()).setTotal(Math.toIntExact(a));
        tableTops.add(tableTop1);

        //部分结算
        settlementReq.setStatus(SettlementEnum.PARTIAL_PAYMENT.getStatus());
        settlementLogisticsStatusCountVos.setPartialPaymentCount(settlementLogisticsMapper.getCountList(settlementReq));
        TableTop tableTop2 = new TableTop();
        tableTop2.setName("部分结算").setValue(SettlementEnum.PARTIAL_PAYMENT.getStatus()).setTotal(Math.toIntExact(settlementLogisticsStatusCountVos.getPartialPaymentCount()));
        tableTops.add(tableTop2);

        //全部结算
        settlementReq.setStatus(SettlementEnum.ALL_PAYMENT.getStatus());
        settlementLogisticsStatusCountVos.setAllPaymentCount(settlementLogisticsMapper.getCountList(settlementReq));
        TableTop tableTop3 = new TableTop();
        tableTop3.setName("全部结算").setValue(SettlementEnum.ALL_PAYMENT.getStatus()).setTotal(Math.toIntExact(settlementLogisticsStatusCountVos.getAllPaymentCount()));
        tableTops.add(tableTop3);

        return tableTops;
    }

    /**
     * 运费-物流订单详情
     *
     * @author Aick Spt
     * @date 2023-08-07 10:14
     */
    private SettlementLogisticsDto detail(Long id, Integer unitType) {
        SettlementLogisticsDto settlementLogisticsDto = settlementLogisticsMapper.detail(id, unitType);
        if (settlementLogisticsDto == null) {
            throw new BusinessException("查无数据");
        }
        setDetailDesc(settlementLogisticsDto);
        return settlementLogisticsDto;
    }

    /**
     * 增加 创建、更新人名称及字段
     *
     * @author Aick Spt
     * @date 2023-08-07 10:14
     */
    private void setDetailDesc(SettlementLogisticsDto settlementLogisticsDto) {
        settlementLogisticsDto.setStatusText(SettlementEnum.getStatusDesc(settlementLogisticsDto.getStatus()));
        if (settlementLogisticsDto.getLedgerSettlePrice() != null) {
            if (settlementLogisticsDto.getActualPrice() != null) {
                settlementLogisticsDto.setResiduePrice(settlementLogisticsDto.getLedgerSettlePrice().subtract(settlementLogisticsDto.getActualPrice()));
            } else {
                settlementLogisticsDto.setResiduePrice(settlementLogisticsDto.getLedgerSettlePrice());
            }
        } else {
            settlementLogisticsDto.setResiduePrice(new BigDecimal(0));
        }
        settlementLogisticsDto.setCreateByText("创建人名称");//"创建人名称"
        settlementLogisticsDto.setUpdateByText("更新人名称");//"更新人名称"

        Map<Long, UserCacheResDto> map = new HashMap<>();
        Long createBy = settlementLogisticsDto.getCreateBy();
        Long updateBy = settlementLogisticsDto.getUpdateBy();
        UserCacheResDto userCacheResDto = map.get(createBy);
        if (Objects.isNull(userCacheResDto)) {
            //通过缓存拿对应数据
            userCacheResDto = remoteSystemService.queryUserCacheById(createBy);
            map.put(createBy, userCacheResDto);
        }
        if (Objects.nonNull(userCacheResDto)) {
            //写入对应数据
            settlementLogisticsDto.setCreateByText(userCacheResDto.getName());
        }
        userCacheResDto = map.get(updateBy);
        if (Objects.isNull(userCacheResDto)) {
            //通过缓存拿对应数据
            userCacheResDto = remoteSystemService.queryUserCacheById(updateBy);
            map.put(updateBy, userCacheResDto);
        }
        if (Objects.nonNull(userCacheResDto)) {
            //写入对应数据
            settlementLogisticsDto.setUpdateByText(userCacheResDto.getName());
        }
    }

}
