package com.yd.csf.api.controller;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yd.auth.core.dto.AuthUserDto;
import com.yd.auth.core.utils.SecurityUtil;
import com.yd.common.enums.ResultCode;
import com.yd.common.exception.BusinessException;
import com.yd.common.result.Result;
import com.yd.csf.api.dto.CommissionExcelDTO;
import com.yd.csf.service.common.ErrorCode;
import com.yd.csf.service.dto.*;
import com.yd.csf.service.model.Commission;
import com.yd.csf.service.model.CommissionCompareRecord;
import com.yd.csf.service.model.CommissionEditRecord;
import com.yd.csf.service.model.CommissionExpected;
import com.yd.csf.service.service.CommissionCompareRecordService;
import com.yd.csf.service.service.CommissionEditRecordService;
import com.yd.csf.service.service.CommissionExpectedService;
import com.yd.csf.service.service.CommissionService;
import com.yd.csf.service.vo.CommissionStatisticsVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 保单来佣接口
 *
 * @author jianan
 * @since 2025-09-15
 */
@RestController
@RequestMapping("/commission")
@Tag(name = "保单来佣接口")
public class ApiCommissionController {

    private static final Logger log = LoggerFactory.getLogger(ApiCommissionController.class);

    @Resource
    private CommissionService commissionService;

    @Resource
    private CommissionExpectedService commissionExpectedService;

    @Resource
    private CommissionEditRecordService commissionEditRecordService;

    @Resource
    private CommissionCompareRecordService commissionCompareRecordService;



    @PostMapping("/upload/excel")
    @Operation(summary = "上传保单来佣Excel文件")
    @Transactional(rollbackFor = Exception.class)
    public Result<Boolean> uploadExcel(@RequestParam("file") MultipartFile file) throws IOException {
        List<CommissionExcelDTO> dataList = new ArrayList<>();
        try {
            dataList = EasyExcel.read(file.getInputStream())
                    .head(CommissionExcelDTO.class)
                    .sheet("来佣")
                    .doReadSync();

        } catch (IOException e) {
            throw new RuntimeException("Excel读取失败", e);
        }

        // 数据校验
        validateCommissionUpload(dataList);

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

        // 数据处理
        processData(dataList, loginUserId);

        return Result.success(true);
    }

    /**
     * 校验导入的来佣数据是否符合要求，返回行号和错误信息
     */
    private void validateCommissionUpload(List<CommissionExcelDTO> dataList) {
        // 校验数据是否为空
        if (CollectionUtils.isEmpty(dataList)) {
            throw new BusinessException(ResultCode.PARAMS_ERROR.getCode(), "导入数据不能为空");
        }
        StringBuilder errorMsg = new StringBuilder();
        for (CommissionExcelDTO excelDTO : dataList) {
            // 校验必填字段是否为空
            if (StringUtils.isBlank(excelDTO.getPolicyNo()) ||
                    StringUtils.isBlank(excelDTO.getReconciliationCompany()) ||
                    StringUtils.isBlank(excelDTO.getCommissionName()) ||
                    excelDTO.getAmount() == null ||
                    StringUtils.isBlank(excelDTO.getCurrency()) ||
                    excelDTO.getCommissionDate() == null) {
                errorMsg.append("第").append(dataList.indexOf(excelDTO) + 1).append("行存在空字段");
            }
            // 校验来佣金额是否为正数
            if (excelDTO.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
                errorMsg.append("第").append(dataList.indexOf(excelDTO) + 1).append("行来佣金额必须为正数");
            }
        }
        if (errorMsg.length() > 0) {
            throw new BusinessException(ResultCode.PARAMS_ERROR.getCode(), errorMsg.toString());
        }
    }

    /**
     * 1.处理导入的数据 2.比对预计来佣 3.保存到数据库
     */
    private void processData(List<CommissionExcelDTO> dataList, String loginUserId) {
        List<Commission> entities = new ArrayList<>();
        for (CommissionExcelDTO data : dataList) {
            // 数据验证
            Commission entity = CommissionExcelDTO.convertToEntity(data, loginUserId);
            entities.add(entity);
        }

        // 根据导入的来佣获取保单号集合
        List<String> policyNoList = entities.stream()
                .map(Commission::getPolicyNo)
                .collect(Collectors.toList());
        // 根据保单号查询预计来佣
        List<CommissionExpected> expectedList = commissionExpectedService.lambdaQuery()
                .in(CommissionExpected::getPolicyNo, policyNoList)
                .list();

        // 校验导入的来佣是否与预计来佣一致
        for (Commission commission : entities) {
            String policyNo = commission.getPolicyNo();
            Integer commissionPeriod = commission.getCommissionPeriod();
            String commissionName = commission.getCommissionName();

            CommissionExpected expected = getCommissionExpected(expectedList, policyNo, commissionPeriod, commissionName);
            if (expected != null) {
                commissionService.compareWithExpected(commission.getPremium(), commission, expected);
            } else {
                // 预计来佣不存在，来佣状态设置为 比对失败
                commission.setStatus("2");
                commission.setRemark("未找到当前来佣对应的预计来佣，比对失败");
            }
        }

        // 保存来佣数据
        commissionService.saveBatch(entities);
        // 更新预计来佣状态
        commissionExpectedService.updateBatchById(expectedList);
    }

