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

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yd.csf.feign.request.expectedfortune.ApiExpectedFortunePageRequest;
import com.yd.csf.feign.response.expectedfortune.ApiExpectedFortunePageResponse;
import com.yd.csf.service.dto.UserGradeDto;
import com.yd.csf.service.enums.CurrencyEnum;
import com.yd.csf.service.model.ExpectedFortune;
import com.yd.csf.service.dao.ExpectedFortuneMapper;
import com.yd.csf.service.model.Policy;
import com.yd.csf.service.model.PolicyFollow;
import com.yd.csf.service.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yd.csf.service.vo.ExpectedFortuneStatisticsVO;
import com.yd.csf.service.vo.PayableReportVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 预计发佣表 服务实现类
 * </p>
 *
 * @author zxm
 * @since 2025-11-17
 */
@Service
public class ExpectedFortuneServiceImpl extends ServiceImpl<ExpectedFortuneMapper, ExpectedFortune> implements IExpectedFortuneService {

    @Resource
    private PolicyService policyService;

    @Resource
    private PolicyFollowService policyFollowService;

    @Resource
    private IConditionConfigService iConditionConfigService;

    @Autowired
    private IAgentAccumulatedFycService iAgentAccumulatedFycService;

    @Override
    public IPage<ApiExpectedFortunePageResponse> page(Page<ApiExpectedFortunePageResponse> page,
                                                      ApiExpectedFortunePageRequest request) {
        return baseMapper.page(page, request);
    }

    @Override
    public List<ExpectedFortune> listByPolicyBizId(String policyBizId) {
        return baseMapper.listByPolicyBizId(policyBizId);
    }

    /**
     * 查询列表
     *
     * @param policyNo
     * @return
     */
    @Override
    public List<ExpectedFortune> queryList(String policyNo) {
        return baseMapper.selectList(new LambdaQueryWrapper<ExpectedFortune>().eq(ExpectedFortune::getPolicyNo, policyNo));
    }

    @Override
    public Boolean batchDelByPolicyNo(String policyNo) {
        return this.remove(new LambdaQueryWrapper<ExpectedFortune>().eq(ExpectedFortune::getPolicyNo, policyNo));
    }

    @Override
    public ExpectedFortuneStatisticsVO getStatistics(List<Long> expectedFortuneIds) {
        return baseMapper.getStatistics(expectedFortuneIds);
    }

    @Override
    public IPage<ApiExpectedFortunePageResponse> getVOPage(IPage<ExpectedFortune> iPage) {
        List<ExpectedFortune> expectedFortuneList = iPage.getRecords();
        Page<ApiExpectedFortunePageResponse> expectedFortuneVOPage = new Page<>(iPage.getCurrent(), iPage.getSize(), iPage.getTotal());
        if (CollUtil.isEmpty(expectedFortuneList)) {
            return expectedFortuneVOPage;
        }
        List<ApiExpectedFortunePageResponse> expectedFortuneVOList = toVOList(expectedFortuneList);
        expectedFortuneVOPage.setRecords(expectedFortuneVOList);
        return expectedFortuneVOPage;
    }

