package com.zcloud.personnel.positioning.command.query;

import com.alibaba.cola.dto.PageResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jjb.saas.framework.auth.model.SSOUser;
import com.jjb.saas.framework.auth.utils.AuthContext;
import com.zcloud.gbscommon.utils.PageQueryHelper;
import com.zcloud.personnel.positioning.command.AlarmRuleConfigPersistence;
import com.zcloud.personnel.positioning.command.convertor.AlarmRuleCoConvertor;
import com.zcloud.personnel.positioning.command.convertor.AlarmRuleFenceRelCoConvertor;
import com.zcloud.personnel.positioning.command.convertor.AlarmRuleItemCoConvertor;
import com.zcloud.personnel.positioning.dto.AlarmRuleCompanyPageQry;
import com.zcloud.personnel.positioning.dto.AlarmRulePageQry;
import com.zcloud.personnel.positioning.dto.clientobject.AlarmRuleCO;
import com.zcloud.personnel.positioning.dto.clientobject.AlarmRuleCompanyStatCO;
import com.zcloud.personnel.positioning.dto.clientobject.AlarmRuleFenceRelCO;
import com.zcloud.personnel.positioning.dto.clientobject.AlarmRuleItemCO;
import com.zcloud.personnel.positioning.dto.clientobject.OptionCO;
import com.zcloud.personnel.positioning.persistence.dataobject.AlarmRuleDO;
import com.zcloud.personnel.positioning.persistence.dataobject.AlarmRuleCompanyStatDO;
import com.zcloud.personnel.positioning.persistence.dataobject.AlarmRuleFenceRelDO;
import com.zcloud.personnel.positioning.persistence.dataobject.AlarmRuleItemDO;
import com.zcloud.personnel.positioning.persistence.dataobject.CompanyOptionDO;
import com.zcloud.personnel.positioning.persistence.repository.AlarmRuleFenceRelRepository;
import com.zcloud.personnel.positioning.persistence.repository.AlarmRuleItemRepository;
import com.zcloud.personnel.positioning.persistence.repository.AlarmRuleRepository;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * web-app
 *
 * @Author fangjiakai
 * @Date 2026-07-07
 */
@Component
@AllArgsConstructor
public class AlarmRuleQueryExe {
    private final AlarmRuleRepository alarmRuleRepository;
    private final AlarmRuleFenceRelRepository alarmRuleFenceRelRepository;
    private final AlarmRuleItemRepository alarmRuleItemRepository;
    private final AlarmRuleCoConvertor alarmRuleCoConvertor;
    private final AlarmRuleFenceRelCoConvertor alarmRuleFenceRelCoConvertor;
    private final AlarmRuleItemCoConvertor alarmRuleItemCoConvertor;

    public PageResponse<AlarmRuleCompanyStatCO> listCompanyStats(AlarmRuleCompanyPageQry qry) {
        AlarmRuleCompanyPageQry query = qry == null ? new AlarmRuleCompanyPageQry() : qry;
        Map<String, Object> params = PageQueryHelper.toHashMap(query);
        String ruleStatus = normalizeStatus(query.getEqRuleStatus());
        if (StringUtils.hasText(ruleStatus)) {
            params.put("eqRuleStatus", ruleStatus);
        }
        PageResponse<AlarmRuleCompanyStatDO> pageResponse = alarmRuleRepository.listCompanyStats(params);
        List<AlarmRuleCompanyStatCO> data = alarmRuleCoConvertor
                .converCompanyStatDOsToCOs(pageResponse.getData());
        return PageResponse.of(data, pageResponse.getTotalCount(), pageResponse.getPageSize(), pageResponse.getPageIndex());
    }

    public List<OptionCO> listCompanyOptions(String keyword) {
        Map<String, Object> params = new HashMap<>();
        SSOUser ssoUser = AuthContext.getCurrentUser();
        if (ssoUser != null && ssoUser.getCompanyId() != null) {
            params.put("eqCorpinfoId", String.valueOf(ssoUser.getCompanyId()));
        }
        if (StringUtils.hasText(keyword)) {
            params.put("keyword", keyword.trim());
        }
        List<CompanyOptionDO> dataObjects = alarmRuleRepository.listCompanyOptions(params);
        return alarmRuleCoConvertor.converCompanyOptionDOsToCOs(dataObjects);
    }

    public PageResponse<AlarmRuleCO> execute(AlarmRulePageQry qry) {
        AlarmRulePageQry query = qry == null ? new AlarmRulePageQry() : qry;
        Map<String, Object> params = PageQueryHelper.toHashMap(query);
        params.put("eqDeleteEnum", "FALSE");
        normalizeListParams(params);
        fillCorpinfo(params);
        preferCorpinfoId(params);
        PageResponse<AlarmRuleDO> pageResponse = alarmRuleRepository.listPage(params);
        List<AlarmRuleCO> data = alarmRuleCoConvertor.converDOsToCOs(pageResponse.getData());
        fillFenceRelations(data);
        return PageResponse.of(data, pageResponse.getTotalCount(), pageResponse.getPageSize(), pageResponse.getPageIndex());
    }

    public List<AlarmRuleCO> listAll() {
        QueryWrapper<AlarmRuleDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("delete_enum", "FALSE");
        applyCorpinfo(queryWrapper);
        queryWrapper.orderByDesc("create_time");
        List<AlarmRuleCO> rows = alarmRuleCoConvertor.converDOsToCOs(alarmRuleRepository.list(queryWrapper));
        fillFenceRelations(rows);
        return rows;
    }