    private static CommissionExpected getCommissionExpected(List<CommissionExpected> expectedList, String policyNo, Integer commissionPeriod, String commissionName) {
        return expectedList.stream()
                .filter(item -> item.getPolicyNo().equals(policyNo)
                        && commissionPeriod.equals(item.getCommissionPeriod())
                        && commissionName.equals(item.getCommissionName()))
                .findFirst()
                .orElse(null);
    }

    /**
     * 生成可出账（发佣）记录，支持手动复选框选择
     *
     * @param generateFortuneRequest
     * @param request
     * @return
     */
    @PostMapping("/generate/fortune")
    @Operation(summary = "生成可出账（发佣）记录，支持手动复选框选择")
    public Result<Boolean> generateFortune(@RequestBody GenerateFortuneRequest generateFortuneRequest,
                                                            HttpServletRequest request) {
        List<String> commissionBizIdList = generateFortuneRequest.getCommissionBizIdList();
        if (CollectionUtils.isEmpty(commissionBizIdList)) {
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), "commissionBizIdList不能为空");
        }
        return Result.success(commissionService.generateFortune(generateFortuneRequest));
    }

    /**
     * 创建保单来佣
     *
     * @param customerAddRequest
     * @param request
     * @return
     */
    @Operation(summary = "创建保单来佣")
    @PostMapping("/add")
    public Result<Boolean> addCommission(@RequestBody CommissionAddRequest customerAddRequest, HttpServletRequest request) {
        if (customerAddRequest == null || StringUtils.isBlank(customerAddRequest.getPolicyNo())) {
            return Result.fail(ResultCode.PARAMS_ERROR.getCode(), "保单号不能为空");
        }
        return Result.success(commissionService.addCommission(customerAddRequest));
    }

    /**
     * 来佣比对记录列表
     */
    @PostMapping("/compare/records")
    @Operation(summary = "来佣比对记录列表")
    public Result<Page<CommissionCompareRecord>> getCommissionCompareRecords(@RequestBody CommissionCompareRecordQueryRequest queryRequest) {
        if (StringUtils.isBlank(queryRequest.getCommissionBizId())) {
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), "commissionBizId不能为空");
        }
        // 查询来佣比对记录
        Page<CommissionCompareRecord> page = commissionCompareRecordService.page(new Page<>(queryRequest.getPageNo(), queryRequest.getPageSize()),
                new LambdaQueryWrapper<CommissionCompareRecord>()
                        .eq(CommissionCompareRecord::getCommissionBizId, queryRequest.getCommissionBizId())
                        .orderByAsc(CommissionCompareRecord::getCommissionPeriod));

        return Result.success(page);
    }

    /**
     * 删除来佣
     *
     * @param deleteRequest
     * @param request
     * @return
     */
    @PostMapping("/delete")
    public Result<Boolean> deleteCommission(@RequestBody CommissionDeleteRequest deleteRequest, HttpServletRequest request) {
        if (StringUtils.isBlank(deleteRequest.getCommissionBizId())) {
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), ErrorCode.PARAMS_ERROR.getMessage());
        }
        String commissionBizId = deleteRequest.getCommissionBizId();

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

        // 判断是否存在
        Commission oldCommission = commissionService.getByCommissionBizId(commissionBizId);
        if (oldCommission == null) {
            return Result.fail(ErrorCode.NOT_FOUND_ERROR.getCode(), ErrorCode.NOT_FOUND_ERROR.getMessage());
        }
        // 仅本人或管理员可删除
