package com.yd.csf.api.controller;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
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.CommonEnum;
import com.yd.common.enums.ResultCode;
import com.yd.common.exception.BusinessException;
import com.yd.common.result.Result;
import com.yd.common.utils.RandomStringGenerator;
import com.yd.csf.api.dto.FortuneImportDTO;
import com.yd.csf.service.common.ErrorCode;
import com.yd.csf.service.dto.*;
import com.yd.csf.service.enums.FortuneStatusEnum;
import com.yd.csf.service.model.Fortune;
import com.yd.csf.service.model.FortuneAccount;
import com.yd.csf.service.model.FortuneAccountEditRecord;
import com.yd.csf.service.service.FortuneAccountEditRecordService;
import com.yd.csf.service.service.FortuneAccountService;
import com.yd.csf.service.service.FortuneService;
import com.yd.csf.service.vo.FortuneVO;
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.ObjectUtils;
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 javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

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

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

    @Resource
    private FortuneService fortuneService;

    @Resource
    private FortuneAccountService fortuneAccountService;

    @Resource
    private FortuneAccountEditRecordService fortuneAccountEditRecordService;


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

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

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

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

        return Result.success(true);
    }

    /**
     * 处理导入的数据
     */
    private void processData(List<FortuneImportDTO> dataList, String loginUserId) {
        List<Fortune> addList = new ArrayList<>();
        List<Fortune> updateList = new ArrayList<>();
        for (FortuneImportDTO data : dataList) {
            // 数据验证
            Fortune entity = FortuneImportDTO.convertToEntity(data, loginUserId);
            if (StringUtils.isBlank(entity.getFortuneBizId())) {
                entity.setFortuneBizId(RandomStringGenerator.generateBizId16(CommonEnum.UID_TYPE_FORTUNE.getCode()));
                addList.add(entity);
            } else {
                updateList.add(entity);
            }
        }
        // 批量保存
        if (CollectionUtils.isNotEmpty(addList)) {
            fortuneService.saveBatch(addList);
        }
        // 批量更新
        if (CollectionUtils.isNotEmpty(updateList)) {
            // 先根据bizId查询已存在的记录
            List<String> updateBizIdList = updateList.stream().map(Fortune::getFortuneBizId).collect(Collectors.toList());
            List<Fortune> existingList = fortuneService.lambdaQuery().in(Fortune::getFortuneBizId, updateBizIdList).list();
            // 根据 bizId 映射到 entity
            Map<String, Fortune> existingMap = existingList.stream().collect(Collectors.toMap(Fortune::getFortuneBizId, f -> f));
            // 合并更新数据
            for (Fortune updateEntity : updateList) {
                Fortune existingEntity = existingMap.get(updateEntity.getFortuneBizId());
                if (existingEntity != null) {
                    // 合并更新字段
                    existingEntity.setPolicyNo(updateEntity.getPolicyNo());
                    existingEntity.setFortunePeriod(updateEntity.getFortunePeriod());
                    existingEntity.setFortuneTotalPeriod(updateEntity.getFortuneTotalPeriod());
                    existingEntity.setFortuneName(updateEntity.getFortuneName());
                    existingEntity.setAmount(updateEntity.getAmount());
                    existingEntity.setCurrency(updateEntity.getCurrency());
                    existingEntity.setBroker(updateEntity.getBroker());
                    existingEntity.setTeam(updateEntity.getTeam());
                    existingEntity.setRemark(updateEntity.getRemark());
                }
            }
            // 批量更新
            fortuneService.updateBatchById(existingList);
        }
    }

    /**
     * 创建发佣
     *
     * @param fortuneAddRequest
     * @param request
     * @return
     */
    @Operation(summary = "创建发佣")
    @PostMapping("/add")
    public Result<Boolean> addFortune(@RequestBody FortuneAddRequest fortuneAddRequest, HttpServletRequest request) {
        if (fortuneAddRequest == null) {
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), ErrorCode.PARAMS_ERROR.getMessage());
        }
        return Result.success(fortuneService.addFortune(fortuneAddRequest));
    }

    /**
     * 批量创建发佣
     *
     * @param fortuneAddRequestList
     * @param request
     * @return
     */
    @Operation(summary = "批量创建发佣")
    @PostMapping("/addBatch")
    public Result<Boolean> addFortuneBatch(@RequestBody List<FortuneAddRequest> fortuneAddRequestList, HttpServletRequest request) {
        if (CollectionUtils.isEmpty(fortuneAddRequestList)) {
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), "发佣数据不能为空");
        }
        return Result.success(fortuneService.addFortuneBatch(fortuneAddRequestList));
    }

    /**
     * 下载选中的发佣数据
     *
     * @param fortuneDownloadRequest
     * @param response
     * @return
     */
    @Operation(summary = "下载选中的发佣数据")
    @PostMapping("/download/raw")
    public void downloadFortune(@RequestBody FortuneDownloadRequest fortuneDownloadRequest, HttpServletResponse response) throws IOException {
        if (CollectionUtils.isEmpty(fortuneDownloadRequest.getFortuneBizIdList())) {
            throw new BusinessException(ResultCode.PARAMS_ERROR.getCode(), "请选择要下载的发佣数据");
        }
        fortuneService.downloadFortune(fortuneDownloadRequest, response);
    }

    /**
     * 生成出账清单（按人）
     *
     * @param fortuneDownloadRequest
     * @param response
     * @return
     */
    @Operation(summary = "生成出账清单")
    @PostMapping("/download/account")
    public Result<Boolean> downloadAccount(@RequestBody FortuneDownloadRequest fortuneDownloadRequest, HttpServletResponse response) throws IOException {
        if (CollectionUtils.isEmpty(fortuneDownloadRequest.getFortuneBizIdList())) {
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), "请选择要出账的发佣数据");
        }
        if (StringUtils.isBlank(fortuneDownloadRequest.getActualPayoutDate())) {
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), "请输入出账年月（实）");
        }

        fortuneService.downloadAccount(fortuneDownloadRequest, response);

