package com.sckw.transport.service;


import com.alibaba.fastjson.JSON;
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.core.common.enums.enums.ErrorCodeEnum;
import com.sckw.core.exception.BusinessPlatfromException;
import com.sckw.core.model.constant.Global;
import com.sckw.core.model.enums.ParkingChangeStrategyEnum;
import com.sckw.core.utils.CollectionUtils;
import com.sckw.core.utils.StringUtils;
import com.sckw.core.web.response.result.PageDataResult;
import com.sckw.system.api.RemoteSystemService;
import com.sckw.system.api.model.dto.res.EntCacheResDto;
import com.sckw.transport.model.KwtParkingChargeStrategy;
import com.sckw.transport.model.KwtParkingChargeStrategyUnit;
import com.sckw.transport.model.KwtParkingStrategySwitch;
import com.sckw.transport.model.ParkingChangeStrategySaveParam;
import com.sckw.transport.model.param.*;
import com.sckw.transport.repository.KwtParkingChangeStrategyRepository;
import com.sckw.transport.repository.KwtParkingChangeStrategyUnitRepository;
import com.sckw.transport.repository.KwtParkingStrategySwitchRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
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: 2026-01-05
 * Des: 收费策略 Service
 * Version: 1.0
 */

@Slf4j
@Service
@RequiredArgsConstructor
public class ParkingChangeStrategyService {

    private static final BigDecimal ZERO_AMOUNT = BigDecimal.ZERO;

    private final KwtParkingChangeStrategyRepository parkingChangeStrategyRepository;
    private final KwtParkingChangeStrategyUnitRepository parkingChangeStrategyUnitRepository;
    private final KwtParkingStrategySwitchRepository parkingStrategySwitchRepository;


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

    /**
     * 分页查询收费策略
     * @param param
     */
    public PageDataResult<ParkingChangeStrategyResp> pageQueryChangeStrategy(ParkingChangeStrategyQueryParam param) {
        log.info("分页查询收费策略：{}", JSON.toJSONString(param));

        //构建查询条件
        LambdaQueryWrapper<KwtParkingChargeStrategy> wrapper = buildAndExecuteQuery(param);

        Page<KwtParkingChargeStrategy> pageByStatus = parkingChangeStrategyRepository.page(new Page<>(param.getPageNum(), param.getPageSize()), wrapper);
        List<KwtParkingChargeStrategy> records = pageByStatus.getRecords();
        if (CollectionUtils.isEmpty(records)) {
            log.info("收费策略信息空");
            return PageDataResult.empty(param.getPageNum(), param.getPageSize());
        }
        List<ParkingChangeStrategyResp> changeStrategyRespList = getChangeStrategyPageResult(records);
        return PageDataResult.success(param.getPageNum(), param.getPageSize(), pageByStatus.getTotal(), changeStrategyRespList);
    }


    /**
     * 构建查询条件并执行分页查询
     */
    private LambdaQueryWrapper<KwtParkingChargeStrategy> buildAndExecuteQuery(ParkingChangeStrategyQueryParam param) {
        LambdaQueryWrapper<KwtParkingChargeStrategy> wrapper = Wrappers.<KwtParkingChargeStrategy>lambdaQuery()
                .eq(param.getType() != null, KwtParkingChargeStrategy::getType, param.getType())
                .like(StringUtils.isNotBlank(param.getStrategyName()), KwtParkingChargeStrategy::getStrategyName, param.getStrategyName())
                .eq(KwtParkingChargeStrategy::getDelFlag, 0)
                .orderByDesc(KwtParkingChargeStrategy::getCreateTime);

        handleSearchKeyword(param, wrapper);

        return wrapper;
    }

    /**
     * 关键词模糊查询
     */
    private void handleSearchKeyword(ParkingChangeStrategyQueryParam param, LambdaQueryWrapper<KwtParkingChargeStrategy> wrapper) {
        if (StringUtils.isBlank(param.getEntName())) {
            return;
        }
        Set<Long> strategyIds = addMatchedIds(param.getEntName());
        if (CollectionUtils.isEmpty(strategyIds)) {
            wrapper.eq(KwtParkingChargeStrategy::getId, -1);
        } else {
            wrapper.in(KwtParkingChargeStrategy::getId, strategyIds);
        }
    }


