package com.bonus.material.equipment.service.impl;


import cn.hutool.core.collection.CollectionUtil;
import com.bonus.common.core.utils.SpringUtils;
import com.bonus.common.core.utils.StringUtils;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.core.web.domain.BaseEntity;
import com.bonus.common.datascope.annotation.DataScope;
import com.bonus.common.datascope.utils.CommonDataPermissionInfo;
import com.bonus.common.security.utils.SecurityUtils;
import com.bonus.material.basic.domain.SysDeptVO;
import com.bonus.material.equipment.domain.*;
import com.bonus.material.equipment.mapper.SysDeptMapper;
import com.bonus.material.equipment.service.ISysDeptService;
import com.bonus.material.owner.domain.Ownerdomin;
import com.bonus.material.owner.mapper.OwnerMapper;
import com.bonus.system.api.domain.SysDept;
import com.bonus.system.api.domain.SysUser;
import org.apache.commons.lang3.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Function;
import javax.annotation.Resource;
import java.util.stream.Collectors;

@Service
public class SysDeptServiceImpl implements ISysDeptService {

    private static final Logger log = LoggerFactory.getLogger(SysDeptServiceImpl.class);

    @Resource
    private SysDeptMapper mapper;

    @Resource
    private OwnerMapper ownerMapper;

    @Override
    public List<DeptTreeSelect> selectDeptTreeList(SysDept dept) {
        List<SysDept> depts = SpringUtils.getAopProxy(this).selectDeptList(dept);
        return buildDeptTreeSelect(depts);
    }

    @Override
    public List<SysUser> selectUserList(DeptEquipmentConfig user) {
        if(user.getDeptId()==null||"".equals(user.getDeptId())){
            Long deptId = SecurityUtils.getLoginUser().getSysUser().getDeptId();
            user.setDeptId(deptId);
        }
        List<SysUser> sysUsers = mapper.selectUserList(user);
        return sysUsers;
    }

    @Override
    public AjaxResult selectConfigList(DeptEquipmentConfig user) {
        try {
            List<ConfigEntity> configEntities = mapper.selectConfigList(user);
            return ObjectUtils.isNotEmpty(configEntities) ? AjaxResult.success(configEntities) : AjaxResult.success();
        } catch (Exception e) {
            log.error(e.getMessage());
            return AjaxResult.success();
        }
    }

    @Override
    public AjaxResult getTree() {
        try {
            List<DeptTreeSelect> sysDepts = mapper.getTree();
            return ObjectUtils.isNotEmpty(sysDepts) ? AjaxResult.success(sysDepts) : AjaxResult.success();
        } catch (Exception e) {
            log.error(e.getMessage());
            return AjaxResult.success();
        }
    }