//        if (!oldCommission.getUserId().equals(loginUserId) && !userService.isAdmin(request)) {
//            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
//        }
        // 操作数据库
        boolean result = commissionService.removeById(oldCommission.getId());
        if (!result) {
            return Result.fail(ErrorCode.OPERATION_ERROR.getCode(), ErrorCode.OPERATION_ERROR.getMessage());
        }
        return Result.success(result);
    }

    /**
     * 更新保单来佣
     *
     * @param commissionUpdateRequest
     * @return
     */
    @PostMapping("/update")
    @Operation(summary = "更新保单来佣信息")
    public Result<Boolean> updateCommission(@RequestBody CommissionUpdateRequest commissionUpdateRequest) {
        if (commissionUpdateRequest == null || commissionUpdateRequest.getCommissionBizId() == null) {
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), ErrorCode.PARAMS_ERROR.getMessage());
        }
        return Result.success(commissionService.updateCommission(commissionUpdateRequest));
    }

    /**
     * 来佣操作记录列表
     *
     * @param queryRequest
     * @return
     */
    @PostMapping("/edit/records")
    @Operation(summary = "来佣操作记录列表")
    public Result<Page<CommissionEditRecord>> getCommissionEditRecords(@RequestBody CommissionEditRecordQueryRequest queryRequest) {
        if (StringUtils.isBlank(queryRequest.getCommissionBizId())) {
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), "commissionBizId不能为空");
        }
        // 查询来佣操作记录
        Page<CommissionEditRecord> page = commissionEditRecordService.page(new Page<>(queryRequest.getPageNo(), queryRequest.getPageSize()), new LambdaQueryWrapper<CommissionEditRecord>()
                .eq(CommissionEditRecord::getCommissionBizId, queryRequest.getCommissionBizId())
                .orderByAsc(CommissionEditRecord::getSeq));
        return Result.success(page);
    }

    /**
     * 计算统计数据 总金额、总入账金额、待入账金额、已入账比例（已入账金额/总金额）、总保单数
     */
     @PostMapping("/statistics")
     @Operation(summary = "计算统计数据 总金额、总入账金额、待入账金额、已入账比例（已入账金额/总金额）、总保单数")
     public Result<CommissionStatisticsVO> getCommissionStatistics(@RequestBody CommissionStatisticsRequest commissionStatisticsRequest) {
        if (commissionStatisticsRequest == null) {
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), ErrorCode.PARAMS_ERROR.getMessage());
        }
        return Result.success(commissionService.getCommissionStatistics(commissionStatisticsRequest.getCommissionIds()));
     }


    /**
     * 根据 commissionBizId 获取保单来佣（封装类）
     *
     * @param commissionBizId
     * @return
     */
//    @GetMapping("/get/vo")
//    @Operation(summary = "根据 policyBizId 获取保单来佣详情")
//    public Result<PolicyFollowVO> getPolicyFollowByPolicyBizId(@RequestParam("commissionBizId") String commissionBizId, HttpServletRequest request) {
//        if (commissionBizId == null) {
//            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), ErrorCode.PARAMS_ERROR.getMessage());
//        }
//        // 查询数据库
//        PolicyFollow policyFollow = policyFollowService.getByPolicyBizId(policyBizId);
//        if (policyFollow == null) {
//            return Result.fail(ErrorCode.NOT_FOUND_ERROR.getCode(), ErrorCode.NOT_FOUND_ERROR.getMessage());
//        }
//
//        // 获取封装类
//        return Result.success(policyFollowService.getPolicyFollowVO(policyFollow));
//    }

    /**
     * 分页获取保单来佣列表（仅管理员可用）
     *
     * @param fnaQueryRequest
     * @return
     */
//    @PostMapping("/list/page")
//    public Result<Page<Customer>> listFnaByPage(@RequestBody FnaQueryRequest fnaQueryRequest) {
//        long current = fnaQueryRequest.getPageNo();
//        long size = fnaQueryRequest.getPageSize();
//        // 查询数据库
//        Page<Customer> fnaPage = policyFollowService.page(new Page<>(current, size),
//                policyFollowService.getQueryWrapper(fnaQueryRequest));
//        return Result.success(fnaPage);
//    }

    /**
     * 分页获取保单来佣列表（VO）
     *
     * @param commissionQueryRequest
     * @param request
     * @return
     */
    @PostMapping("/list/page/vo")
    @Operation(summary = "分页获取保单来佣列表")
    public Result<Map<String, Object>> listPolicyFollowByPage(@RequestBody CommissionQueryRequest commissionQueryRequest,
                                                             HttpServletRequest request) {
        long current = commissionQueryRequest.getPageNo();
        long size = commissionQueryRequest.getPageSize();

        // 查询列表数据
        QueryWrapper<Commission> queryWrapper = commissionService.getQueryWrapper(commissionQueryRequest);
        Page<Commission> commissionPage = commissionService.page(new Page<>(current, size),
                queryWrapper);

        // 查询统计数据
        List<Commission> commissionList = commissionService.list(queryWrapper);
        // 计算统计数据
        List<Long> commissionIds = commissionList.stream().map(Commission::getId).collect(Collectors.toList());
        CommissionStatisticsVO commissionStatisticsVO = commissionService.getCommissionStatistics(commissionIds);
        // 组装返回值
        Map<String, Object> map = new HashMap<>();
        map.put("commissionStatisticsVO", commissionStatisticsVO);
        map.put("page", commissionService.getCommissionVOPage(commissionPage));
        return Result.success(map);
    }

}
