package com.sckw.payment.service.wallet;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.sckw.core.common.enums.StringConstant;
import com.sckw.core.model.enums.EntTypeEnum;
import com.sckw.core.model.enums.SystemTypeEnum;
import com.sckw.core.web.context.LoginUserHolder;
import com.sckw.core.web.response.result.PageDataResult;
import com.sckw.payment.enums.PrepayTypEnum;
import com.sckw.payment.model.KwpBizWallet;
import com.sckw.payment.model.KwpBizWalletPrepay;
import com.sckw.payment.repose.KwpBizWalletPageResponse;
import com.sckw.payment.repose.KwpBizWalletPrepayPageResponse;
import com.sckw.payment.repose.vo.KwpBizWalletPrepayExcelVO;
import com.sckw.payment.repose.vo.KwpBizWalletVO;
import com.sckw.payment.repository.KwpBizWalletPrepayRepository;
import com.sckw.payment.repository.KwpBizWalletRepository;
import com.sckw.payment.request.KwpBizWalletPrepayQueryRequest;
import com.sckw.payment.request.KwpBizWalletPrepayRequest;
import com.sckw.payment.request.KwpBizWalletQueryRequest;
import com.sckw.payment.request.KwpBizWalletSaveRequest;
import com.sckw.system.api.RemoteSystemService;
import com.sckw.system.api.model.dto.res.EntTypeResDto;
import com.sckw.system.api.model.dto.res.KwsEntDeptDto;
import com.sckw.system.api.model.dto.res.KwsEnterpriseResDto;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Author: donglang
 * Time: 2025-11-03
 * Des: 钱包管理服务
 * Version: 1.0
 */

@Slf4j
@Service
@RequiredArgsConstructor
public class KwpBizWalletService {

    private final KwpBizWalletRepository kwpBizWalletRepository;

    private final KwpBizWalletPrepayRepository kwpBizWalletPrepayRepository;

    @DubboReference(version = "1.0.0", group = "design", check = false)
    private RemoteSystemService remoteSystemService;


    private static final String OFFLINE_WALLET = "线下钱包";

    /**
     * 分页查询钱包明细
     */
    public PageDataResult<KwpBizWalletPageResponse> pageBizWalletList(KwpBizWalletQueryRequest request) {
        log.info("分页查询钱包明细，入参：{}", JSONObject.toJSONString(request));
        int systemType = LoginUserHolder.getSystemType();

        //非管理端,返回空分页结果
        if (systemType != SystemTypeEnum.COMPANY.getCode()) {
            log.info("当前登录企业非管理端：{}", SystemTypeEnum.COMPANY.getCode());
            return PageDataResult.empty(request.getPage(), request.getPageSize());
        }

        //查询当前登录企业
        EntTypeResDto entTypeResDto = remoteSystemService.queryEntTypeById(LoginUserHolder.getEntId());
        if (entTypeResDto == null) {
            throw new RuntimeException("entId:" + LoginUserHolder.getEntId() + ", 企业信息不存在！");
        }
        List<KwpBizWalletPageResponse> walletList = new ArrayList<>();
        if (entTypeResDto.getType() == EntTypeEnum.SUPPLIER.getCode()) {
            //供应商及子企业
            walletList = querySupWallet(entTypeResDto);
        } else if (entTypeResDto.getType() == EntTypeEnum.PURCHASER.getCode()) {
            //采购商企业
            walletList = queryProWallet(entTypeResDto.getEntId());
        }

        //模糊查询过滤
        List<KwpBizWalletPageResponse> walletResponses = filterByFuzzyName(walletList, request);

        //排序、内存分页
        walletResponses.sort(Comparator.comparing(KwpBizWalletPageResponse::getEntId));
        List<List<KwpBizWalletPageResponse>> pageList = Lists.partition(walletResponses, request.getPageSize());
        List<KwpBizWalletPageResponse> walletPageList = pageList.size() >= request.getPage() ?
                pageList.get(request.getPage() - 1) : Collections.emptyList();

        PageDataResult<KwpBizWalletPageResponse> walletPageResponse = PageDataResult.success(request.getPage(), request.getPageSize(), (long) walletPageList.size(), walletPageList);
        log.info("分页查询钱包明细成功，结果：{}", JSONObject.toJSONString(walletPageResponse));
        return walletPageResponse;
    }


