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.fasterxml.jackson.databind.ObjectMapper;
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.model.Fortune;
import com.yd.csf.service.model.FortuneAccount;
import com.yd.csf.service.service.FortuneAccountService;
import com.yd.csf.service.service.FortuneService;
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.http.MediaType;
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.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("/fortune")
@Tag(name = "保单发佣接口")
public class ApiFortuneController {

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

    @Resource
    private FortuneService fortuneService;

    @Resource
    private FortuneAccountService fortuneAccountService;


    @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 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 void downloadAccount(@RequestBody FortuneDownloadRequest fortuneDownloadRequest, HttpServletResponse response) throws IOException {
        if (CollectionUtils.isEmpty(fortuneDownloadRequest.getFortuneBizIdList())) {
            throw new BusinessException(ResultCode.PARAMS_ERROR.getCode(), "请选择要出账的发佣数据");
        }
        try {
            fortuneService.downloadAccount(fortuneDownloadRequest, response);
        } catch (Exception e) {
            // 设置响应类型为 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));
        }
    }

    /**
     * 分页获取出账列表
     *
     * @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 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(), ErrorCode.PARAMS_ERROR.getMessage());
        }
        return Result.success(fortuneService.updateFortune(fortuneUpdateRequest));
    }

    /**
     * 修改发佣状态
     *
     * @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));
    }


    /**
     * 根据 fortuneBizId 获取保单发佣（封装类）
     *
     * @param fortuneBizId
     * @return
     */
//    @GetMapping("/get/vo")
//    @Operation(summary = "根据 policyBizId 获取保单发佣详情")
//    public Result<PolicyFollowVO> getPolicyFollowByPolicyBizId(@RequestParam("fortuneBizId") String fortuneBizId, HttpServletRequest request) {
//        if (fortuneBizId == 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 fortuneQueryRequest
     * @param request
     * @return
     */
    @PostMapping("/list/page/vo")
    @Operation(summary = "分页获取保单发佣列表")
    public Result<Map<String, Object>> 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()));

        // 组装返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("statisticsVO", statisticsVO);
        result.put("page", fortuneService.getFortuneVOPage(fortunePage));
        return Result.success(result);
    }

    /**
     * 计算统计数据 总出账金额、对应这些保单的总入账金额、总保单数
     */
    @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()));
    }
}