    public AlarmRuleCO queryById(Long id) {
        QueryWrapper<AlarmRuleDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", id);
        queryWrapper.eq("delete_enum", "FALSE");
        AlarmRuleDO dataObject = alarmRuleRepository.getOne(queryWrapper, false);
        AlarmRuleCO co = alarmRuleCoConvertor.converDOToCO(dataObject);
        if (co == null) {
            return null;
        }
        fillFenceRelations(Collections.singletonList(co));
        fillRuleItems(co);
        return co;
    }

    private void fillFenceRelations(List<AlarmRuleCO> rows) {
        if (rows == null || rows.isEmpty()) {
            return;
        }
        List<Long> ruleIds = rows.stream()
                .map(AlarmRuleCO::getId)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        if (ruleIds.isEmpty()) {
            return;
        }
        QueryWrapper<AlarmRuleFenceRelDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("rule_id", ruleIds);
        queryWrapper.eq("delete_enum", "FALSE");
        queryWrapper.orderByAsc("id");
        List<AlarmRuleFenceRelCO> relRows = alarmRuleFenceRelCoConvertor
                .converDOsToCOs(alarmRuleFenceRelRepository.list(queryWrapper));
        Map<Long, List<AlarmRuleFenceRelCO>> relMap = relRows.stream()
                .collect(Collectors.groupingBy(AlarmRuleFenceRelCO::getRuleId));
        for (AlarmRuleCO row : rows) {
            List<AlarmRuleFenceRelCO> relList = relMap.getOrDefault(row.getId(), Collections.emptyList());
            row.setFenceRelList(relList);
            if (AlarmRuleConfigPersistence.ATTR_COMPANY_AREA.equals(row.getAlarmAttr())) {
                row.setFenceNames("无需选择");
            } else {
                row.setFenceNames(relList.stream()
                        .map(AlarmRuleFenceRelCO::getFenceName)
                        .filter(StringUtils::hasText)
                        .distinct()
                        .collect(Collectors.joining(",")));
            }
        }
    }

    private void fillRuleItems(AlarmRuleCO row) {
        QueryWrapper<AlarmRuleItemDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("rule_id", row.getId());
        queryWrapper.eq("delete_enum", "FALSE");
        queryWrapper.orderByAsc("level", "id");
        List<AlarmRuleItemCO> itemRows = alarmRuleItemCoConvertor
                .converDOsToCOs(alarmRuleItemRepository.list(queryWrapper));
        row.setRuleItemList(itemRows);
    }

    private void fillCorpinfo(Map<String, Object> params) {
        if (params.get("eqCorpinfoId") != null
                || StringUtils.hasText((String) params.get("eqCorpinfoName"))
                || StringUtils.hasText((String) params.get("likeCorpinfoName"))) {
            return;
        }
        SSOUser ssoUser = AuthContext.getCurrentUser();
        if (ssoUser != null && ssoUser.getCompanyId() != null) {
            params.put("eqCorpinfoId", String.valueOf(ssoUser.getCompanyId()));
        }
    }

    private void preferCorpinfoId(Map<String, Object> params) {
        String corpinfoId = (String) params.get("eqCorpinfoId");
        if (!StringUtils.hasText(corpinfoId)) {
            return;
        }
        params.remove("eqCorpinfoName");
    }

    private void applyCorpinfo(QueryWrapper<AlarmRuleDO> queryWrapper) {
        SSOUser ssoUser = AuthContext.getCurrentUser();
        if (ssoUser != null && ssoUser.getCompanyId() != null) {
            queryWrapper.eq("corpinfo_id", String.valueOf(ssoUser.getCompanyId()));
        }
    }

    private void normalizeListParams(Map<String, Object> params) {
        String alarmAttr = normalizeAlarmAttr((String) params.get("eqAlarmAttr"));
        if (StringUtils.hasText(alarmAttr)) {
            params.put("eqAlarmAttr", alarmAttr);
        }
        String alarmCode = normalizeAlarmCode((String) params.get("eqAlarmCode"));
        if (StringUtils.hasText(alarmCode)) {
            params.put("eqAlarmCode", alarmCode);
        }
        String ruleStatus = normalizeStatus((String) params.get("eqRuleStatus"));
        if (StringUtils.hasText(ruleStatus)) {
            params.put("eqRuleStatus", ruleStatus);
        }
    }

    private String normalizeAlarmAttr(String value) {
        if (!StringUtils.hasText(value)) {
            return null;
        }
        String attr = value.trim();
        if ("公司区域告警".equals(attr)) {
            return AlarmRuleConfigPersistence.ATTR_COMPANY_AREA;
        }
        if ("电子围栏告警".equals(attr)) {
            return AlarmRuleConfigPersistence.ATTR_FENCE;
        }
        return attr;
    }

    private String normalizeAlarmCode(String value) {
        if (!StringUtils.hasText(value)) {
            return null;
        }
        String code = value.trim();
        if ("进入围栏告警".equals(code) || "禁入围栏告警".equals(code)) {
            return "CROSS_IN";
        }
        if ("离开围栏告警".equals(code) || "区域越界告警".equals(code)) {
            return "CROSS_OUT";
        }
        if ("超时停留告警".equals(code)) {
            return "RETENTION";
        }
        if ("脱岗告警".equals(code)) {
            return "LACKED";
        }
        if ("停留告警".equals(code)) {
            return "STAY";
        }
        if ("碰撞告警".equals(code)) {
            return "CRASH";
        }
        return code;
    }

    private String normalizeStatus(String status) {
        if (!StringUtils.hasText(status)) {
            return null;
        }
        String value = status.trim();
        if ("启用".equals(value) || "1".equals(value)) {
            return AlarmRuleConfigPersistence.STATUS_ENABLED;
        }
        if ("停用".equals(value) || "0".equals(value)) {
            return AlarmRuleConfigPersistence.STATUS_DISABLED;
        }
        return value;
    }

}