    /**
     * 查询供应商企业钱包信息
     *
     * @param entTypeResDto
     * @return
     */
    private List<KwpBizWalletPageResponse> querySupWallet(EntTypeResDto entTypeResDto) {
        List<Long> entIds = new ArrayList<>();
        entIds.add(entTypeResDto.getEntId());
        //查询供应商的子级企业
        List<KwsEntDeptDto> kwsEntDeptDtoList = remoteSystemService.queryEntDeptByPid(entTypeResDto.getEntId());
        List<Long> subEntId = kwsEntDeptDtoList.stream().map(KwsEntDeptDto::getEntId).collect(Collectors.toList());
        entIds.addAll(subEntId);

        //查询供应企业所关联的钱包数据
        LambdaQueryWrapper<KwpBizWallet> queryWrapper = Wrappers.<KwpBizWallet>lambdaQuery()
                .in(KwpBizWallet::getSupEntId, entIds);

        List<KwpBizWallet> bizWalletList = kwpBizWalletRepository.list(queryWrapper);
        if (bizWalletList == null || CollectionUtils.isEmpty(bizWalletList)) {
            log.info("当前供应企业无子级企业，entId：{}", entTypeResDto.getEntId());
            return new ArrayList<>();
        }

        List<KwpBizWalletPageResponse> supWalletList = getAndConvertWallet(entIds, bizWalletList);
        log.info("供应企业钱包信息结果：{}", JSONObject.toJSONString(supWalletList));
        return supWalletList;
    }

    /**
     * 查询采购商企业钱包信息
     *
     * @param entId
     * @return
     */
    private List<KwpBizWalletPageResponse> queryProWallet(Long entId) {
        //查询采购企业所关联的钱包数据
        LambdaQueryWrapper<KwpBizWallet> queryWrapper = Wrappers.<KwpBizWallet>lambdaQuery()
                .in(KwpBizWallet::getProEntId, entId);
        List<KwpBizWallet> bizWalletList = kwpBizWalletRepository.list(queryWrapper);
        if (bizWalletList == null || bizWalletList.isEmpty()) {
            log.info("当前采购企业无钱包数据，entId：{}", entId);
            return new ArrayList<>();
        }

        //查询钱包所关联的供应商企业id
        List<Long> entIds = bizWalletList.stream().map(KwpBizWallet::getSupEntId).collect(Collectors.toList());

        List<KwpBizWalletPageResponse> proWallet = getAndConvertWallet(entIds, bizWalletList);
        log.info("采购企业钱包信息结果：{}", JSONObject.toJSONString(proWallet));
        return proWallet;
    }


    /**
     * 获取钱包数据
     *
     * @param entIds
     * @param bizWalletList
     * @return
     */
    private List<KwpBizWalletPageResponse> getAndConvertWallet(List<Long> entIds, List<KwpBizWallet> bizWalletList) {

        //根据供应企业id分组
        Map<Long, List<KwpBizWallet>> walletGroupBySup = bizWalletList.stream().collect(
                Collectors.groupingBy(KwpBizWallet::getSupEntId));

        List<KwpBizWalletPageResponse> walletList = new ArrayList<>();
        for (Long id : entIds) {
            List<KwpBizWallet> walletGroupList = walletGroupBySup.getOrDefault(id, new ArrayList<>());
            if (walletGroupList.isEmpty()) {
                continue;
            }
            KwpBizWalletPageResponse walletPageResp = new KwpBizWalletPageResponse();
            walletPageResp.setEntId(id);
            //企业名称
            walletPageResp.setEntName(queryEntById(id));
            //钱包总数
            walletPageResp.setWalletNum(walletGroupList.size());
            //总余额
            BigDecimal totalAmount = calTotalAmount(walletGroupList);
            walletPageResp.setTotalAmount(totalAmount);
            //钱包信息
            List<KwpBizWalletVO> bizWalletVOList = conversionWallet(walletGroupList);
            walletPageResp.setWalletVOList(bizWalletVOList);

            walletList.add(walletPageResp);
        }
        return walletList;
    }