//            // 设置响应类型为 JSON，而不是文件流
//            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
//            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
//            response.setCharacterEncoding("UTF-8");
//
//            Result<String> errorResult = Result.fail(
//                    ResultCode.FAIL.getCode(),
//                    e.getMessage()
//            );
//
//            response.getWriter().write(new ObjectMapper().writeValueAsString(errorResult));

        return Result.success(true);
    }


    /**
     * 分页获取出账列表
     *
     * @param fortuneAccountQueryRequest
     * @param request
     * @return
     */
    @PostMapping("/list/page/fortuneAccount")
    @Operation(summary = "分页获取出账列表")
    public Result<Map<String, Object>> listAccountByPage(@RequestBody FortuneAccountQueryRequest fortuneAccountQueryRequest,
                                                            HttpServletRequest request) {
        long current = fortuneAccountQueryRequest.getPageNo();
        long size = fortuneAccountQueryRequest.getPageSize();

        // 查询数据库
        QueryWrapper<FortuneAccount> queryWrapper = fortuneAccountService.getQueryWrapper(fortuneAccountQueryRequest);
        Page<FortuneAccount> fortunePage = fortuneAccountService.page(new Page<>(current, size),
                queryWrapper);
        // 统计数据 总金额、总人数
        List<FortuneAccount> fortuneAccountList = fortuneAccountService.list(queryWrapper);
        FortuneAccountStatisticsVO statisticsVO = fortuneAccountService.getFortuneAccountStatistics(fortuneAccountList.stream()
                .map(FortuneAccount::getId)
                .collect(Collectors.toList()));
        // 获取封装类
        Map<String, Object> result = new HashMap<>();
        result.put("page", fortuneAccountService.getFortuneAccountVOPage(fortunePage));
        result.put("statisticsVO", statisticsVO);
        return Result.success(result);
    }

    /**
     * 统计数据 总金额、总人数
     *
     * @param fortuneAccountQueryRequest
     * @param request
     * @return
     */
    @PostMapping("/fortuneAccount/statistics")
    @Operation(summary = "统计数据 总金额、总人数")
    public Result<FortuneAccountStatisticsVO> getFortuneAccountStatistics(@RequestBody FortuneAccountStatisticsQueryRequest fortuneAccountQueryRequest,
                                                            HttpServletRequest request) {
        return Result.success(fortuneAccountService.getFortuneAccountStatistics(fortuneAccountQueryRequest.getFortuneAccountIdList()));
    }


    /**
     * 创建出账
     *
     * @param fortuneAccountAddRequest
     * @param request
     * @return
     */
    @Operation(summary = "创建出账")
    @PostMapping("/add/fortuneAccount")
    public Result<Map<String, Object>> addFortuneAccount(@RequestBody FortuneAccountAddRequest fortuneAccountAddRequest, HttpServletRequest request) {
        if (fortuneAccountAddRequest == null) {
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), ErrorCode.PARAMS_ERROR.getMessage());
        }
        return Result.success(fortuneAccountService.addFortuneAccount(fortuneAccountAddRequest));
    }

    /**
     * 删除出账
     *
     * @param deleteRequest
     * @param request
     * @return
     */
    @PostMapping("/delete/fortuneAccount")
    @Operation(summary = "删除出账")
    public Result<Boolean> deleteFortuneAccount(@RequestBody FortuneAccountDeleteRequest deleteRequest, HttpServletRequest request) {
        if (StringUtils.isBlank(deleteRequest.getFortuneAccountBizId())) {
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), ErrorCode.PARAMS_ERROR.getMessage());
        }
        String fortuneAccountBizId = deleteRequest.getFortuneAccountBizId();

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

        // 判断是否存在
        FortuneAccount oldFortuneAccount = fortuneAccountService.getByFortuneAccountBizId(fortuneAccountBizId);
        if (oldFortuneAccount == null) {
            return Result.fail(ErrorCode.NOT_FOUND_ERROR.getCode(), ErrorCode.NOT_FOUND_ERROR.getMessage());
        }
        // 仅本人或管理员可删除