    @Override
    public List<DeptConfigRateSummary> selectDeptConfigRatePivot(DeptConfigRateSummary entity) {
        // 1. 查询配置率项（每条代表一个公司+设备+评分项）
        Long deptId = SecurityUtils.getLoginUser().getSysUser().getDeptId();
        entity.setDeptId(deptId);
        List<DeptConfigRateSummary> configList = mapper.selectDeptConfigRatePivot(entity);
        BigDecimal max = new BigDecimal("20");
        // 2. 查询 ma_own_manage 表中原始设备数据
        List<Ownerdomin> ownListFromManage = ownerMapper.list(null);

        // 3. 查询 ma_dev_info 表中聚合后的设备数据（包含公司名）
        List<NewOwnerdomin> ownListFromDevInfo = ownerMapper.listGrouped();

        // 4. 构建设备索引 Map<公司ID_设备名, List<Ownerdomin>>
        Map<String, List<Ownerdomin>> ownIndex = new HashMap<>();

        /*从自己配置的自有、外租表里面进行遍历  目的是放到对应的键里面去*/
        for (Ownerdomin device : ownListFromManage) {
            String key = device.getCompanyId() + "_" + device.getMaNameId();
            ownIndex.computeIfAbsent(key, k -> new ArrayList<>()).add(device);
        }
        /*去ma_dev_info装置配置表里面获取可有重复装备的数据*/
        for (NewOwnerdomin dev : ownListFromDevInfo) {
            String key = dev.getCompanyId() + "_" + dev.getTypeId() + "_" + dev.getDevType();
            List<Ownerdomin> existList = ownIndex.get(key);
            if (existList != null && !existList.isEmpty()) {
                for (Ownerdomin device : existList) {
                    //  1. 累加设备数量
                    device.setMaNum(device.getMaNum() + dev.getMaNum());

                    // 2. 只有当原类型不是 "1"（即不是“租赁”）时才改成 "2"自有
                    if (!"1".equals(device.getType())) {
                        device.setType("2");
                    }
                }
            } else {
                Ownerdomin newDevice = new Ownerdomin();
                newDevice.setCompanyId((long) dev.getCompanyId());
                newDevice.setMaName(dev.getMaName());
                newDevice.setType("2");
                newDevice.setOrderCount(dev.getOrderCount());
                newDevice.setMaNum(dev.getMaNum());
                ownIndex.computeIfAbsent(key, k -> new ArrayList<>()).add(newDevice);
            }
        }

        // 5. 构建公司 → 汇总对象 Map<String, DeptConfigRateSummary>
        Map<String, DeptConfigRateSummary> companyMap = new LinkedHashMap<>();

        for (DeptConfigRateSummary config : configList) {
            String company = config.getCompanyName();
            String type = config.getConfigType().toPlainString(); // 0:线路 1:电缆 2:变电
            String isNew = config.getIsNew(); // 0:线路 1:电缆 2:变电
            String typeId = config.getTypeId();
            String devType = config.getDevType();
            BigDecimal orderCount = config.getOrderCount();
            Long configCompanyId = config.getCompanyId();

            String key = configCompanyId + "_" + typeId + "_" + devType;
            List<Ownerdomin> sameCompanyDevices = ownIndex.getOrDefault(key, Collections.emptyList());

            BigDecimal score = computeScoreByMaName(orderCount, sameCompanyDevices, config, type);

            BigDecimal newscore = null;
            //针对订单数量大于0的进行计算（需要给外租也就是type=1的进行赋值）
            if (orderCount.compareTo(BigDecimal.ZERO) > 0
                    && (sameCompanyDevices == null || sameCompanyDevices.isEmpty())) {
                newscore = computeScoreByOrder(config);
            }
            DeptConfigRateSummary dto = companyMap.computeIfAbsent(company, k -> {
                DeptConfigRateSummary d = new DeptConfigRateSummary();
                d.setDeptName(config.getDeptName());
                d.setConfigType(config.getConfigType());
                d.setIsNew(config.getIsNew());
                d.setCompanyId(configCompanyId);
                d.setCompanyName(company);
                d.setValueA(BigDecimal.ZERO);
                d.setValueB(BigDecimal.ZERO);
                d.setValueC(BigDecimal.ZERO);
                d.setNewValueA(BigDecimal.ZERO);
                d.setNewValueB(BigDecimal.ZERO);
                d.setNewValueC(BigDecimal.ZERO);
                return d;
            });

            switch (type) {
                case "0":
                    if (!isNew.equals("0")) {
                        BigDecimal oldValue = dto.getNewValueA();
                        BigDecimal newValue = oldValue.add(score);
                        if (newValue.compareTo(max) > 0) {
                            dto.setNewValueA(max);
                        } else {
                            dto.setNewValueA(dto.getNewValueA().add(score));
                        }
                    } else {
                        dto.setValueA(dto.getValueA().add(score));
                        dto.setValueA(
                                (dto.getValueA() == null ? BigDecimal.ZERO : dto.getValueA())
                                        .add(newscore == null ? BigDecimal.ZERO : newscore)
                        );
                    }
                    break;
                case "1":
                    if (!isNew.equals("0")) {
                        BigDecimal oldValue = dto.getNewValueB();
                        BigDecimal newValue = oldValue.add(score);
                        if (newValue.compareTo(max) > 0) {
                            dto.setNewValueB(max);

                        } else {
                            dto.setNewValueB(dto.getNewValueB().add(score));
                        }
                    } else {
                        dto.setValueB(dto.getValueB().add(score));
                        dto.setValueB(
                                (dto.getValueB() == null ? BigDecimal.ZERO : dto.getValueB())
                                        .add(newscore == null ? BigDecimal.ZERO : newscore)
                        );
                    }
                    break;
                case "2":
                    if (!isNew.equals("0")) {
                        BigDecimal oldValue = dto.getNewValueC();
                        BigDecimal newValue = oldValue.add(score);
                        if (newValue.compareTo(max) > 0) {
                            dto.setNewValueC(max);

                        } else {
                            dto.setNewValueC(dto.getNewValueC().add(score));
                        }
                    } else {
                        dto.setValueC(dto.getValueC().add(score));
                        dto.setValueC(
                                (dto.getValueC() == null ? BigDecimal.ZERO : dto.getValueC())
                                        .add(newscore == null ? BigDecimal.ZERO : newscore)
                        );
                    }
                    break;
            }
        }

        // 6. 返回汇总结果
        return new ArrayList<>(companyMap.values());

    }

