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

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yd.base.feign.client.exchangerate.ApiExchangeRateFeignClient;
import com.yd.base.feign.request.exchangerate.ApiExchangeRateConvertRequest;
import com.yd.base.feign.response.exchangerate.ApiExchangeRateConvertResponse;
import com.yd.common.enums.CommonEnum;
import com.yd.common.exception.BusinessException;
import com.yd.common.result.Result;
import com.yd.common.utils.CodeGenerator;
import com.yd.common.utils.RandomStringGenerator;
import com.yd.csf.api.dto.ApiSalarySplitSummaryPageDTO;
import com.yd.csf.api.service.ApiSalarySplitService;
import com.yd.csf.feign.dto.excel.ApiSalarySplitSummaryExcelDto;
import com.yd.csf.feign.dto.salarysplit.ApiSalarySplitBatchSaveDto;
import com.yd.csf.feign.dto.salarysplit.ApiSalarySplitPageDto;
import com.yd.csf.feign.dto.salarysplit.ApiSalarySplitStatisticsDto;
import com.yd.csf.feign.dto.salarysplit.ApiSalarySplitSummaryPageDto;
import com.yd.csf.feign.request.salarysplit.*;
import com.yd.csf.api.dto.ApiSalarySplitPageListDTO;
import com.yd.csf.feign.response.salarysplit.ApiQueryRemainingResponse;
import com.yd.csf.feign.response.salarysplit.ApiSalarySplitExportSummaryListResponse;
import com.yd.csf.feign.response.salarysplit.ApiSalarySplitQueryRateResponse;
import com.yd.csf.service.model.FortuneAccount;
import com.yd.csf.service.model.SalarySplit;
import com.yd.csf.service.service.FortuneAccountService;
import com.yd.csf.service.service.ISalarySplitService;
import com.yd.oss.feign.client.ApiExcelFeignClient;
import com.yd.oss.feign.dto.ExportParam;
import com.yd.oss.feign.dto.ExportResult;
import com.yd.oss.feign.request.ApiExportRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ApiSalarySplitServiceImpl implements ApiSalarySplitService {

    @Autowired
    private FortuneAccountService fortuneAccountService;

    @Autowired
    private ISalarySplitService iSalarySplitService;

    @Autowired
    private ApiExchangeRateFeignClient apiExchangeRateFeignClient;

    @Autowired
    private ApiExcelFeignClient apiExcelFeignClient;

    /**
     * 分页查询-薪资拆分应发信息汇总列表
     * @param request
     * @return
     */
    @Override
    public Result<ApiSalarySplitSummaryPageDTO> summaryPage(ApiSalarySplitSummaryPageRequest request) {
        ApiSalarySplitSummaryPageDTO response = new ApiSalarySplitSummaryPageDTO();
        // 查询分页信息
        Page<ApiSalarySplitSummaryPageDto> page = new Page<>(request.getPageNo(), request.getPageSize());
        IPage<ApiSalarySplitSummaryPageDto> iPage = iSalarySplitService.summaryPage(page, request);
        response.setPage(iPage);
        //查询薪资拆分业务ID列表
        List<String> salarySplitBizIdList = iSalarySplitService.queryList(request);
        response.setSalarySplitBizIdList(salarySplitBizIdList);
        return Result.success(response);
    }

    /**
     * 分页查询-薪资拆分应发信息列表
     * @param request
     * @return
     */
    @Override
    public Result<ApiSalarySplitPageListDTO> page(ApiSalarySplitPageRequest request) {
        ApiSalarySplitPageListDTO response = new ApiSalarySplitPageListDTO();
        // 查询分页信息
        Page<ApiSalarySplitPageDto> page = new Page<>(request.getPageNo(), request.getPageSize());
        IPage<ApiSalarySplitPageDto> iPage = iSalarySplitService.page(page, request);
        response.setPage(iPage);

        // 查询统计信息
        ApiSalarySplitStatisticsDto statisticsDto = new ApiSalarySplitStatisticsDto();
        FortuneAccount fortuneAccount = fortuneAccountService.queryOne(request.getFortuneAccountBizId());
        // 出账币种
        statisticsDto.setBeSplitCurrency(fortuneAccount != null ? fortuneAccount.getCurrency() : "");

        BigDecimal beSplitAmount = BigDecimal.ZERO;
        if (fortuneAccount != null) {
            // 查询所有拆分记录，计算已拆分总金额
            List<SalarySplit> salarySplits = iSalarySplitService.lambdaQuery()
                    .eq(SalarySplit::getFortuneAccountBizId, request.getFortuneAccountBizId())
                    .list();
            BigDecimal splitTotal = salarySplits.stream()
                    .map(SalarySplit::getFromAmount)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            BigDecimal fortuneAmount = fortuneAccount.getHkdAmount() != null ? fortuneAccount.getHkdAmount() : BigDecimal.ZERO;
            beSplitAmount = fortuneAmount.subtract(splitTotal);
            if (beSplitAmount.compareTo(BigDecimal.ZERO) < 0) {
                beSplitAmount = BigDecimal.ZERO; // 防止负数
            }
        }
        statisticsDto.setBeSplitAmount(beSplitAmount);
        response.setStatisticsDto(statisticsDto);

        return Result.success(response);
    }

    /**
     * 批量保存
     * @param request
     * @return
     */
    @Override
    public Result batchSave(ApiSalarySplitBatchSaveRequest request) {
        //查询出账记录是否存在
        FortuneAccount fortuneAccount = fortuneAccountService.queryOne(request.getFortuneAccountBizId());
        if (fortuneAccount == null) {
            throw new BusinessException("出账记录不存在");
        }
        //薪资拆分应发记录-先删除后新增
        iSalarySplitService.deleteByFortuneAccountBizId(request.getFortuneAccountBizId());

        //批量新增
        if (CollectionUtils.isEmpty(request.getApiSalarySplitBatchSaveDtoList())) {
            return Result.success();
        }
        List<SalarySplit> salarySplitList = new ArrayList<>();
        for (ApiSalarySplitBatchSaveDto dto : request.getApiSalarySplitBatchSaveDtoList()) {
            SalarySplit salarySplit = new SalarySplit();
            BeanUtils.copyProperties(dto,salarySplit);
            //薪资拆分应发表唯一业务ID
            salarySplit.setSalarySplitBizId(RandomStringGenerator.generateBizId16(CommonEnum.UID_TYPE_SALARY_SPLIT.getCode()));
            //发放编号
            salarySplit.setSalarySplitNo(CodeGenerator.generate10Code("SP"));
            //出账记录业务id
            salarySplit.setFortuneAccountBizId(request.getFortuneAccountBizId());
            salarySplitList.add(salarySplit);
        }
        iSalarySplitService.saveOrUpdateBatch(salarySplitList);
        return Result.success();
    }

    /**
     * 查询-原币种剩余总金额和原币种
     * @param request
     * @return
     */
    @Override
    public Result<ApiQueryRemainingResponse> queryRemaining(ApiQueryRemainingRequest request) {
        // 1. 校验出账记录是否存在
        FortuneAccount fortuneAccount = fortuneAccountService.queryOne(request.getFortuneAccountBizId());
        if (fortuneAccount == null) {
            throw new BusinessException("出账记录不存在");
        }

        // 2. 计算本次拟拆分金额总和（使用请求中的 fromAmountList）
        BigDecimal splitTotal = BigDecimal.ZERO;
        if (CollectionUtils.isNotEmpty(request.getFromAmountList())) {
            splitTotal = request.getFromAmountList().stream()
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
        }

        // 3. 计算剩余可拆金额（账户总额 - 本次拟拆分总额）
        BigDecimal fortuneAmount = fortuneAccount.getHkdAmount() != null ? fortuneAccount.getHkdAmount() : BigDecimal.ZERO;
        BigDecimal beSplitAmount = fortuneAmount.subtract(splitTotal);
        if (beSplitAmount.compareTo(BigDecimal.ZERO) < 0) {
            beSplitAmount = BigDecimal.ZERO; // 防止负数
        }

        // 4. 封装响应
        ApiQueryRemainingResponse response = new ApiQueryRemainingResponse();
        response.setCurrency(fortuneAccount.getCurrency());
        response.setFromAmount(beSplitAmount);
        return Result.success(response);
    }

    /**
     * 查询-原币种和原币种金额——>目标币种即时汇率和目标币种金额
     * @param request
     * @return
     */
    @Override
    public Result<ApiSalarySplitQueryRateResponse> queryRate(ApiSalarySplitQueryRateRequest request) {
        //查询出账记录是否存在
        FortuneAccount fortuneAccount = fortuneAccountService.queryOne(request.getFortuneAccountBizId());
        if (fortuneAccount == null) {
            throw new BusinessException("出账记录不存在");
        }
        ApiExchangeRateConvertRequest convertRequest = new ApiExchangeRateConvertRequest();
        //原币种金额
        convertRequest.setAmount(request.getFromAmount());
        //原币种
        convertRequest.setFromCurrency(fortuneAccount.getCurrency());
        //目标币种
        convertRequest.setToCurrency(request.getToCurrency());
        //调用远程转换接口
        Result<ApiExchangeRateConvertResponse> result = apiExchangeRateFeignClient.convert(convertRequest);
        if (result != null && result.getData() != null) {
            ApiSalarySplitQueryRateResponse response = new ApiSalarySplitQueryRateResponse();
            BeanUtils.copyProperties(result.getData(),response);
            return Result.success(response);
        }
        return Result.success();
    }

    /**
     * 导出-薪资拆分应发信息汇总列表
     * @param request
     * @return
     */
    @Override
    public Result<ApiSalarySplitExportSummaryListResponse> export(ApiSalarySplitExportSummaryListRequest request) {
        // 查询数据
        List<ApiSalarySplitSummaryPageDto> dataList = iSalarySplitService.summaryList(request);
        log.info("导出-薪资拆分应发信息汇总列表:dataList,{}", JSON.toJSONString(dataList));
        List<ApiSalarySplitSummaryExcelDto> excelDtoList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(dataList)) {
            excelDtoList = dataList.stream().map(dto -> {
                ApiSalarySplitSummaryExcelDto excelDto = new ApiSalarySplitSummaryExcelDto();
                BeanUtils.copyProperties(dto,excelDto);
                return excelDto;
            }).collect(Collectors.toList());
        }
        log.info("导出-薪资拆分应发信息汇总列表:excelDtoList,{}", JSON.toJSONString(excelDtoList));
        // 构建导出参数
        ExportParam exportParam = new ExportParam();
        // 指定需要导出的字段（字段名必须与 DTO 中的属性名一致）
        exportParam.setFieldNames(Arrays.asList(
                "salarySplitNo","brokerName","team","fromAmount",
                "currency","exchangeRate","toAmount","toCurrency",
                "fortuneAccountMonth","billOrg","hkdAmount","fortuneAccountBizId"
        ));
        exportParam.setFileName("薪资拆分应发信息汇总");
        exportParam.setUploadToOss(true);
        exportParam.setOssPath("exports/salary_split/");

        // 构建请求对象
        ApiExportRequest exportRequest = new ApiExportRequest();
        exportRequest.setDataList(excelDtoList);
        exportRequest.setEntityClass(ApiSalarySplitSummaryExcelDto.class);
        exportRequest.setExportParam(exportParam);

        log.info("导出-薪资拆分应发信息汇总列表:exportRequest,{}", JSON.toJSONString(exportRequest));
        // 远程调用导出接口
        Result<ExportResult> result = apiExcelFeignClient.export(exportRequest);
        if (result.getCode() != 200 || result.getData() == null) {
            throw new BusinessException("导出失败：" + result.getMsg());
        }

        ExportResult exportResult = result.getData();
        if (!exportResult.getSuccess()) {
            throw new BusinessException("导出失败：" + exportResult.getErrorMsg());
        }

        log.info("导出-薪资拆分应发信息汇总列表:exportResult,{}", JSON.toJSONString(exportResult));
        // 封装响应
        ApiSalarySplitExportSummaryListResponse response = new ApiSalarySplitExportSummaryListResponse();
        response.setUrl(exportResult.getOssUrl());
//        response.setFileSize(exportResult.getFileSize());
//        response.setTotalCount(dataList.size());
        return Result.success(response);
    }

}