//        if (!oldFna.getUserId().equals(loginUserId) && !userService.isAdmin(request)) {
//            return Result.fail(ErrorCode.NO_AUTH_ERROR.getCode(), ErrorCode.NO_AUTH_ERROR.getMessage());
//        }
        // 操作数据库
        boolean result = fortuneAccountService.removeById(oldFortuneAccount);
        if (!result) {
            return Result.fail(ErrorCode.OPERATION_ERROR.getCode(), ErrorCode.OPERATION_ERROR.getMessage());
        }
        return Result.success(result);
    }

    /**
     * 修改出账信息
     *
     * @param fortuneUpdateRequest
     * @return
     */
    @PostMapping("/update/fortuneAccount")
    @Operation(summary = "修改出账信息")
    public Result<Boolean> updateFortuneAccount(@RequestBody FortuneAccountUpdateRequest fortuneUpdateRequest) {
        if (StringUtils.isBlank(fortuneUpdateRequest.getFortuneAccountBizId())) {
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), "出账数据业务ID不能为空");
        }
        return Result.success(fortuneAccountService.updateFortuneAccount(fortuneUpdateRequest));
    }

    /**
     * 修订记录
     *
     * @param queryRequest
     * @return
     */
    @PostMapping("/editRecords/fortuneAccount")
    @Operation(summary = "修订记录")
    public Result<Page<FortuneAccountEditRecord>> getFortuneAccountEditRecords(@RequestBody FortuneAccountEditRecordQueryRequest queryRequest) {
        if (StringUtils.isBlank(queryRequest.getFortuneAccountBizId())) {
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), "fortuneAccountBizId不能为空");
        }
        Page<FortuneAccountEditRecord> page = fortuneAccountEditRecordService.page(new Page<>(queryRequest.getPageNo(), queryRequest.getPageSize()),
                new QueryWrapper<FortuneAccountEditRecord>()
                        .eq("fortune_account_biz_id", queryRequest.getFortuneAccountBizId()));
        return Result.success(page);
    }

    /**
     * 完成出账
     *
     * @param completeFortuneAccountRequest
     * @return
     */
    @PostMapping("/complete/fortuneAccount")
    @Operation(summary = "完成出账")
    public Result<Boolean> completeFortuneAccount(@RequestBody CompleteFortuneAccountRequest completeFortuneAccountRequest) {
        if (CollectionUtils.isEmpty(completeFortuneAccountRequest.getFortuneAccountBizIdList())) {
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), "出账数据业务ID列表不能为空");
        }
        return Result.success(fortuneAccountService.completeFortuneAccount(completeFortuneAccountRequest));
    }

    /**
     * 删除发佣
     *
     * @param deleteRequest
     * @param request
     * @return
     */
    @PostMapping("/delete")
    @Operation(summary = "删除发佣")
    public Result<Boolean> deleteFortune(@RequestBody FortuneDeleteRequest deleteRequest, HttpServletRequest request) {
        if (StringUtils.isBlank(deleteRequest.getFortuneBizId())) {
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), ErrorCode.PARAMS_ERROR.getMessage());
        }
        String fortuneBizId = deleteRequest.getFortuneBizId();

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

        // 判断是否存在
        Fortune oldFortune = fortuneService.getByFortuneBizId(fortuneBizId);
        if (oldFortune == null) {
            return Result.fail(ErrorCode.NOT_FOUND_ERROR.getCode(), ErrorCode.NOT_FOUND_ERROR.getMessage());
        }
        // 仅本人或管理员可删除
