package com.njcn.csharmonic.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.csdevice.api.CsCommTerminalFeignClient;
import com.njcn.csdevice.pojo.dto.DevDetailDTO;
import com.njcn.csharmonic.mapper.PqGovernPlanMapper;
import com.njcn.csharmonic.pojo.param.PqGovernPlanParam;
import com.njcn.csharmonic.pojo.po.PqGovernPlan;
import com.njcn.csharmonic.pojo.vo.PqGovernPlanVo;
import com.njcn.csharmonic.service.IPqGovernPlanService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author xy
 * @since 2026-06-16
 */
@Service
@RequiredArgsConstructor
@DS("sjzx")
public class PqGovernPlanServiceImpl extends ServiceImpl<PqGovernPlanMapper, PqGovernPlan> implements IPqGovernPlanService {

    private final CsCommTerminalFeignClient csCommTerminalFeignClient;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean save(PqGovernPlanParam param) {
        checkGovernPointConflict(param.getGovernBefore(), param.getGovernAfter(), null);
        PqGovernPlan plan = new PqGovernPlan();
        plan.setPid(param.getPid());
        plan.setGovernName(param.getGovernName());
        plan.setGovernType(param.getGovernType());
        plan.setGovernMethod(param.getGovernMethod());
        plan.setGovernBefore(param.getGovernBefore());
        plan.setGovernAfter(param.getGovernAfter());
        plan.setSort(param.getSort());
        return this.save(plan);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean update(PqGovernPlanParam.UpdatePqGovernPlanParam param) {
        PqGovernPlan plan = this.getById(param.getId());
        if (plan == null) {
            throw new RuntimeException("治理方案不存在");
        }
        checkGovernPointConflict(param.getGovernBefore(), param.getGovernAfter(), param.getId());
        plan.setPid(param.getPid());
        plan.setGovernName(param.getGovernName());
        plan.setGovernType(param.getGovernType());
        plan.setGovernMethod(param.getGovernMethod());
        plan.setGovernBefore(param.getGovernBefore());
        plan.setGovernAfter(param.getGovernAfter());
        plan.setSort(param.getSort());
        return this.updateById(plan);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delete(List<String> ids) {
        return this.removeByIds(ids);
    }

    @Override
    public List<PqGovernPlanVo> getListByPid(String pid) {
        List<PqGovernPlanVo> data = new java.util.ArrayList<>();
        LambdaQueryWrapper<PqGovernPlan> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PqGovernPlan::getPid, pid)
                .orderByAsc(PqGovernPlan::getSort);
        List<PqGovernPlan> result = this.list(wrapper);
        if (CollUtil.isNotEmpty(result)) {
            List<String> allLine = result.stream()
                    .flatMap(plan -> Stream.of(plan.getGovernBefore(), plan.getGovernAfter()))
                    .filter(StrUtil::isNotBlank)
                    .collect(Collectors.toList());
            List<DevDetailDTO> ledger = csCommTerminalFeignClient.getLedgerByLineId(allLine).getData();
            if (CollUtil.isNotEmpty(ledger)) {
                Map<String, DevDetailDTO> lineMap = ledger.stream().collect(Collectors.toMap(DevDetailDTO::getLineId, item -> item));
                for (PqGovernPlan item : result) {
                    PqGovernPlanVo vo = new PqGovernPlanVo();
                    BeanUtils.copyProperties(item, vo);
                    DevDetailDTO dto1 = lineMap.get(item.getGovernBefore());
                    DevDetailDTO dto2 = lineMap.get(item.getGovernAfter());
                    vo.setLedgerBefore(dto1.getEngineeringName() + "-" + dto1.getProjectName() + "-" + dto1.getEquipmentName() + "-" + dto1.getLineName());
                    vo.setLedgerAfter(dto2.getEngineeringName() + "-" + dto2.getProjectName() + "-" + dto2.getEquipmentName() + "-" + dto2.getLineName());
                    data.add(vo);
                }
            }
        }
        return data;
    }

    @Override
    public List<PqGovernPlan> getListExcludeNull() {
        LambdaQueryWrapper<PqGovernPlan> wrapper = new LambdaQueryWrapper<>();
        wrapper.isNotNull(PqGovernPlan::getGovernBefore)
                .isNotNull(PqGovernPlan::getGovernAfter);
        return this.list(wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean clearGovernPoints(String id) {
        PqGovernPlan plan = this.getById(id);
        if (plan == null) {
            throw new RuntimeException("治理方案不存在");
        }
        LambdaUpdateWrapper<PqGovernPlan> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(PqGovernPlan::getId, id)
                .set(PqGovernPlan::getGovernBefore, null)
                .set(PqGovernPlan::getGovernAfter, null);
        return this.update(wrapper);
    }

    @Override
    public List<PqGovernPlan> getListByMonitorPoint(List<String> ids, String type) {
        LambdaQueryWrapper<PqGovernPlan> wrapper = new LambdaQueryWrapper<>();
        wrapper.and(w -> w.in(PqGovernPlan::getGovernBefore, ids)
                        .or()
                        .in(PqGovernPlan::getGovernAfter, ids));
        if (!Objects.isNull(type)) {
            wrapper.eq(PqGovernPlan::getGovernType, type);
        }
        return this.list(wrapper);
    }

    /**
     * 校验治理前后监测点的冲突
     * 1. 治理前后监测点不能相同
     * 2. 监测点已被其他方案绑定则不能再次绑定（无论治理前还是治理后）
     *
     * @param governBefore  治理前监测点id
     * @param governAfter   治理后监测点id
     * @param excludeId     排除的方案id（修改时排除自身）
     */
    private void checkGovernPointConflict(String governBefore, String governAfter, String excludeId) {
        if (StrUtil.isNotBlank(governBefore) && StrUtil.isNotBlank(governAfter)
                && governBefore.equals(governAfter)) {
            throw new BusinessException("治理前后监测点不能相同");
        }
        LambdaQueryWrapper<PqGovernPlan> wrapper = new LambdaQueryWrapper<>();
        wrapper.ne(StrUtil.isNotBlank(excludeId), PqGovernPlan::getId, excludeId);
        List<PqGovernPlan> allPlans = this.list(wrapper);
        List<String> boundPoints = allPlans.stream()
                .flatMap(p -> java.util.stream.Stream.of(p.getGovernBefore(), p.getGovernAfter()))
                .filter(StrUtil::isNotBlank)
                .collect(Collectors.toList());
        if (StrUtil.isNotBlank(governBefore) && boundPoints.contains(governBefore)) {
            throw new BusinessException("治理前监测点已被其他方案绑定，不能重复绑定");
        }
        if (StrUtil.isNotBlank(governAfter) && boundPoints.contains(governAfter)) {
            throw new BusinessException("治理后监测点已被其他方案绑定，不能重复绑定");
        }
    }
}