    /**
     * 从企业名称模糊查询收费策略
     * @param entName
     */
    private Set<Long> addMatchedIds(String entName) {
        List<EntCacheResDto> entCacheResDtoList = remoteSystemService.queryEntCacheByName(entName);
        if (CollectionUtils.isEmpty(entCacheResDtoList)) {
            return new HashSet<>();
        }
        Set<Long> entIds = entCacheResDtoList.stream().map(EntCacheResDto::getId).collect(Collectors.toSet());
        List<KwtParkingChargeStrategyUnit> strategyUnits = parkingChangeStrategyUnitRepository.queryByEntIds(entIds);
        return strategyUnits.stream().map(KwtParkingChargeStrategyUnit::getStrategyId).collect(Collectors.toSet());
    }

    /**
     * 获取收费策略
     * @param records
     */
    private List<ParkingChangeStrategyResp> getChangeStrategyPageResult(List<KwtParkingChargeStrategy> records) {
        log.info("开始查询收费策略，param:{}", JSON.toJSONString(records));
        if (CollectionUtils.isEmpty(records)) {
            return Collections.emptyList();
        }
        List<ParkingChangeStrategyResp> changeStrategyList = records.stream()
                .map(change -> {
                    ParkingChangeStrategyResp resp = new ParkingChangeStrategyResp();
                    resp.setId(change.getId());
                    resp.setStrategyName(change.getStrategyName());
                    resp.setType(change.getType());
                    resp.setTypeDesc(ParkingChangeStrategyEnum.geDesc(change.getType()));
                    BigDecimal displayMethod = change.getMethod();
                    resp.setMethod(displayMethod);

                    if (Objects.equals(ParkingChangeStrategyEnum.BY_TON.getCode(), change.getType())) {
                        resp.setMethodDesc(displayMethod + "元/吨");
                    } else if (Objects.equals(ParkingChangeStrategyEnum.BY_TIME.getCode(), change.getType())) {
                        resp.setMethodDesc(displayMethod + "元/次");
                    } else {
                        resp.setMethodDesc(displayMethod + "元/月");
                    }
                    // 查询分配单位数量
                    List<KwtParkingChargeStrategyUnit> strategyUnitList = parkingChangeStrategyUnitRepository.queryByStrategyId(change.getId());
                    if (CollectionUtils.isEmpty(strategyUnitList)) {
                        resp.setEntNumber(0);
                    } else {
                        resp.setEntNumber(strategyUnitList.size());
                    }
                    resp.setStatus(change.getStatus());
                    resp.setRemark(change.getRemark());
                    resp.setCreateTime(change.getCreateTime());
                    return resp;
                }).collect(Collectors.toList());

        log.info("收费策略查询结束，size:{}", JSON.toJSONString(changeStrategyList.size()));
        return changeStrategyList;

    }


    /**
     * 保存收费策略
     * @param param
     */
    public void saveChangeStrategy(ParkingChangeStrategySaveParam param) {
        log.info("保存收费策略，param：{}", JSON.toJSONString(param));
        // 新增
        if (param.getId() == null) {
            KwtParkingChargeStrategy changeStrategy = new KwtParkingChargeStrategy();
            changeStrategy.setStrategyName(param.getStrategyName());
            changeStrategy.setType(param.getType());
            changeStrategy.setMethod(param.getMethod());
            changeStrategy.setStatus(1);
            changeStrategy.setRemark(param.getRemark());
            parkingChangeStrategyRepository.save(changeStrategy);
        } else {
            // 更新
            KwtParkingChargeStrategy changeStrategy = parkingChangeStrategyRepository.getById(param.getId());
            if (changeStrategy == null) {
                throw new BusinessPlatfromException(ErrorCodeEnum.DRIVER_NOT_FOUND, "收费策略不存在");
            }
            changeStrategy.setStrategyName(param.getStrategyName());
            changeStrategy.setType(param.getType());
            changeStrategy.setMethod(param.getMethod());
            changeStrategy.setStatus(param.getStatus());
            changeStrategy.setRemark(param.getRemark());
            parkingChangeStrategyRepository.updateById(changeStrategy);
        }
    }