    private BigDecimal computeScoreByOrder(DeptConfigRateSummary config) {

        BigDecimal leaseNum;
        BigDecimal orderCount = config.getOrderCount() != null ? config.getOrderCount() : BigDecimal.ZERO; // 订单数量
        leaseNum = orderCount;
        //  BigDecimal configValue = config.getConfigValue();//自有人员数量
        BigDecimal configValue = BigDecimal.valueOf(0);
        BigDecimal baseNum = config.getConfigValue();  // 基本配置数量（F列）
        BigDecimal configRate = config.getConfigRate(); // 满分值（K列）

        // 权重
        BigDecimal leaseWeight = new BigDecimal("0.6");
        BigDecimal orderWeight = new BigDecimal("0.9");

        // 实际值 = 自有 + 租赁×0.6 + 订单×0.9
        BigDecimal actual = configValue
                .add(leaseNum.multiply(leaseWeight))
                .add(orderCount.multiply(orderWeight));

        if (baseNum == null || baseNum.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO; // 避免除以 0，可按需调整为 configRate
        }

        // 计算比例
        BigDecimal ratio = actual.divide(baseNum, 4, RoundingMode.HALF_UP);

        // 最终得分
        if (ratio.compareTo(BigDecimal.ONE) >= 0) {
            System.err.println("比例大于1，得分为满分" + config.getDeptName() + " " + config.toString());
            return configRate; // 满分
        } else {
            System.err.println("比例 × 满分" + config.getDeptName() + " " + config.toString());
            return ratio.multiply(configRate).setScale(2, RoundingMode.HALF_UP); // 比例 × 满分
        }
    }