//        if (!oldFna.getUserId().equals(loginUserId) && !userService.isAdmin(request)) {
//            return Result.fail(ErrorCode.NO_AUTH_ERROR.getCode(), ErrorCode.NO_AUTH_ERROR.getMessage());
//        }
        // 操作数据库
        boolean result = fortuneService.removeById(oldFortune);
        if (!result) {
            return Result.fail(ErrorCode.OPERATION_ERROR.getCode(), ErrorCode.OPERATION_ERROR.getMessage());
        }
        return Result.success(result);
    }

    /**
     * 更新保单发佣（检核操作）
     *
     * @param fortuneUpdateRequest
     * @return
     */
    @PostMapping("/update")
    @Operation(summary = "更新保单发佣信息（检核操作）")
    public Result<Boolean> updateFortune(@RequestBody FortuneUpdateRequest fortuneUpdateRequest) {
        if (fortuneUpdateRequest == null || fortuneUpdateRequest.getFortuneBizId() == null) {
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), "fortuneBizId不能为空");
        }
        return Result.success(fortuneService.updateFortune(fortuneUpdateRequest));
    }

    /**
     * 分期出账
     *
     * @param fortuneSplitRequest 分期出账请求
     * @return
     */
    @PostMapping("/split")
    @Operation(summary = "分期出账")
    public Result<Boolean> splitFortune(@RequestBody FortuneSplitRequest fortuneSplitRequest) {
        if (fortuneSplitRequest == null || CollectionUtils.isEmpty(fortuneSplitRequest.getFortuneSplitDtoList())) {
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), "分期出账请求不能为空");
        }
        // 操作数据库
        return Result.success(fortuneService.splitFortune(fortuneSplitRequest));
    }

    /**
     * 修改设置出账年月（实）），设置完成后，更新到应付款管理明细中
     *
     * @param editActualPayoutDateRequest
     * @return
     */
    @PostMapping("/edit/actual_payout_date")
    @Operation(summary = "修改设置出账年月（实），设置完成后，更新到应付款管理明细中")
    public Result<Boolean> editActualPayoutDate(@RequestBody EditActualPayoutDateRequest editActualPayoutDateRequest) {
        if (editActualPayoutDateRequest == null || StringUtils.isBlank(editActualPayoutDateRequest.getFortuneBizId())) {
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), "fortuneBizId 不能为空");
        }
        if (StringUtils.isBlank(editActualPayoutDateRequest.getActualPayoutDate())) {
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), "actualPayoutDate 不能为空");
        }
        return Result.success(fortuneService.editActualPayoutDate(editActualPayoutDateRequest));
    }

    /**
     * 修改结算汇率，设置完成后，更新到应付款管理明细中
     *
     * @param editExchangeRateRequest
     * @return
     */
    @PostMapping("/edit/exchange_rate")
    @Operation(summary = "修改结算汇率，设置完成后，更新到应付款管理明细中")
    public Result<Boolean> editExchangeRate(@RequestBody EditExchangeRateRequest editExchangeRateRequest) {
        if (editExchangeRateRequest == null || StringUtils.isBlank(editExchangeRateRequest.getFortuneBizId())) {
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), "fortuneBizId 不能为空");
        }
        if (editExchangeRateRequest.getExchangeRate() == null) {
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), "exchangeRate 不能为空");
        }
        if (editExchangeRateRequest.getHkdAmount() == null) {
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), "hkdAmount 不能为空");
        }
        return Result.success(fortuneService.editExchangeRate(editExchangeRateRequest));
    }

    /**
     * 修改出账状态
     *
     * @param fortuneStatusUpdateRequest
     * @return
     */
    @PostMapping("/update/status")
    @Operation(summary = "修改出账状态")
    public Result<Boolean> updateFortuneStatus(@RequestBody FortuneStatusUpdateRequest fortuneStatusUpdateRequest) {
        if (fortuneStatusUpdateRequest == null || CollectionUtils.isEmpty(fortuneStatusUpdateRequest.getFortuneBizIdList())) {
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), ErrorCode.PARAMS_ERROR.getMessage());
        }
        return Result.success(fortuneService.updateFortuneStatus(fortuneStatusUpdateRequest));
    }

    /**
     * 出账检核页面-分页获取保单发佣列表（VO）
     *
     * @param fortuneQueryRequest
     * @param request
     * @return
     */
    @PostMapping("/list/page/vo")
    @Operation(summary = "出账检核页面-分页获取保单发佣列表（VO）")
    public Result<FortunePageResponse> listFortuneByPage(@RequestBody FortuneQueryRequest fortuneQueryRequest,
                                                          HttpServletRequest request) {
        long current = fortuneQueryRequest.getPageNo();
        long size = fortuneQueryRequest.getPageSize();

        // 查询条件
        Wrapper<Fortune> queryWrapper = fortuneService.getQueryWrapper(fortuneQueryRequest);
        Page<Fortune> fortunePage = fortuneService.page(new Page<>(current, size),
                queryWrapper);

        // 查询统计数据
        List<Fortune> fortuneList = fortuneService.list(queryWrapper);
        FortuneStatisticsVO statisticsVO = fortuneService.getFortuneStatistics(fortuneList.stream().map(Fortune::getId).collect(Collectors.toList()));

        // 组装返回结果
        FortunePageResponse response = new FortunePageResponse();
        response.setStatisticsVO(statisticsVO);
        response.setPage(fortuneService.getFortuneVOPage(fortunePage));
        return Result.success(response);
    }

    /**
     * 出账检核页面-计算统计数据 总出账金额、对应这些保单的总入账金额、总保单数
     */
    @PostMapping("/statistics")
    @Operation(summary = "出账检核页面-计算统计数据 总出账金额、对应这些保单的总入账金额、总保单数")
    public Result<FortuneStatisticsVO> getFortuneStatistics(@RequestBody FortuneStatisticsRequest statisticsRequest) {
        if (CollectionUtils.isEmpty(statisticsRequest.getFortuneIdList())) {
            return Result.fail(ErrorCode.PARAMS_ERROR.getCode(), "fortuneId列表不能为空");
        }
        return Result.success(fortuneService.getFortuneStatistics(statisticsRequest.getFortuneIdList()));
    }

    /**
     * 出账记录
     *
     * @param fortuneQueryRequest
     * @param request
     * @return
     */
    @PostMapping("/pageByExpectedFortuneBizId")
    @Operation(summary = "出账记录")
    public Result<Page<FortuneVO>> pageByExpectedFortuneBizId(@RequestBody FortuneQueryRequest fortuneQueryRequest,
                                                      HttpServletRequest request) {
        if (ObjectUtils.isEmpty(fortuneQueryRequest.getExpectedFortuneBizId())) {
            return Result.fail(ResultCode.PARAMS_ERROR.getCode(), "expectedFortuneBizId 不能为空");
        }
        long current = fortuneQueryRequest.getPageNo();
        long size = fortuneQueryRequest.getPageSize();
        // 查询列表数据
        QueryWrapper<Fortune> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("expected_fortune_biz_id", fortuneQueryRequest.getExpectedFortuneBizId());
        queryWrapper.in("status", Arrays.asList(FortuneStatusEnum.CHECKED.getItemValue(), FortuneStatusEnum.SENT.getItemValue()));
        Page<Fortune> fortunePage = fortuneService.page(new Page<>(current, size),
                queryWrapper);
        // 组装返回值
        return Result.success(fortuneService.getFortuneVOPage(fortunePage));
    }
}
