package com.sckw.fleet.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sckw.contract.api.RemoteContractService;
import com.sckw.contract.api.model.vo.ContractLogisticsScoreVO;
import com.sckw.contract.api.model.vo.KwcContractLogisticsDto;
import com.sckw.core.common.enums.enums.ErrorCodeEnum;
import com.sckw.core.exception.BusinessPlatfromException;
import com.sckw.core.utils.CollectionUtils;
import com.sckw.core.utils.IdWorker;
import com.sckw.core.web.context.LoginUserHolder;
import com.sckw.core.web.response.result.PageDataResult;
import com.sckw.fleet.api.RemoteFleetService;
import com.sckw.fleet.api.model.dto.DriverScoreQuery;
import com.sckw.fleet.api.model.dto.RUpdateDriverScoreDto;
import com.sckw.fleet.api.model.dto.UpdateDriverScoreDto;
import com.sckw.fleet.api.model.vo.RDriverVo;
import com.sckw.fleet.dao.KwfDriverMapper;
import com.sckw.fleet.dao.KwfDriverScoreDetailMapper;
import com.sckw.fleet.dao.KwfDriverScoreMapper;
import com.sckw.fleet.model.KwfDriver;
import com.sckw.fleet.model.KwfDriverScore;
import com.sckw.fleet.model.KwfDriverScoreDetail;
import com.sckw.fleet.model.request.DriverScorerDetailRequest;
import com.sckw.fleet.model.vo.DriverScorerDetailVO;
import com.sckw.fleet.repository.KwfDriverScoreDetailRepository;
import com.sckw.fleet.repository.KwfDriverScoreRepository;
import com.sckw.system.api.RemoteSystemService;
import com.sckw.system.api.model.dto.res.KwsEnterpriseResDto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * @Author: tangyishan
 * @CreateTime: 2025-12-11  15:05
 * @Description: 司机评分服务
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class KwfDriverScoreService {

    @Autowired
    private KwfDriverMapper kwfDriverMapper;
    @Autowired
    private KwfDriverScoreMapper kwfDriverScoreMapper;
    @Autowired
    private KwfDriverScoreDetailMapper kwfDriverScoreDetailMapper;
    private final KwfDriverScoreRepository driverScoreRepository;
    private final KwfDriverScoreDetailRepository driverScoreDetailRepository;

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

    /**
     * 更新司机评分
     */
    @Transactional(rollbackFor = Exception.class)
    public void update(UpdateDriverScoreDto updateDriverScoreDto) {
        log.info("进入KwfDriverScoreService.updateScore()方法，修改司机评分参数为：{}", JSON.toJSONString(updateDriverScoreDto));
        //查询出当前物流企业的所有司机
        List<KwfDriver> drivers= kwfDriverMapper.findListByEntId(updateDriverScoreDto.getLogisticsEntId());
        if(CollectionUtils.isEmpty(drivers)){
            //无司机，直接返回
            return;
        }
        Map<Long, KwfDriver> driversMap = drivers.stream().collect(Collectors.toMap(KwfDriver::getId, v -> v));
        //查询指定供应商，指定物流的下的所有司机的评分
        KwfDriverScore driverScoreDto = new KwfDriverScore();
        driverScoreDto.setProviderEntId(updateDriverScoreDto.getProviderEntId());
        driverScoreDto.setLogisticsEntId(updateDriverScoreDto.getLogisticsEntId());
        List<KwfDriverScore> kwfDriverScores = new ArrayList<>(kwfDriverScoreMapper.selectKwfDriverScoreList(driverScoreDto).stream().filter(v -> driversMap.containsKey(v.getDriverId())).toList());
        //对未进行评分初始化的司机进行初始化
        initDriverScore(updateDriverScoreDto, driversMap, kwfDriverScores);
        if(CollectionUtils.isEmpty(kwfDriverScores)){
            //无已存在的司机评分，直接返回
            return;
        }
        //
        //根据不同的操作类型调用不同的更新方法
        if(Objects.equals(updateDriverScoreDto.getOperatorType(), 1)){
//            initDriverScore(updateDriverScoreDto, driversMap,driverScoreMap);
        }else if(Objects.equals(updateDriverScoreDto.getOperatorType(), 2)){
            //修改司机评分
            updateDriverScore(updateDriverScoreDto, driversMap,kwfDriverScores);
        }else {
            //重置司机评分
            resetDriverScore(updateDriverScoreDto, driversMap,kwfDriverScores);
        }
    }


    /**
     * 初始化司机评分
     */
    private KwfDriverScoreAndDetail initDriverScore(UpdateDriverScoreDto updateDriverScoreDto, Map<Long, KwfDriver> driversMap,List<KwfDriverScore> kwfDriverScores){
        List<Long> driverIds = kwfDriverScores.stream().map(KwfDriverScore::getDriverId).toList();
        //找出没有评分记录的司机
        List<KwfDriver> noScoreDrivers = driversMap.values().stream().filter(driver -> !driverIds.contains(driver.getId())).toList();
        //所有司机均有评分，继承之前的评分，无需进行初始化
        if(noScoreDrivers.isEmpty()){
            return null;
        }
        //构建司机评分记录和评分明细集合
        KwfDriverScoreAndDetail kwfDriverScoreAndDetail = buildDriverScoreInitRecord(updateDriverScoreDto, noScoreDrivers);
        //批量插入评分记录
        kwfDriverScoreMapper.insertBatch(kwfDriverScoreAndDetail.getDriverScores());
        //批量插入评分明细
        kwfDriverScoreDetailMapper.insertBatch(kwfDriverScoreAndDetail.getDriverScoreDetails());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException ignored) {
        }
        return kwfDriverScoreAndDetail;
    }

    /**
     * 修改司机评分
     */
    private void updateDriverScore(UpdateDriverScoreDto updateDriverScoreDto, Map<Long, KwfDriver> driversMap,List<KwfDriverScore> kwfDriverScores){
        //driversMap-物流企业下所有司机，kwfDriverScores-指定供应商，指定物流的所有司机的评分
        //深拷贝出新的司机评分集合
        List<KwfDriverScore> kwfDriverScoresNew = JSON.parseObject(JSON.toJSONString(kwfDriverScores), new TypeReference<>() {});
        //给所有司机进行改分，收集超额的分
        BigDecimal min = new BigDecimal("0.00");
        BigDecimal max = new BigDecimal("100.00");
        BigDecimal exceedScore = new BigDecimal("0.00");
        for (KwfDriverScore driverScore : kwfDriverScoresNew) {
            BigDecimal score = driverScore.getScore();
            BigDecimal resultScore = score.add(updateDriverScoreDto.getScoreChange());
            if(resultScore.compareTo(min) < 0){
                exceedScore = exceedScore.add(resultScore);
                driverScore.setScore(new BigDecimal("0.00"));
            }else if(resultScore.compareTo(max)>0){
                exceedScore = exceedScore.add(resultScore.subtract(max));
                driverScore.setScore(new BigDecimal("100.00"));
            }else {
                driverScore.setScore(resultScore);
            }
        }
        //有超额的分，依次分配或扣减分数最低或做高的司机评分到平均分
        if(exceedScore.compareTo(BigDecimal.ZERO) != 0){
            //默认按照评分升序排序，如果是减分操作，则按照降序排序
            Comparator<KwfDriverScore> comparator = Comparator.comparing(KwfDriverScore::getScore);
            if(updateDriverScoreDto.getScoreChange().compareTo(BigDecimal.ZERO) < 0){
                comparator = comparator.reversed();
            }
            kwfDriverScoresNew = kwfDriverScoresNew.stream().sorted(comparator).toList();
            //分配超额的分，加分操作依次给最低的司机加到分均分，减分操作依次给最高分的司机减到分均分
            for (KwfDriverScore kwfDriverScore : kwfDriverScoresNew) {
                //超额的分已经分配完，退出循环
                if(exceedScore.compareTo(BigDecimal.ZERO) == 0){
                    break;
                }
                //计算当前司机最大可改的分
                BigDecimal changeMaxScore = updateDriverScoreDto.getAfterUpdateLogisticsEntScore().subtract(kwfDriverScore.getScore());
                //计算司机实际可改的分
                BigDecimal changeScore = exceedScore.abs().compareTo(changeMaxScore.abs()) < 0 ? exceedScore : changeMaxScore;
                kwfDriverScore.setScore(kwfDriverScore.getScore().add(changeScore));
                //计算剩余可分配的分
                exceedScore = exceedScore.subtract(changeScore);
            }
        }
        //构建司机评分记录和评分明细集合
        KwfDriverScoreAndDetail kwfDriverScoreAndDetail = buildDriverScoreUpdateRecord(updateDriverScoreDto, driversMap, kwfDriverScores, kwfDriverScoresNew);
        //批量更新评分记录
        kwfDriverScoreMapper.updateScoreBatch(kwfDriverScoreAndDetail.getDriverScores());
        //批量插入评分明细
        kwfDriverScoreDetailMapper.insertBatch(kwfDriverScoreAndDetail.getDriverScoreDetails());
    }

    /**
     * 重置司机评分
     */
    private void resetDriverScore(UpdateDriverScoreDto updateDriverScoreDto, Map<Long, KwfDriver> driversMap,List<KwfDriverScore> kwfDriverScores){
        //driversMap-物流企业下所有司机，kwfDriverScores-指定供应商，指定物流的所有司机的评分
        //构建司机评分记录和评分明细集合
        KwfDriverScoreAndDetail kwfDriverScoreAndDetail = buildDriverScoreResetRecord(updateDriverScoreDto, driversMap, kwfDriverScores);
        //批量更新评分记录
        kwfDriverScoreMapper.updateScoreBatch(kwfDriverScoreAndDetail.getDriverScores());
        //批量插入评分明细
        kwfDriverScoreDetailMapper.insertBatch(kwfDriverScoreAndDetail.getDriverScoreDetails());
    }

    private KwfDriverScoreAndDetail buildDriverScoreInitRecord(UpdateDriverScoreDto updateDriverScoreDto,List<KwfDriver> drivers){
        Date now = new Date();
        //构建司机评分记录集合
        List<KwfDriverScore> driverScores = new ArrayList<>();
        List<KwfDriverScoreDetail> driverScoreDetails = new ArrayList<>();
        BigDecimal initScore = new BigDecimal("0.00");
        IdWorker idWorker = new IdWorker(1L);
        for (KwfDriver driver : drivers) {
            long scoreId = idWorker.nextId();
            //构建司机评分记录
            KwfDriverScore driverScore = new KwfDriverScore();
            driverScore.setId(scoreId);
            driverScore.setProviderEntId(updateDriverScoreDto.getProviderEntId());
            driverScore.setLogisticsEntId(updateDriverScoreDto.getLogisticsEntId());
            driverScore.setDriverId(driver.getId());
            driverScore.setScore(updateDriverScoreDto.getAfterUpdateLogisticsEntScore());
            driverScore.setCreateBy(LoginUserHolder.getUserId());
            driverScore.setCreateTime(now);
            driverScore.setUpdateBy(LoginUserHolder.getUserId());
            driverScore.setUpdateTime(now);
            driverScores.add(driverScore);
            //构建司机评分明细
            KwfDriverScoreDetail scoreDetail = buildDriverScoreDetail("司机评分初始化", driverScore, driver, initScore);
            driverScoreDetails.add(scoreDetail);
        }

        return new KwfDriverScoreAndDetail(driverScores, driverScoreDetails);
    }

    private KwfDriverScoreAndDetail buildDriverScoreUpdateRecord(UpdateDriverScoreDto updateDriverScoreDto,Map<Long, KwfDriver> driversMap,List<KwfDriverScore> kwfDriverScores,List<KwfDriverScore> kwfDriverScoresNew){
        //原评分记录集合
        Map<Long, KwfDriverScore> originDriverScoreMap = kwfDriverScores.stream().collect(Collectors.toMap(KwfDriverScore::getDriverId, v -> v));
        //构建司机评分记录集合
        List<KwfDriverScoreDetail> driverScoreDetails = new ArrayList<>();
        Date now = new Date();
        for (KwfDriverScore driverScore : kwfDriverScoresNew) {
            //更新评分记录更新信息
            driverScore.setUpdateBy(LoginUserHolder.getUserId());
            driverScore.setUpdateTime(now);
            //构建司机评分明细信息
            KwfDriverScore originDriverScore = originDriverScoreMap.get(driverScore.getDriverId());
            KwfDriverScoreDetail scoreDetail = buildDriverScoreDetail(updateDriverScoreDto.getAction(), driverScore, driversMap.get(driverScore.getDriverId()), originDriverScore.getScore());
            driverScoreDetails.add(scoreDetail);
        }

        return new KwfDriverScoreAndDetail(kwfDriverScoresNew, driverScoreDetails);
    }

    private KwfDriverScoreAndDetail buildDriverScoreResetRecord(UpdateDriverScoreDto updateDriverScoreDto,Map<Long, KwfDriver> driversMap,List<KwfDriverScore> kwfDriverScores){
        //构建司机评分记录集合
        List<KwfDriverScoreDetail> driverScoreDetails = new ArrayList<>();
        for (KwfDriverScore driverScore : kwfDriverScores) {
            BigDecimal originDriverScore = driverScore.getScore();
            //更新评分记录更新信息
            driverScore.setScore(updateDriverScoreDto.getAfterUpdateLogisticsEntScore());
            driverScore.setUpdateBy(LoginUserHolder.getUserId());
            driverScore.setUpdateTime(new Date());
            //构建司机评分明细信息
            KwfDriverScoreDetail scoreDetail = buildDriverScoreDetail(updateDriverScoreDto.getAction(), driverScore, driversMap.get(driverScore.getDriverId()), originDriverScore);
            driverScoreDetails.add(scoreDetail);
        }

        return new KwfDriverScoreAndDetail(kwfDriverScores, driverScoreDetails);
    }


    private KwfDriverScoreDetail buildDriverScoreDetail(String action,KwfDriverScore driverScore,KwfDriver driver,BigDecimal originDriverScore){
        IdWorker idWorker = new IdWorker(1L);
        Date now = new Date();
        //构建司机评分明细信息
        KwfDriverScoreDetail scoreDetail = new KwfDriverScoreDetail();
        scoreDetail.setId(idWorker.nextId());
        scoreDetail.setScoreId(driverScore.getId());
        if(driver != null){
            scoreDetail.setDriverId(driver.getId());
        }
        scoreDetail.setAction(action);
        BigDecimal scoreChange = driverScore.getScore().subtract(originDriverScore);
        scoreDetail.setScoreChange(scoreChange);
        scoreDetail.setScore(driverScore.getScore());
        scoreDetail.setCreateBy(LoginUserHolder.getUserId());
        scoreDetail.setCreateTime(now);
        scoreDetail.setUpdateBy(LoginUserHolder.getUserId());
        scoreDetail.setUpdateTime(now);
        return scoreDetail;
    }

    public BigDecimal countDriverScore(DriverScoreQuery query) {
        return kwfDriverScoreMapper.selectKwfDriverScoreCount(query);
    }


    @Data
    @AllArgsConstructor
    public static class KwfDriverScoreAndDetail{
        List<KwfDriverScore> driverScores;
        List<KwfDriverScoreDetail> driverScoreDetails;
    }

    /**
     * 分页查询司机评分明细
     * @param request
     * @return
     */
    public PageDataResult<DriverScorerDetailVO> queryScoreDetailPage(DriverScorerDetailRequest request) {
        log.info("分页查询司机评分明细：{}", JSON.toJSONString(request));
        if (request.getScoreId() == null) {
            log.info("司机评分id不能为空，司机id:{}", request.getDriverId());
            return PageDataResult.empty(request.getPageNum(), request.getPageSize());
        }
        LambdaQueryWrapper<KwfDriverScoreDetail> queryWrapper = Wrappers.<KwfDriverScoreDetail>lambdaQuery()
                .eq(KwfDriverScoreDetail::getDriverId, request.getDriverId())
                .eq(KwfDriverScoreDetail::getScoreId, request.getScoreId())
                .like(StringUtils.isNotBlank(request.getAction()), KwfDriverScoreDetail::getAction, request.getAction())
                .eq(KwfDriverScoreDetail::getDelFlag, 0)
                .orderByDesc(KwfDriverScoreDetail::getId);
        Page<KwfDriverScoreDetail> scoreDetailPageList = driverScoreDetailRepository.page(new Page<>(request.getPageNum(), request.getPageSize()), queryWrapper);
        List<KwfDriverScoreDetail> records = scoreDetailPageList.getRecords();
        if (CollectionUtils.isEmpty(records)) {
            log.info("当前司机的无司机评分记录，司机id:{}", request.getDriverId());
            return PageDataResult.empty(request.getPageNum(), request.getPageSize());
        }

        List<DriverScorerDetailVO> scorerDetailVOList = new ArrayList<>();
        for (KwfDriverScoreDetail detail : records) {
            DriverScorerDetailVO detailVO = new DriverScorerDetailVO();
            detailVO.setScoreId(detail.getScoreId());
            detailVO.setDriverId(detail.getDriverId());
            detailVO.setAction(detail.getAction());
            detailVO.setScoreChange(detail.getScoreChange());
            detailVO.setScore(detail.getScore());
            detailVO.setCreateTime(detail.getCreateTime());
            scorerDetailVOList.add(detailVO);

            //查询当前物流企业自动派单且生效的物流合同
            KwcContractLogisticsDto logContractByEntId = remoteContractService.findLogContractByEntId(request.getEntId());
            if (logContractByEntId != null) {
                KwsEnterpriseResDto entDto = remoteSystemService.queryEnterpriseByEntId(logContractByEntId.getEntId());
                detailVO.setSupEntId(logContractByEntId.getEntId());
                detailVO.setSupEntName(entDto == null ? null : entDto.getFirmName());
            }
            RDriverVo driver = remoteFleetService.findDriver(request.getDriverId());
            if (driver != null) {
                detailVO.setDriverName(driver.getName());
            }
        }
        log.info("分页查询司机评分明细成功！");
        return PageDataResult.success(request.getPageNum(), request.getPageSize(), (long) scorerDetailVOList.size(), scorerDetailVOList);
    }


    /**
     * 修改司机评分
     * @param dto
     */
    public void updateDriverScore(RUpdateDriverScoreDto dto) {
        if (dto.getScore() == null) {
            throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR, "分数不能为空!");
        }
        //1. 查询司机的评分
        KwfDriverScore driverScore = driverScoreRepository.findDriverScoreByEntIds(dto.getSupEntId(), dto.getLogEntId(), dto.getDriverId());
        //2.司机没评分，初始化时间分数（企业分数）
        if (driverScore == null) {
            log.info("司机无评分, 需初始化司机分数，司机id：{}", dto.getDriverId());
            ContractLogisticsScoreVO logisticsScore = remoteContractService.findLogisticsScoreByEntId(dto.getSupEntId(), dto.getLogEntId());
            if (logisticsScore.getScore() == null || logisticsScore.getScore().compareTo(BigDecimal.ZERO) < 0) {
                throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR, "修改司机分数，企业无评分!");
            }
            //初始化司机分数
            driverScore = initDriverScore(dto, logisticsScore.getScore());
        }
        //司机当前分数
        BigDecimal currentScore = driverScore.getScore() == null || driverScore.getScore().compareTo(BigDecimal.ZERO) < 0
                ? BigDecimal.ZERO : driverScore.getScore();
        //司机加减分数
        BigDecimal scoreChange = dto.getScore();

        //3. 修改司机评分
        BigDecimal newScore = currentScore.add(scoreChange);
        driverScore.setScore(newScore.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : newScore);
        driverScoreRepository.updateById(driverScore);

        //4.新增司机评分明细
        addDriverScoreDetail(driverScore, scoreChange, dto.getAction());
    }


    /**
     * 初始化司机分数
     * @param dto
     * @param entScore
     */
    private KwfDriverScore initDriverScore(RUpdateDriverScoreDto dto, BigDecimal entScore) {
        KwfDriverScore driverScore = new KwfDriverScore();
        driverScore.setProviderEntId(dto.getSupEntId());
        driverScore.setLogisticsEntId(dto.getLogEntId());
        driverScore.setDriverId(dto.getDriverId());
        driverScore.setScore(entScore);
        driverScore.setCreateBy(LoginUserHolder.getUserId() == null ? -1 : LoginUserHolder.getUserId());
        driverScore.setUpdateBy(LoginUserHolder.getUserId() == null ? -1 : LoginUserHolder.getUserId());
        boolean saveResult = driverScoreRepository.save(driverScore);
        if (!saveResult) {
            throw new BusinessPlatfromException(ErrorCodeEnum.PARAM_ERROR, "初始化司机评分失败!");
        }
        return driverScore;
    }

    /**
     * 新增司机评分明细
     * @param action
     * @param driverScore
     * @param scoreChange
     * @param scoreChange
     */
    private void addDriverScoreDetail(KwfDriverScore driverScore, BigDecimal scoreChange, String action) {
        KwfDriverScoreDetail scoreDetail = new KwfDriverScoreDetail();
        scoreDetail.setScoreId(driverScore.getId());
        scoreDetail.setDriverId(driverScore.getDriverId());
        scoreDetail.setAction(action);
        scoreDetail.setScoreChange(scoreChange);
        scoreDetail.setScore(driverScore.getScore());
        scoreDetail.setCreateBy(LoginUserHolder.getUserId() == null ? -1 : LoginUserHolder.getUserId());
        scoreDetail.setUpdateBy(LoginUserHolder.getUserId() == null ? -1 : LoginUserHolder.getUserId());
        driverScoreDetailRepository.save(scoreDetail);
    }


}