    /**
     * 计算总余额
     */
    private BigDecimal calTotalAmount(List<KwpBizWallet> wallets) {
        return wallets.stream().map(w ->
                w.getAmount().add(w.getPrepayAmount())).reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    /**
     * 钱包信息转换
     *
     * @param walletGroupList
     * @return
     */
    private List<KwpBizWalletVO> conversionWallet(List<KwpBizWallet> walletGroupList) {
        List<KwpBizWalletVO> walletVOList = walletGroupList.stream().map(wallet -> {
            KwpBizWalletVO walletVO = KwpBizWalletVO.toPageResp(wallet);
            walletVO.setSupEntName(queryEntById(wallet.getSupEntId()));
            walletVO.setProEntName(queryEntById(wallet.getProEntId()));
            return walletVO;
        }).collect(Collectors.toList());

        walletVOList.sort(Comparator.comparing(KwpBizWalletVO::getCreateTime));
        return walletVOList;
    }


    /**
     * 模糊查询过滤（供应商企业名称、采购商企业名称）
     */
    private List<KwpBizWalletPageResponse> filterByFuzzyName(List<KwpBizWalletPageResponse> walletList, KwpBizWalletQueryRequest request) {
        if (CollectionUtils.isEmpty(walletList)) {
            return walletList;
        }
        return walletList.stream()
                .map(wallet -> {
                    List<KwpBizWalletVO> filteredVOs = matchesAllConditions(request, wallet);
                    wallet.setWalletVOList(filteredVOs);
                    return wallet;
                })
                // 过滤二级列表为空的一级供应商
                .filter(wallet -> !wallet.getWalletVOList().isEmpty())
                .collect(Collectors.toList());
    }


    /**
     * 过滤条件
     *
     * @param request
     * @param wallet
     * @return
     */
    private static List<KwpBizWalletVO> matchesAllConditions(KwpBizWalletQueryRequest request, KwpBizWalletPageResponse wallet) {
        List<KwpBizWalletVO> filteredVOs = wallet.getWalletVOList().stream().filter(vo -> {
            boolean matches = true;
            // 过滤供应商企业ID
            if (matches && request.getSupEntId() != null) {
                matches = vo.getSupEntId() != null && vo.getSupEntId().equals(request.getSupEntId());
            }
            // 过滤供应商企业名称
            if (matches && org.springframework.util.StringUtils.hasText(request.getSupEntName())) {
                matches = vo.getSupEntName() != null && vo.getSupEntName().toLowerCase().contains(request.getSupEntName().toLowerCase());
            }

            // 过滤采购商企业ID
            if (matches && request.getProEntId() != null) {
                matches = vo.getProEntId() != null && vo.getProEntId().equals(request.getProEntId());
            }
            // 过滤采购商企业名称
            if (matches && org.springframework.util.StringUtils.hasText(request.getProEntName())) {
                matches = vo.getProEntName() != null && vo.getProEntName().toLowerCase().contains(request.getProEntName().toLowerCase());
            }
            return matches;
        }).collect(Collectors.toList());
        return filteredVOs;
    }


    /**
     * 查询企业名称
     */
    private String queryEntById(Long entId) {
        if (entId == null) {
            return "";
        }
        KwsEnterpriseResDto enterpriseResDto = remoteSystemService.queryEnterpriseByEntId(entId);
        if (enterpriseResDto == null) {
            return "";
        }
        return enterpriseResDto.getFirmName();
    }


    /**
     * 新增钱包
     */
    public void addWallet(KwpBizWalletSaveRequest request) {
        log.info("新增钱包，入参：{}", JSONObject.toJSONString(request));
        //校验
        checkAddWallet(request);

        KwpBizWallet kwpBizWallet = new KwpBizWallet();
        kwpBizWallet.setSupEntId(request.getSupEntId());
        kwpBizWallet.setProEntId(request.getProEntId());
        kwpBizWallet.setCreateUser(LoginUserHolder.getUserName());
        kwpBizWallet.setUpdateUser(LoginUserHolder.getUserName());
        //采购商企业名称
        String entName = queryEntById(request.getProEntId());
        kwpBizWallet.setName(entName + StringConstant.HYPHEN + OFFLINE_WALLET);
        kwpBizWalletRepository.save(kwpBizWallet);
        log.info("新增钱包成功！");
    }

    /**
     * 新增钱包校验
     *
     * @param request
     */
    private void checkAddWallet(KwpBizWalletSaveRequest request) {
        int systemType = LoginUserHolder.getSystemType();
        //非管理端，不可新建钱包
        if (systemType != SystemTypeEnum.COMPANY.getCode()) {
            throw new RuntimeException("entId:" + LoginUserHolder.getEntId() + ", 非管理端企业，不可新建钱包！");
        }
        //查询当前登录企业
        EntTypeResDto entTypeResDto = remoteSystemService.queryEntTypeById(LoginUserHolder.getEntId());
        if (entTypeResDto == null) {
            throw new RuntimeException("entId:" + LoginUserHolder.getEntId() + ", 企业信息不存在！");
        }
        //校验创建钱包企业
        if (entTypeResDto.getType() != EntTypeEnum.SUPPLIER.getCode()) {
            throw new RuntimeException("entId:" + LoginUserHolder.getEntId() + ", 非供应商企业不能新建钱包！");
        }
        //校验新增钱包的企业数据库是否存在
        List<KwsEnterpriseResDto> enterpriseResDtoList = remoteSystemService
                .queryEntListByEntIds(Lists.newArrayList(request.getSupEntId(), request.getProEntId()));
        if (enterpriseResDtoList.size() < 2) {
            throw new RuntimeException("所选企业不存在！");
        }
        //幂等校验
        LambdaQueryWrapper<KwpBizWallet> queryWrapper = Wrappers.<KwpBizWallet>lambdaQuery()
                .eq(KwpBizWallet::getSupEntId, request.getSupEntId())
                .eq(KwpBizWallet::getProEntId, request.getProEntId());
        List<KwpBizWallet> bizWalletList = kwpBizWalletRepository.list(queryWrapper);
        if (CollectionUtils.isNotEmpty(bizWalletList)) {
            throw new RuntimeException("entId:" + LoginUserHolder.getEntId() + ", 已存在相同供应商企业和采购企业的钱包，不能重复创建！");
        }
    }

    /**
     * 钱包状态更新
     */
    public void updateWallet(Long id) {
        log.info("更新钱包状态，入参：{}", id);
        if (id == null) {
            throw new RuntimeException("钱包id不能为空！");
        }
        KwpBizWallet wallet = kwpBizWalletRepository.getById(id);
        if (wallet == null) {
            throw new RuntimeException("钱包id:" + id + ", 钱包信息不存在！");
        }
        if (wallet.getState() == 0) {
            wallet.setState(1);
        } else {
            wallet.setState(0);
        }
        kwpBizWalletRepository.updateById(wallet);
        log.info("更新钱包成功!");
    }

    /**
     * 钱包金额更新
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateWalletAmount(KwpBizWalletPrepayRequest request) {
        log.info("人工录入明细，入参：{}", JSONObject.toJSONString(request));
        KwpBizWallet wallet = kwpBizWalletRepository.getById(request.getWalletId());
        if (wallet == null) {
            throw new RuntimeException("钱包id:" + request.getWalletId() + ", 钱包信息不存在！");
        }
        if (request.getType() == 0) {
            //预付
            wallet.setAmount(wallet.getAmount().add(request.getAmount()));
        } else {
            //扣款  扣减金额不能大于可用余额
            if (request.getAmount().compareTo(wallet.getAmount()) > 0) {
                throw new RuntimeException("扣款金额不能大于可用金额！， 扣款金额：" + request.getAmount() + ", 可用金额：" + wallet.getAmount());
            }
            wallet.setAmount(wallet.getAmount().subtract(request.getAmount()));
        }
        //钱包金额更新
        kwpBizWalletRepository.updateById(wallet);

        //创建钱包金额更新日志
        KwpBizWalletPrepay walletOperation = new KwpBizWalletPrepay();
        walletOperation.setWalletId(request.getWalletId());
        //本次变动金额
        walletOperation.setChangeAmount(request.getAmount());
        //可用金额
        walletOperation.setAmount(wallet.getAmount());
        walletOperation.setType(request.getType());
        walletOperation.setVoucherUrl(request.getVoucherUrl());
        walletOperation.setRemark(request.getRemark());
        kwpBizWalletPrepayRepository.save(walletOperation);
        log.info("人工录入明细成功！");
    }


    /**
     * 分页查询钱包冻账明细
     */
    public PageDataResult<KwpBizWalletPrepayPageResponse> walletPrepayDetail(KwpBizWalletPrepayQueryRequest request) {
        log.info("分页查询钱包冻账明细，入参：{}", JSONObject.toJSONString(request));
        Page<KwpBizWalletPrepay> page = new Page<>(request.getPage(), request.getPageSize());
        LambdaQueryWrapper<KwpBizWalletPrepay> queryWrapper = Wrappers.<KwpBizWalletPrepay>lambdaQuery()
                .eq(KwpBizWalletPrepay::getWalletId, request.getWalletId())
                .eq(request.getType() != null, KwpBizWalletPrepay::getType, request.getType())
                .like(StringUtils.isNotBlank(request.getRemark()), KwpBizWalletPrepay::getRemark, request.getRemark())
                .ge(request.getMinAmount() != null, KwpBizWalletPrepay::getChangeAmount, request.getMinAmount())
                .le(request.getMaxAmount() != null, KwpBizWalletPrepay::getChangeAmount, request.getMaxAmount())
                .ge(request.getStartTime() != null, KwpBizWalletPrepay::getCreateTime, request.getStartTime())
                .le(request.getEndTime() != null, KwpBizWalletPrepay::getCreateTime, request.getEndTime())
                .orderByDesc(KwpBizWalletPrepay::getCreateTime)
                .orderByDesc(KwpBizWalletPrepay::getId);
        Page<KwpBizWalletPrepay> walletPrepayPage = kwpBizWalletPrepayRepository.page(page, queryWrapper);
        //若为null,返回空分页结果
        if (walletPrepayPage == null || CollectionUtils.isEmpty(walletPrepayPage.getRecords())) {
            log.info("分页查询钱包冻账明细无数据");
            return PageDataResult.empty(request.getPage(), request.getPageSize());
        }

        List<KwpBizWalletPrepayPageResponse> walletPrepayPageList = walletPrepayPage.getRecords().stream()
                .map(prepay -> {
                    KwpBizWalletPrepayPageResponse pageResp = KwpBizWalletPrepayPageResponse.toPageResp(prepay);
                    KwpBizWallet wallet = kwpBizWalletRepository.getById(prepay.getWalletId());
                    if (wallet == null) {
                        throw new RuntimeException("钱包id:" + request.getWalletId() + ", 钱包信息不存在！");
                    }
                    //钱包信息
                    pageResp.setWalletName(wallet.getName());

                    //企业名称
                    String entName = queryEntById(wallet.getSupEntId());
                    pageResp.setSupEntName(entName);
                    return pageResp;
                }).collect(Collectors.toList());
          PageDataResult<KwpBizWalletPrepayPageResponse> walletPrepayPageResponse = PageDataResult
                .success(request.getPage(), request.getPageSize(), walletPrepayPage.getTotal(), walletPrepayPageList);
        log.info("分页查询钱包冻账明细成功，结果：{}", JSONObject.toJSONString(walletPrepayPageResponse));
        return walletPrepayPageResponse;

    }

    /**
     * 钱包冻账明细导出
     */
    public List<KwpBizWalletPrepayExcelVO> queryExportWalletPrepay(KwpBizWalletPrepayQueryRequest request) {
        log.info("钱包冻账明细导出，入参：{}", JSONObject.toJSONString(request));
        //查询导出数据
        PageDataResult<KwpBizWalletPrepayPageResponse> walletPrepayPageResult = walletPrepayDetail(request);
        List<KwpBizWalletPrepayExcelVO> walletPrepayExcelVO = walletPrepayPageResult.getList().stream().map(vo -> {
            KwpBizWalletPrepayExcelVO excelVO = KwpBizWalletPrepayExcelVO.toPageResp(vo);
            //变动类型
            String descByCode = PrepayTypEnum.getDescByCode(vo.getType());
            excelVO.setType(descByCode);

            return excelVO;
        }).collect(Collectors.toList());
        log.info("钱包冻账明细导出成功，结果：{}", JSONObject.toJSONString(walletPrepayPageResult));
        return walletPrepayExcelVO;
    }
}