    /**
     * 删除收费策略
     * @param id
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteChangeStrategy(Long id) {
        log.info("删除收费策略，id：{}", id);
        // 1.s删除
        if (id == null) {
            throw new BusinessPlatfromException(ErrorCodeEnum.DRIVER_NOT_FOUND, "id不能为空");
        }
        KwtParkingChargeStrategy changeStrategy = parkingChangeStrategyRepository.getById(id);
        if (changeStrategy == null) {
            throw new BusinessPlatfromException(ErrorCodeEnum.DRIVER_NOT_FOUND, "收费策略不存在");
        }
        parkingChangeStrategyRepository.removeById(changeStrategy);

        // 2.删除分配公司
        List<KwtParkingChargeStrategyUnit> strategyUnitList = parkingChangeStrategyUnitRepository.queryByStrategyId(id);
        if (CollectionUtils.isNotEmpty(strategyUnitList)) {
            Set<Long> ids = strategyUnitList.stream().map(KwtParkingChargeStrategyUnit::getId).collect(Collectors.toSet());
            parkingChangeStrategyUnitRepository.removeBatchByIds(ids);
        }
    }

    /**
     * 查询收费策略已分配单位
     * @param id
     * @return List<ParkingChangeStrategyUnitResp>
     */
    public List<ParkingChangeStrategyUnitResp> queryChangeStrategyEnt(Long id) {
        log.info("查询收费策略已分配单位，id：{}", id);
        List<KwtParkingChargeStrategyUnit> strategyUnitList = parkingChangeStrategyUnitRepository.queryByStrategyId(id);
        if (CollectionUtils.isEmpty(strategyUnitList)) {
            return Collections.emptyList();
        }
        return strategyUnitList.stream()
                .map(unit -> {
                    ParkingChangeStrategyUnitResp resp = new ParkingChangeStrategyUnitResp();
                    resp.setId(unit.getId());
                    resp.setStrategyId(id);
                    resp.setEntId(unit.getEntId());

                    // 查询企业名称
                    resp.setEntName(getEntName(unit.getEntId()));
                    return resp;
                }).collect(Collectors.toList());
    }

    /**
     * 保存单位分配
     * @param param
     */
    public ParkingChangeStrategyUnitSaveResp saveChangeStrategyEnt(ParkingChangeStrategyUnitSaveParam param) {
        log.info("保存单位分配，param：{}", JSON.toJSONString(param));
        ParkingChangeStrategyUnitSaveResp resp = new ParkingChangeStrategyUnitSaveResp();
        // 清空逻辑
        if (CollectionUtils.isEmpty(param.getEntIds())) {
            parkingChangeStrategyUnitRepository.deleteByStrategyId(param.getStrategyId());
            return resp;
        }

        // 校验冲突
        List<KwtParkingChargeStrategyUnit> existingRelations = parkingChangeStrategyUnitRepository.queryByStrategyIdAndEnt(param.getStrategyId(), param.getEntIds());
        if (CollectionUtils.isNotEmpty(existingRelations) && !param.getForceReplace()) {
            Set<Long> conflictIds = existingRelations.stream()
                    .map(KwtParkingChargeStrategyUnit::getEntId)
                    .collect(Collectors.toSet());
            String conflictNames = conflictIds.stream().map(this::getEntName).collect(Collectors.joining(","));
            resp.setEntNames(conflictNames);
            resp.setErrorCode(ErrorCodeEnum.DATA_SAVE_FAIL.getCode());
            resp.setErrorMsg(conflictNames + "已存在策略, 是否确认替换？");
            return resp;
        }

        // 如果是强制模式，先清理掉旧的关联关系（替换）
        if (CollectionUtils.isNotEmpty(existingRelations) && param.getForceReplace()) {
            Set<Long> conflictIds = existingRelations.stream()
                    .map(KwtParkingChargeStrategyUnit::getEntId)
                    .collect(Collectors.toSet());
            // 删除这些单位原本关联的旧策略记录
            parkingChangeStrategyUnitRepository.deleteByEntId(conflictIds);
        }

        // 正常流程
        parkingChangeStrategyUnitRepository.deleteByStrategyId(param.getStrategyId());
        List<KwtParkingChargeStrategyUnit> insertList = param.getEntIds().stream()
                .map(entId -> {
                    KwtParkingChargeStrategyUnit unit = new KwtParkingChargeStrategyUnit();
                    unit.setStrategyId(param.getStrategyId());
                    unit.setEntId(entId);
                    return unit;
                })
                .collect(Collectors.toList());

        // 批量插入
        parkingChangeStrategyUnitRepository.saveBatch(insertList);
        return resp;
    }