    @Override
    public List<ApiExpectedFortunePageResponse> toVOList(List<ExpectedFortune> expectedFortuneList) {
        if (CollUtil.isEmpty(expectedFortuneList)) {
            return Collections.emptyList();
        }

        // 收集所有 brokerBizId
        List<String> brokerBizIds = expectedFortuneList.stream()
                .map(ExpectedFortune::getBrokerBizId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());

        Map<String, String> brokerRatioMap = new HashMap<>();
        List<UserGradeDto> userGradeDtoList = new ArrayList<>();
        if (CollUtil.isNotEmpty(brokerBizIds)) {
            List<Map<String, Object>> ratioList = iConditionConfigService.selectBrokerRatioByBizIds(brokerBizIds);
            brokerRatioMap = ratioList.stream()
                    .filter(map -> map.get("conditional_value") != null)
                    .collect(Collectors.toMap(
                            map -> (String) map.get("brokerBizId"),
                            map -> (String) map.get("conditional_value"),
                            (v1, v2) -> v1
                    ));
            userGradeDtoList = iAgentAccumulatedFycService.queryUserGradeList(brokerBizIds);
        }
        Map<String, UserGradeDto> userGradeMap = userGradeDtoList.stream()
                .collect(Collectors.toMap(UserGradeDto::getClientUserBizId, Function.identity()));

        List<String> policyNos = expectedFortuneList.stream()
                .map(ExpectedFortune::getPolicyNo)
                .collect(Collectors.toList());
        List<Policy> policyList = policyService.lambdaQuery()
                .in(Policy::getPolicyNo, policyNos).list();
        List<PolicyFollow> policyFollowList = policyFollowService.lambdaQuery()
                .in(PolicyFollow::getPolicyNo, policyNos).list();

        Map<String, Policy> policyMap = policyList.stream()
                .collect(Collectors.toMap(Policy::getPolicyNo, Function.identity()));
        Map<String, PolicyFollow> policyFollowMap = policyFollowList.stream()
                .collect(Collectors.toMap(PolicyFollow::getPolicyNo, Function.identity()));

        // 组装 VO
        Map<String, String> finalBrokerRatioMap = brokerRatioMap;
        List<ApiExpectedFortunePageResponse> voList = expectedFortuneList.stream().map(ef -> {
            ApiExpectedFortunePageResponse vo = new ApiExpectedFortunePageResponse();
            BeanUtils.copyProperties(ef, vo);

            vo.setCurrencyName("港币");

            String ratio = finalBrokerRatioMap.get(ef.getBrokerBizId());
            vo.setCommissionRatio(ratio);

            Policy policy = policyMap.get(ef.getPolicyNo());
            PolicyFollow follow = policyFollowMap.get(ef.getPolicyNo());
            UserGradeDto userGradeDto = userGradeMap.get(ef.getBrokerBizId());
            if (userGradeDto != null) {
                vo.setBrokerGradeName(userGradeDto.getGradeName());
            }
            if (policy != null) {
                vo.setInsuranceCompany(policy.getInsuranceCompany());
                vo.setPremium(policy.getPaymentPremium());
            }
            if (follow != null) {
                vo.setProductName(follow.getProductName());
                vo.setProductLaunchBizId(follow.getProductLaunchBizId());
            }
            return vo;
        }).collect(Collectors.toList());

        return voList;
    }

    @Override
    public IPage<PayableReportVO> payableReportPage(Page<PayableReportVO> page, List<Long> expectedFortuneIds) {
        return baseMapper.payableReportPage(page, expectedFortuneIds);
    }

    @Override
    public void updateBatchByBizId(List<String> expectedFortuneBizIdList, String status) {
        baseMapper.updateBatchByBizId(expectedFortuneBizIdList, status);
    }

    @Override
    public ExpectedFortune getByBizId(String expectedFortuneBizId) {
        return this.getOne(new QueryWrapper<ExpectedFortune>().eq("expected_fortune_biz_id", expectedFortuneBizId));
    }

    @Override
    public Integer getPayableNoCurrentSeq() {

        ExpectedFortune latest = this.getOne(
                new QueryWrapper<ExpectedFortune>()
                        .isNotNull("payable_no")
                        .eq("is_part", 0)
                        .orderByDesc("id")
                        .last("LIMIT 1"),
                true
        );
        //获取当前序号作为起点
        int currentSeq = 0;
        if (!Objects.isNull(latest)) {
            String payableNo = latest.getPayableNo();
            currentSeq = Integer.parseInt(payableNo.substring(payableNo.length() - 6));
        }

        return currentSeq;
    }

    @Override
    public String getPayableNo(String fortuneType) {
        Integer currentSeq = getPayableNoCurrentSeq();
        return String.format("%s%s%s",
                fortuneType + "-CSF",
                LocalDate.now().getYear() % 100,
                currentSeq + 1);
    }
}
