package com.yd.csf.service.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yd.auth.core.dto.AuthUserDto;
import com.yd.auth.core.utils.SecurityUtil;
import com.yd.common.enums.CommonEnum;
import com.yd.common.enums.ResultCode;
import com.yd.common.exception.BusinessException;
import com.yd.common.utils.RandomStringGenerator;
import com.yd.csf.service.common.ErrorCode;
import com.yd.csf.service.dto.*;
import com.yd.csf.service.enums.PolicyFollowStatusEnum;
import com.yd.csf.service.model.*;
import com.yd.csf.service.service.*;
import com.yd.csf.service.dao.PolicyFollowMapper;
import com.yd.csf.service.utils.AsyncQueryUtil;
import com.yd.csf.service.utils.GSONUtil;
import com.yd.csf.service.vo.PolicyFollowDetailVO;
import com.yd.csf.service.vo.PolicyFollowVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
* @author Zhang Jianan
* @description 针对表【policy_follow(新单跟进表)】的数据库操作Service实现
* @createDate 2025-09-16 18:18:06
*/
@Service
@Slf4j
public class PolicyFollowServiceImpl extends ServiceImpl<PolicyFollowMapper, PolicyFollow>
    implements PolicyFollowService{

    @Resource
    private PolicyBrokerService policyBrokerService;
    @Resource
    private PolicyService policyService;
    @Resource
    private PolicyFollowService policyFollowService;
    @Resource
    private PolicyFollowRecordService policyFollowRecordService;
    @Resource
    private PolicyFollowFileService policyFollowFileService;
    @Resource
    private AsyncQueryUtil asyncQueryUtil;
    @Resource
    private PolicyPolicyholderService policyPolicyholderService;
    @Resource
    private PolicyInsurantService policyInsurantService;
    @Resource
    private PolicyBeneficiaryService policyBeneficiaryService;
    @Resource
    private PolicySecondHolderService policySecondHolderService;
    @Resource
    private PolicyAdditionalService policyAdditionalService;
    @Resource
    private IExpectedFortuneService expectedFortuneService;


    @Override
    public PolicyFollow getByPolicyBizId(String policyBizId) {
        return this.getOne(new QueryWrapper<PolicyFollow>().eq("policy_biz_id", policyBizId));
    }

    @Override
    public QueryWrapper<PolicyFollow> getQueryWrapper(PolicyFollowQueryRequest policyFollowQueryRequest) {
        QueryWrapper<PolicyFollow> queryWrapper = new QueryWrapper<>();
        if (policyFollowQueryRequest == null) {
            return queryWrapper;
        }
        String policyNo = policyFollowQueryRequest.getPolicyNo();
        String customerName = policyFollowQueryRequest.getCustomerName();
        String customerBizId = policyFollowQueryRequest.getCustomerBizId();
        String status = policyFollowQueryRequest.getStatus();
        String insurer = policyFollowQueryRequest.getInsurer();
        String productName = policyFollowQueryRequest.getProductName();
        Date signDateStart = policyFollowQueryRequest.getSignDateStart();
        Date signDateEnd = policyFollowQueryRequest.getSignDateEnd();

        queryWrapper.eq(ObjectUtils.isNotEmpty(policyNo), "policy_no", policyNo);
        queryWrapper.eq(ObjectUtils.isNotEmpty(customerName), "customer_name", customerName);
        queryWrapper.eq(ObjectUtils.isNotEmpty(customerBizId), "customer_biz_id", customerBizId);
        queryWrapper.eq(ObjectUtils.isNotEmpty(status.trim()), "status", status);
        queryWrapper.eq(ObjectUtils.isNotEmpty(insurer), "insurance", insurer);
        queryWrapper.eq(ObjectUtils.isNotEmpty(productName), "product_code", productName);
        queryWrapper.ge(ObjectUtils.isNotEmpty(signDateStart), "sign_date", signDateStart);
        queryWrapper.le(ObjectUtils.isNotEmpty(signDateEnd), "sign_date", signDateEnd);

        // 排序
        queryWrapper.orderByDesc("id");

        return queryWrapper;
    }

    @Override
    public Page<PolicyFollowVO> getPolicyFollowVOPage(Page<PolicyFollow> policyFollowPage) {
        List<PolicyFollow> policyFollowList = policyFollowPage.getRecords();
        Page<PolicyFollowVO> policyFollowVOPage = new Page<>(policyFollowPage.getCurrent(), policyFollowPage.getSize(), policyFollowPage.getTotal());
        if (CollUtil.isEmpty(policyFollowList)) {
            return policyFollowVOPage;
        }
        // 对象列表 => 封装对象列表
        List<PolicyFollowVO> policyFollowVOList = policyFollowList.stream().map(PolicyFollowVO::objToVo).collect(Collectors.toList());

        // 关联查询转介人
        List<String> policyBizIdList = policyFollowList.stream().map(PolicyFollow::getPolicyBizId).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(policyBizIdList)) {
            // 转介人业务id列表 => 转介人列表
            List<PolicyBroker> policyBrokerList = policyBrokerService.list(new QueryWrapper<PolicyBroker>().in("policy_biz_id", policyBizIdList));
            // 转介人列表 => 转介人业务id列表
            Map<String, List<PolicyBroker>> brokerMap = policyBrokerList.stream().collect(Collectors.groupingBy(PolicyBroker::getPolicyBizId));
            // 转介人列表 => 封装转介人列表
            policyFollowVOList.forEach(policyFollowVO -> {
                List<PolicyBroker> brokerList = brokerMap.get(policyFollowVO.getPolicyBizId());
                policyFollowVO.setBrokerList(brokerList);
            });
        }

        return policyFollowVOPage.setRecords(policyFollowVOList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updatePolicyFollow(PolicyFollowUpdateRequest policyFollowUpdateRequest) {
        // 校验参数
        if (StringUtils.isBlank(policyFollowUpdateRequest.getPolicyBizId())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR.getCode(), "policyBizId不能为空");
        }
        String policyBizId = policyFollowUpdateRequest.getPolicyBizId();
        PolicyFollow policyFollow = getByPolicyBizId(policyBizId);
        if (policyFollow == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR.getCode(), ErrorCode.NOT_FOUND_ERROR.getMessage());
        }
        // 跟进信息
        PolicyFollowUpdateDto policyFollowUpdateDto = policyFollowUpdateRequest.getPolicyFollowUpdateDto();
        if (policyFollowUpdateDto != null) {
            BeanUtils.copyProperties(policyFollowUpdateDto, policyFollow, "id", "policyBizId");
            // 签单员列表 => 字符串
            policyFollow.setSignerList(GSONUtil.toJson(policyFollowUpdateDto.getSignerList()));
            // 计算冷却期结束日期
            if (policyFollowUpdateDto.getCoolingOffDays() != null && policyFollowUpdateDto.getEffectiveDate() != null) {
                policyFollow.setCoolingOffEndDate(DateUtil.offset(policyFollowUpdateDto.getEffectiveDate(), DateField.DAY_OF_MONTH, policyFollowUpdateDto.getCoolingOffDays()));
            }
            // 获取币种字典值
            policyFollow.setCurrency(this.getCurrencyValue(policyFollowUpdateDto.getCurrency()));
        }
        // 设置核保信息
        setValidPolicyInfo(policyFollow, policyFollowUpdateRequest.getVerifyPolicyInfo());
        // 设置保单邮寄
        setPolicyMailing(policyFollow, policyFollowUpdateRequest.getPolicyMailing());

        // 获取当前登录用户
        AuthUserDto currentLoginUser = SecurityUtil.getCurrentLoginUser();
        String loginUserId = currentLoginUser.getId().toString();
        policyFollow.setUpdaterId(loginUserId);
        policyFollow.setUpdateTime(new Date());

        // 修改转介人
        List<PolicyBrokerDto> brokerList = policyFollowUpdateRequest.getBrokerList();
        if (CollUtil.isNotEmpty(brokerList)) {
            // 先删除原有的转介人
            policyBrokerService.remove(new QueryWrapper<PolicyBroker>().eq("policy_biz_id", policyBizId));

            List<PolicyBroker> policyBrokerList = new ArrayList<>();
            for (PolicyBrokerDto policyBrokerDto : brokerList) {
                PolicyBroker policyBroker = new PolicyBroker();
                BeanUtils.copyProperties(policyBrokerDto, policyBroker);
                policyBroker.setPolicyBizId(policyBizId);
                policyBroker.setPolicyNo(policyFollow.getPolicyNo());
                policyBroker.setCreatorId(loginUserId);
                policyBroker.setCreateTime(new Date());
                policyBroker.setUpdaterId(loginUserId);
                policyBroker.setUpdateTime(new Date());
                policyBrokerList.add(policyBroker);
            }

            if (CollUtil.isNotEmpty(policyBrokerList)) {
                policyBrokerService.saveBatch(policyBrokerList);
            }
        }
        return updateById(policyFollow);
    }

    private void setPolicyMailing(PolicyFollow policyFollow, PolicyMailing policyMailing) {
        if (policyMailing == null) {
            return;
        }
        policyFollow.setMailingMethod(policyMailing.getMailingMethod());
        policyFollow.setBrokerSignDate(policyMailing.getBrokerSignDate());
        policyFollow.setInsurerMailingDate(policyMailing.getInsurerMailingDate());
        policyFollow.setCustomerSignDate(policyMailing.getCustomerSignDate());
    }

    private void setValidPolicyInfo(PolicyFollow policyFollow, VerifyPolicyInfo verifyPolicyInfo) {
        if (verifyPolicyInfo == null) {
            return;
        }
        policyFollow.setSubmitDate(verifyPolicyInfo.getSubmitDate());
        policyFollow.setSignDate(verifyPolicyInfo.getSignDate());
        policyFollow.setIssueDate(verifyPolicyInfo.getIssueDate());
        policyFollow.setEffectiveDate(verifyPolicyInfo.getEffectiveDate());
        policyFollow.setIsPrepaid(verifyPolicyInfo.getIsPrepaid());
        policyFollow.setPrepaidAmount(verifyPolicyInfo.getPrepaidAmount());
        policyFollow.setPrepaidAmountAfterDiscount(verifyPolicyInfo.getPrepaidAmountAfterDiscount());
        policyFollow.setPolicyExpirationDate(verifyPolicyInfo.getPolicyExpirationDate());
    }

    @Override
    public PolicyFollowVO getPolicyFollowVO(PolicyFollow policyFollow) {
        if (policyFollow == null) {
            return null;
        }
        PolicyFollowVO policyFollowVO = PolicyFollowVO.objToVo(policyFollow);
        // 关联查询转介人
        QueryWrapper<PolicyBroker> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("policy_biz_id", policyFollow.getPolicyBizId());
        List<PolicyBroker> policyBrokerList = policyBrokerService.list(queryWrapper);
        policyFollowVO.setBrokerList(policyBrokerList);

        return policyFollowVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> addPolicyFollow(PolicyFollowAddRequest policyFollowAddRequest) {
        PolicyFollow policyFollow = new PolicyFollow();
        BeanUtils.copyProperties(policyFollowAddRequest, policyFollow);
        // 生成新单编号
        String policyBizId = RandomStringGenerator.generateBizId16(CommonEnum.UID_TYPE_POLICY.getCode());
        policyFollow.setPolicyBizId(policyBizId);
        // 签单员列表 => 字符串
        policyFollow.setSignerList(GSONUtil.toJson(policyFollowAddRequest.getSignerList()));
        // 计算冷却期结束日期
        if (policyFollowAddRequest.getCoolingOffDays() != null) {
            policyFollow.setCoolingOffEndDate(DateUtil.offset(policyFollowAddRequest.getEffectiveDate(), DateField.DAY_OF_MONTH, policyFollowAddRequest.getCoolingOffDays()));
        }
        // 获取币种字典值
        policyFollow.setCurrency(this.getCurrencyValue(policyFollowAddRequest.getCurrency()));

        // 创建 Policy对象
        Policy policy = new Policy();
        BeanUtils.copyProperties(policyFollowAddRequest, policy);
        policy.setPolicyBizId(policyBizId);
        // 保存转介人
        List<PolicyBroker> policyBrokerList = policyFollowAddRequest.getBrokerList();
        if (CollUtil.isNotEmpty(policyBrokerList)) {
            policyBrokerList.forEach(policyBroker -> {
                policyBroker.setPolicyBizId(policyBizId);
            });
        }

        this.save(policyFollow);
        policyService.save(policy);
        policyBrokerService.saveBatch(policyBrokerList);

        // 返回新单跟进唯一业务ID
        return Collections.singletonMap("policyBizId", policyBizId);
    }

     @Override
     public Boolean addToPolicy(List<String> policyNoList) {
         if (CollectionUtils.isEmpty(policyNoList)) {
             throw new BusinessException(ErrorCode.PARAMS_ERROR.getCode(), "保单号列表不能为空");
         }
         // 获取当前登录用户
         AuthUserDto currentLoginUser = SecurityUtil.getCurrentLoginUser();
         String loginUserId = currentLoginUser.getId().toString();

         // 查询所有跟进记录
         List<PolicyFollow> policyFollowList = list(new QueryWrapper<PolicyFollow>().in("policy_no", policyNoList));
         for (PolicyFollow policyFollow : policyFollowList) {
             // 查询保单是否存在
             String policyBizId = policyFollow.getPolicyBizId();
             Policy policy = policyService.getOne(new QueryWrapper<Policy>().eq("policy_biz_id", policyBizId));
             if (policy != null) {
                 // 更新
                 BeanUtils.copyProperties(policyFollow, policy, "id");
                 policy.setUpdaterId(loginUserId);
                 policy.setUpdateTime(new Date());

                 policyService.updateById(policy);
             } else {
                 // 不存在则创建
                 policy = new Policy();
                 BeanUtils.copyProperties(policyFollow, policy, "id");
                 policy.setId(null);
                 policy.setPolicyBizId(policyBizId);
                 policy.setCreatorId(loginUserId);
                 policy.setCreateTime(new Date());
                 policy.setUpdaterId(loginUserId);
                 policy.setUpdateTime(new Date());

                 policyService.save(policy);
             }
         }
         return true;
     }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean changePolicyFollowStatus(ChangePolicyFollowStatusRequest changePolicyFollowStatusRequest, PolicyFollow policyFollow) {
        if (changePolicyFollowStatusRequest == null || StringUtils.isBlank(changePolicyFollowStatusRequest.getPolicyBizId())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR.getCode(), "policyBizId不能为空");
        }
        if (policyFollow == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR.getCode(), ErrorCode.NOT_FOUND_ERROR.getMessage());
        }
        // 校验状态是否存在
        PolicyFollowStatusEnum policyFollowStatusEnum = PolicyFollowStatusEnum.getEnumByValue(changePolicyFollowStatusRequest.getStatus());
        if (policyFollowStatusEnum == null) {
            throw new BusinessException(ResultCode.PARAM_CHECK_ERROR.getCode(), "跟进状态不存在");
        }
        // 获取当前跟进状态
        PolicyFollowStatusEnum currentStatusEnum = PolicyFollowStatusEnum.getEnumByValue(policyFollow.getStatus());
        // 校验状态是否可变更
        if (PolicyFollowStatusEnum.FINISHED.equals(currentStatusEnum)
                || PolicyFollowStatusEnum.DECLINED.equals(currentStatusEnum)
                || PolicyFollowStatusEnum.CANCELLED.equals(currentStatusEnum)
        ) {
            throw new BusinessException(ResultCode.PARAM_CHECK_ERROR.getCode(), "已完成、已拒绝、已取消状态不能变更");
        }
        // 校验状态
        validPolicyFollowStatus(currentStatusEnum, policyFollowStatusEnum);

        String policyBizId = changePolicyFollowStatusRequest.getPolicyBizId();

        // 保单号和转接人都有的情况下，才能修改为已完成状态
        if (PolicyFollowStatusEnum.FINISHED.equals(policyFollowStatusEnum)) {
            if (StringUtils.isBlank(policyFollow.getPolicyNo())) {
                throw new BusinessException(ResultCode.PARAM_CHECK_ERROR.getCode(), "保单号和转接人都不能为空，才能修改为已完成状态");
            }
            boolean exists = policyBrokerService.exists(new QueryWrapper<PolicyBroker>().eq("policy_biz_id", policyBizId));
            if (!exists) {
                throw new BusinessException(ResultCode.PARAM_CHECK_ERROR.getCode(), "保单号和转接人都不能为空，才能修改为已完成状态");
            }
        }

        // 获取当前登录用户
        AuthUserDto currentLoginUser = SecurityUtil.getCurrentLoginUser();
        String loginUserId = currentLoginUser.getId().toString();

        policyFollow.setStatus(changePolicyFollowStatusRequest.getStatus());
        policyFollow.setNextStatusList(getNextStatus(policyFollowStatusEnum));
        policyFollow.setUpdaterId(loginUserId);
        policyFollowService.updateById(policyFollow);

        // 如果是已完成状态，同步到保单库
        if (PolicyFollowStatusEnum.FINISHED.equals(policyFollowStatusEnum)) {
            addToPolicy(Collections.singletonList(policyFollow.getPolicyNo()));
        }

        // 新增新单状态记录
        PolicyFollowRecord policyFollowRecord = new PolicyFollowRecord();
        policyFollowRecord.setId(null);
        policyFollowRecord.setPolicyBizId(policyBizId);
        policyFollowRecord.setTitle(Objects.requireNonNull(policyFollowStatusEnum.getItemLabel()));
        policyFollowRecord.setMessage(changePolicyFollowStatusRequest.getMessage());
        policyFollowRecord.setCreatorId(loginUserId);
        policyFollowRecord.setCreateTime(new Date());
        policyFollowRecordService.save(policyFollowRecord);

        return true;
    }

    @Override
    public String getNextStatus(PolicyFollowStatusEnum policyFollowStatusEnum) {
        switch (policyFollowStatusEnum) {
            case FOLLOW_UP:
                return PolicyFollowStatusEnum.CHECKING.getItemValue() + ","
                        + PolicyFollowStatusEnum.DECLINED.getItemValue() + ","
                        + PolicyFollowStatusEnum.CANCELLED.getItemValue();
            case CHECKING:
                return PolicyFollowStatusEnum.UNDERWRITING.getItemValue() + ","
                        + PolicyFollowStatusEnum.CANCELLED.getItemValue();
            case UNDERWRITING:
                return PolicyFollowStatusEnum.FINISHED.getItemValue() + ","
                        + PolicyFollowStatusEnum.DECLINED.getItemValue() + ","
                        + PolicyFollowStatusEnum.CANCELLED.getItemValue();
            default:
                return null;
        }
    }

    /**
     * 异步聚合查询新单跟进详情
     */
    @Override
    public PolicyFollowAggregateDto getPolicyFollowAggregate(String policyBizId) {
        long startTime = System.currentTimeMillis();

        try {
            // 1. 异步查询保单信息
            CompletableFuture<Policy> policyFuture = asyncQueryUtil.asyncQuery(
                    () -> policyService.getOne(new QueryWrapper<Policy>().eq("policy_biz_id", policyBizId)),
                    "查询保单信息"
            );

            // 1.1 异步查询附加险列表
            CompletableFuture<List<PolicyAdditional>> additionalListFuture = asyncQueryUtil.asyncQuery(
                    () -> policyAdditionalService.list(new QueryWrapper<PolicyAdditional>().eq("policy_biz_id", policyBizId)),
                    "查询附加险列表"
            );

            // 1.2 异步查询保单投保人
            CompletableFuture<PolicyPolicyholder> policyholderFuture = asyncQueryUtil.asyncQuery(
                    () -> {
                        QueryWrapper<PolicyPolicyholder> queryWrapper = new QueryWrapper<>();
                        queryWrapper.eq("policy_biz_id", policyBizId);
                        return policyPolicyholderService.getOne(queryWrapper);
                    },
                    "查询保单投保人"
            );

            // 1.3 异步查询保单受保人
            CompletableFuture<PolicyInsurant> insurantListFuture = asyncQueryUtil.asyncQuery(
                    () -> {
                        QueryWrapper<PolicyInsurant> queryWrapper = new QueryWrapper<>();
                        queryWrapper.eq("policy_biz_id", policyBizId);
                        return policyInsurantService.getOne(queryWrapper);
                    },
                    "查询保单受保人"
            );

            // 1.4 异步查询保单受益人
            CompletableFuture<List<PolicyBeneficiary>> beneficiaryListFuture = asyncQueryUtil.asyncQuery(
                    () -> {
                        QueryWrapper<PolicyBeneficiary> queryWrapper = new QueryWrapper<>();
                        queryWrapper.eq("policy_biz_id", policyBizId);
                        return policyBeneficiaryService.list(queryWrapper);
                    },
                    "查询保单受益人"
            );

            // 1.5 异步查询保单第二持有人
            CompletableFuture<PolicySecondHolder> policySecondHolderFuture = asyncQueryUtil.asyncQuery(
                    () -> {
                        QueryWrapper<PolicySecondHolder> queryWrapper = new QueryWrapper<>();
                        queryWrapper.eq("policy_biz_id", policyBizId);
                        return policySecondHolderService.getOne(queryWrapper);
                    },
                    "查询保单第二持有人"
            );
            // 1.6 异步查询客户业务ID
            CompletableFuture<String> customerBizIdFuture = asyncQueryUtil.asyncQuery(
                    () -> {
                        QueryWrapper<PolicyFollow> queryWrapper = new QueryWrapper<>();
                        queryWrapper.eq("policy_biz_id", policyBizId);
                        PolicyFollow policyFollow = policyFollowService.getOne(queryWrapper);
                        return policyFollow != null ? policyFollow.getCustomerBizId() : null;
                    },
                    "查询客户业务ID"
            );

            // 2. 等待所有异步任务完成（设置超时时间）
            CompletableFuture.allOf(
                            policyFuture,
                            additionalListFuture,
                            policyholderFuture,
                            insurantListFuture,
                            beneficiaryListFuture,
                            policySecondHolderFuture,
                            customerBizIdFuture)
                    .get(5, TimeUnit.SECONDS); // 5秒超时

            // 3. 构建聚合结果
            PolicyFollowAggregateDto aggregateDto = PolicyFollowAggregateDto.convertToDto(
                    policyFuture.get(),
                    additionalListFuture.get(),
                    policyholderFuture.get(),
                    insurantListFuture.get(),
                    beneficiaryListFuture.get(),
                    policySecondHolderFuture.get(),
                    customerBizIdFuture.get()
            );

            long costTime = System.currentTimeMillis() - startTime;
            log.info("新单跟进聚合查询完成, policyBizId: {}, 总耗时: {}ms", policyBizId, costTime);

            return aggregateDto;

        } catch (Exception e) {
            log.error("新单跟进聚合查询失败, policyBizId: {}, 错误: {}", policyBizId, e.getMessage(), e);
            PolicyFollowAggregateDto errorDto = new PolicyFollowAggregateDto();
            errorDto.setErrorMessage("查询失败: " + e.getMessage());
            return errorDto;
        }
    }

    @Override
    public Page<PolicyFollowDetailVO> getPolicyFollowDetailVOList(Page<PolicyFollow> policyFollowPage) {
        List<PolicyFollow> policyFollowList = policyFollowPage.getRecords();
        Page<PolicyFollowDetailVO> policyFollowDetailVOPage = new Page<>(policyFollowPage.getCurrent(), policyFollowPage.getSize(), policyFollowPage.getTotal());
        if (CollUtil.isEmpty(policyFollowList)) {
            return policyFollowDetailVOPage;
        }

        // 对象列表 => 封装对象列表
        List<PolicyFollowDetailVO> policyFollowDetailVOList = policyFollowList.stream().map(PolicyFollowDetailVO::objToVo).collect(Collectors.toList());

        // 关联查询转介人
        List<String> policyBizIdList = policyFollowList.stream().map(PolicyFollow::getPolicyBizId).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(policyBizIdList)) {
            // 转介人业务id列表 => 转介人列表
            List<PolicyBroker> policyBrokerList = policyBrokerService.list(new QueryWrapper<PolicyBroker>().in("policy_biz_id", policyBizIdList));
            // 转介人列表 => 转介人业务id列表
            Map<String, List<PolicyBroker>> brokerMap = policyBrokerList.stream().collect(Collectors.groupingBy(PolicyBroker::getPolicyBizId));
            // 转介人列表 => 封装转介人列表
            policyFollowDetailVOList.forEach(policyFollowVO -> {
                List<PolicyBroker> brokerList = brokerMap.get(policyFollowVO.getPolicyBizId());
                policyFollowVO.setBrokerList(brokerList);
            });
        }

        policyFollowDetailVOPage.setRecords(policyFollowDetailVOList);
        return policyFollowDetailVOPage;
    }

    @Override
    public String getCurrencyValue(String currency) {
        if (StringUtils.isBlank(currency)) {
            return null;
        }
        switch (currency) {
            case "美元":
                currency = "USD";
                break;
            case "人民幣":
                currency = "CNY";
                break;
            case "港幣":
                currency = "HKD";
                break;
            case "澳元":
                currency = "AUD";
                break;
            case "加元":
                currency = "CAD";
                break;
            case "欧元":
                currency = "EUR";
                break;
            case "英鎊":
                currency = "GBP";
                break;
            case "新加坡元":
                currency = "SGD";
                break;
            default:
                break;
        }
        return currency;
    }

    @Override
    public PolicyReportData queryPolicyReportData(String policyBizId) {
        // 查询主险信息
        PolicyReportData policyReportData = this.baseMapper.queryPolicyReportData(policyBizId);
        // 处理附加险信息
        List<PolicyAdditional> additionalList= policyAdditionalService.list(new QueryWrapper<PolicyAdditional>().eq("policy_biz_id", policyBizId));
        List<PolicyReportData.AdditionalInsurance> additionalInsurances = new ArrayList<>();
        if (CollUtil.isNotEmpty(additionalList)) {
            for (PolicyAdditional additional : additionalList) {
                PolicyReportData.AdditionalInsurance additionalInsurance = new PolicyReportData.AdditionalInsurance();
                additionalInsurance.setName(additional.getAddProductName());
                additionalInsurance.setPaymentTerm(null);
                additionalInsurance.setCurrency(getCurrencyValue(additional.getCurrency()));
                additionalInsurance.setFirstYearAmount(additional.getPremium());
                additionalInsurances.add(additionalInsurance);
            }
        }
        // 处理附加险信息
        policyReportData.setAdditionalInsurances(additionalInsurances);
        // 处理服务经理
        String signerList = policyReportData.getServiceManager();
        if (StringUtils.isNotBlank(signerList)) {
            policyReportData.setServiceManager(signerList.split(",")[0]);
        }
        // 处理位置
        policyReportData.setLocation("香港");
        return policyReportData;
    }

    @Override
    public Boolean uploadAttachment(AttachmentUploadRequest attachmentUploadRequest) {
        String policyBizId = attachmentUploadRequest.getPolicyBizId();
        if (policyBizId == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR.getCode(), "policyBizId不能为空");
        }
        String fileName = attachmentUploadRequest.getFileName();
        if (fileName == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR.getCode(), "fileName不能为空");
        }
        String fileUrl = attachmentUploadRequest.getFileUrl();
        if (fileUrl == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR.getCode(), "fileUrl不能为空");
        }
        String ossFileBizId = attachmentUploadRequest.getOssFileBizId();
        if (ossFileBizId == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR.getCode(), "ossFileBizId不能为空");
        }

        PolicyFollowFile policyFollowFile = new PolicyFollowFile();
        policyFollowFile.setPolicyBizId(attachmentUploadRequest.getPolicyBizId());
        policyFollowFile.setOssFileBizId(attachmentUploadRequest.getOssFileBizId());
        policyFollowFile.setFileName(attachmentUploadRequest.getFileName());
        policyFollowFile.setFileUrl(attachmentUploadRequest.getFileUrl());

        return policyFollowFileService.save(policyFollowFile);
    }

    private static void validPolicyFollowStatus(PolicyFollowStatusEnum currentStatusEnum, PolicyFollowStatusEnum policyFollowStatusEnum) {
        // 如果是已取消，则不校验
        if (PolicyFollowStatusEnum.CANCELLED.equals(policyFollowStatusEnum)) {
            return;
        }

        if (PolicyFollowStatusEnum.FOLLOW_UP.equals(currentStatusEnum) && !PolicyFollowStatusEnum.CHECKING.equals(policyFollowStatusEnum)) {
            throw new BusinessException(ResultCode.PARAM_CHECK_ERROR.getCode(), "待跟进状态只能改为文件检查中");
        }
        if (PolicyFollowStatusEnum.CHECKING.equals(currentStatusEnum) && !PolicyFollowStatusEnum.UNDERWRITING.equals(policyFollowStatusEnum)) {
            throw new BusinessException(ResultCode.PARAM_CHECK_ERROR.getCode(), "文件检查中状态只能改为承保中");
        }
        if (PolicyFollowStatusEnum.UNDERWRITING.equals(currentStatusEnum)) {
            if (!(PolicyFollowStatusEnum.FINISHED.equals(policyFollowStatusEnum) || PolicyFollowStatusEnum.DECLINED.equals(policyFollowStatusEnum))) {
                throw new BusinessException(ResultCode.PARAM_CHECK_ERROR.getCode(), "承保中状态只能改为已完成或已拒绝");
            }
        }
    }

}