    /**
     * 通过企业id查询企业名称
     * @param entId
     */
    private String getEntName(Long entId) {
        // 查询企业名称
        EntCacheResDto entCacheResDto = remoteSystemService.queryEntDetails(entId);
        if (entCacheResDto == null) {
            return null;
        }
        return entCacheResDto.getFirmName();
    }


    /**
     * 查询收费策略开关
     */
    public ParkingStrategySwitchResp querySwitch() {
        log.info("查询收费策略开关");

        ParkingStrategySwitchResp resp = new ParkingStrategySwitchResp();
        resp.setStatus(Global.NO);
        KwtParkingStrategySwitch strategySwitch = parkingStrategySwitchRepository.queryParkingStrategySwitch();
        if (strategySwitch == null) {
           return resp;
        }

        resp.setId(strategySwitch.getId());
        resp.setStatus(strategySwitch.getStatus());
        resp.setDefaultFee(strategySwitch.getDefaultFee());
        log.info("收费策略开关查询结束，开关状态:{}", Objects.equals(strategySwitch.getStatus(), Global.YES) ? "开启" : "关闭");
        return resp;
    }

    /**
     * 修改收费策略开关
     */
    public void updateSwitch(ParkingStrategySwitchSaveParam param) {
        log.info("修改收费策略开关");

        KwtParkingStrategySwitch strategySwitch = parkingStrategySwitchRepository.getById(param.getId());
        if (strategySwitch == null) {
            throw new BusinessPlatfromException(ErrorCodeEnum.DRIVER_NOT_FOUND, "收费策略开关不存在");
        }

        if (Objects.equals(param.getStatus(), Global.YES)  && param.getDefaultFee() == null) {
            throw new BusinessPlatfromException(ErrorCodeEnum.DRIVER_NOT_FOUND, "开关打开后，默认费用不能为空");
        }
        strategySwitch.setStatus(param.getStatus());
        strategySwitch.setDefaultFee(param.getDefaultFee());
        parkingStrategySwitchRepository.updateById(strategySwitch);
    }

    /**
     * 策略 method 为 0.00 时，展示开关表配置的默认服务费
     */
    private BigDecimal resolveStrategyDisplayMethod(BigDecimal method) {
        BigDecimal actualMethod = method == null ? ZERO_AMOUNT : method;
        if (actualMethod.compareTo(ZERO_AMOUNT) != 0) {
            log.info("收费策略配置的计费：{}", actualMethod);
            return actualMethod;
        }
        KwtParkingStrategySwitch strategySwitch = parkingStrategySwitchRepository.queryParkingStrategySwitch();
        if (strategySwitch == null || strategySwitch.getDefaultFee() == null) {
            log.info("收费策略未配置计费，使用默认计费：{}", ZERO_AMOUNT);
            return ZERO_AMOUNT;
        }
        return strategySwitch.getDefaultFee();
    }

}