    private BigDecimal computeScoreByMaName(BigDecimal ordercount, List<Ownerdomin> owns, DeptConfigRateSummary config, String type) {
        if (config == null || owns == null || owns.isEmpty()) return BigDecimal.ZERO;

        BigDecimal ownedTotal = BigDecimal.ZERO;
        BigDecimal leasedTotal = BigDecimal.ZERO;
        boolean limitedType = false; // 是否是 3/4/5 类型
        for (Ownerdomin own : owns) {
            BigDecimal num = new BigDecimal(own.getMaNum());

            // 判断是否为限制分数的类型
            if ("3".equals(own.getType()) || "4".equals(own.getType()) || "5".equals(own.getType())) {
                limitedType = true;
            }
            //如果ordercount大于0，则计算得分leasedTotal+ordercount
            if (ordercount.compareTo(BigDecimal.ZERO) > 0) {
                leasedTotal = leasedTotal.add(ordercount);
            }
            if ("2".equals(own.getType())) {
                ownedTotal = ownedTotal.add(num); // 自有
            } else if ("1".equals(own.getType())) {
                leasedTotal = leasedTotal.add(num); // 租赁
            }
        }

        BigDecimal base = config.getConfigValue();  // 基本配置数量
        BigDecimal score = config.getConfigRate();  // 满分值

        if (base == null || base.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        }


        // 计算比例 = (自有 + 租赁×0.6 + 订单×0.9) / 基本配置标准数量
        BigDecimal rate = ownedTotal
                .add(leasedTotal.multiply(new BigDecimal("0.6")))
                .add(ordercount.multiply(new BigDecimal("0.9")))
                .divide(base, 4, RoundingMode.HALF_UP);

        // 计算原始得分
        BigDecimal result = rate.multiply(score).setScale(2, RoundingMode.HALF_UP);

        // 限制得分不超过满分，且如果是 3/4/5 类型，不能超过 20
        if (rate.compareTo(BigDecimal.ONE) > 0) {
            result = score.setScale(2, RoundingMode.HALF_UP);
        }

        if (limitedType && result.compareTo(new BigDecimal("20")) > 0) {
            result = new BigDecimal("20.00");
        }
        return result;

    }

    @Override
    public List<DeptConfigTypeSummary> selectDeptConfigTypeSummary(DeptConfigTypeSummary entity) {
        return mapper.selectDeptConfigTypeSummary(entity);
    }

    @Override
    public List<EquipmentDetail> detailsInfo(EquipmentDetail equipmentDetail) {
        // 1. 原查询，返回 EquipmentDetail 列表
        return mapper.detailsInfo(equipmentDetail);
    }


    /**
     * 查询部门管理数据
     *
     * @param dept 部门信息
     * @return 部门信息集合
     */
    @DataScope(deptAlias = "d")
    public List<SysDept> selectDeptList(SysDept dept) {
        try {
            BaseEntity entity = CommonDataPermissionInfo.backMissionInfo(dept.getParams().get("dataScope").toString());
            BeanUtils.copyProperties(entity, dept);
        } catch (Exception e) {
            log.error("类型转换失败:", e);
            e.printStackTrace();
        }
        if (dept.getDeptName() != null) {
            String str = dept.getDeptName().replace("\\", "\\\\").replace("%", "\\%").replace("_", "\\_");
            dept.setDeptName(str);
        }
        dept.setCompanyId(Optional.ofNullable(SecurityUtils.getLoginUser().getSysUser().getCompanyId()).orElse(SecurityUtils.getLoginUser().getSysUser().getDeptId()));
        return mapper.selectDeptList(dept);
    }

    public List<DeptTreeSelect> buildDeptTreeSelect(List<SysDept> depts) {
        List<SysDept> deptTrees = buildDeptTree(depts);
        return deptTrees.stream().map(DeptTreeSelect::new).collect(Collectors.toList());
    }

    public List<SysDept> buildDeptTree(List<SysDept> depts) {
        List<SysDept> returnList = new ArrayList<>();
        List<Long> tempList = depts.stream().map(SysDept::getDeptId).collect(Collectors.toList());
        for (SysDept dept : depts) {
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(dept.getParentId())) {
                recursionFn(depts, dept);
                returnList.add(dept);
            }
        }
        if (returnList.isEmpty()) {
            returnList = depts;
        }
        return returnList;
    }

    private void recursionFn(List<SysDept> list, SysDept t) {
        // 得到子节点列表
        List<SysDept> childList = getChildList(list, t);
        t.setChildren(childList);
        for (SysDept tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    private List<SysDept> getChildList(List<SysDept> list, SysDept t) {
        List<SysDept> tlist = new ArrayList<>();
        for (SysDept n : list) {
            if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getDeptId().longValue()) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    private boolean hasChild(List<SysDept> list, SysDept t) {
        return !getChildList(list, t).isEmpty();
    }
}
