package com.zcloud.personnel.positioning.command;

import com.alibaba.cola.exception.BizException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zcloud.personnel.positioning.dto.AlarmRuleFenceRelAddCmd;
import com.zcloud.personnel.positioning.dto.AlarmRuleItemAddCmd;
import com.zcloud.personnel.positioning.persistence.dataobject.AlarmRuleDO;
import com.zcloud.personnel.positioning.persistence.dataobject.AlarmRuleFenceRelDO;
import com.zcloud.personnel.positioning.persistence.dataobject.AlarmRuleItemDO;
import com.zcloud.personnel.positioning.persistence.dataobject.FenceDO;
import com.zcloud.personnel.positioning.persistence.repository.AlarmRuleFenceRelRepository;
import com.zcloud.personnel.positioning.persistence.repository.AlarmRuleItemRepository;
import com.zcloud.personnel.positioning.persistence.repository.FenceRepository;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.List;

/**
 * Page-facing persistence helpers for alarm rule configuration.
 *
 * @Author fangjiakai
 * @Date 2026-07-07
 */
@Component
@AllArgsConstructor
public class AlarmRuleConfigPersistence {
    public static final String ATTR_COMPANY_AREA = "COMPANY_AREA";
    public static final String ATTR_FENCE = "FENCE";
    public static final String STATUS_ENABLED = "ENABLED";
    public static final String STATUS_DISABLED = "DISABLED";
    public static final String REL_EFFECTIVE = "EFFECTIVE";
    public static final String STRATEGY_SPECIFIED = "SPECIFIED";
    public static final String FENCE_SCOPE_COMPANY_AREA = "COMPANY_AREA";

    private final AlarmRuleFenceRelRepository alarmRuleFenceRelRepository;
    private final AlarmRuleItemRepository alarmRuleItemRepository;
    private final FenceRepository fenceRepository;

    public void normalizeRule(AlarmRuleDO rule) {
        rule.setAlarmAttr(normalizeAlarmAttr(rule.getAlarmAttr()));
        rule.setAlarmCode(normalizeAlarmCode(rule.getAlarmCode(), rule.getAlarmName()));
        if (!StringUtils.hasText(rule.getAlarmName())) {
            rule.setAlarmName(alarmNameOf(rule.getAlarmCode()));
        }
        rule.setRuleStatus(normalizeStatus(rule.getRuleStatus(), rule.getEnable()));
        rule.setEnable(STATUS_ENABLED.equals(rule.getRuleStatus()) ? 1 : 0);
        if (!StringUtils.hasText(rule.getRuleCode())) {
            rule.setRuleCode("AR" + System.currentTimeMillis());
        }
        if (!StringUtils.hasText(rule.getRuleName())) {
            rule.setRuleName(defaultIfBlank(rule.getAlarmName(), rule.getRuleCode()));
        }
        if (!StringUtils.hasText(rule.getCorpinfoName()) && StringUtils.hasText(rule.getOrgName())) {
            rule.setCorpinfoName(rule.getOrgName());
        }
        if (!StringUtils.hasText(rule.getOrgName()) && StringUtils.hasText(rule.getCorpinfoName())) {
            rule.setOrgName(rule.getCorpinfoName());
        }
        if (!StringUtils.hasText(rule.getTrackTypes())) {
            rule.setTrackTypes("STAFF");
        }
        if (!StringUtils.hasText(rule.getFenceEffectStrategy())) {
            rule.setFenceEffectStrategy(STRATEGY_SPECIFIED);
        }
    }

    public void saveNewChildren(AlarmRuleDO rule, List<AlarmRuleFenceRelAddCmd> fenceRelList,
                                List<AlarmRuleItemAddCmd> ruleItemList) {
        rebuildFenceRelations(rule, fenceRelList);
        rebuildRuleItems(rule, ruleItemList, true);
    }

    public void rebuildFenceRelations(AlarmRuleDO rule, List<AlarmRuleFenceRelAddCmd> fenceRelList) {
        QueryWrapper<AlarmRuleFenceRelDO> removeWrapper = new QueryWrapper<>();
        removeWrapper.eq("rule_id", rule.getId());
        alarmRuleFenceRelRepository.remove(removeWrapper);

        if (fenceRelList == null || fenceRelList.isEmpty()) {
            if (ATTR_COMPANY_AREA.equals(rule.getAlarmAttr())) {
                saveCompanyAreaFenceRelations(rule);
                return;
            }
            if (ATTR_FENCE.equals(rule.getAlarmAttr())) {
                throw new BizException("电子围栏告警需要选择关联围栏");
            }
            return;
        }
        if (ATTR_FENCE.equals(rule.getAlarmAttr()) && fenceRelList.size() > 1) {
            throw new BizException("Electronic fence alarm rule can only bind one fence");
        }

        for (AlarmRuleFenceRelAddCmd relCmd : fenceRelList) {
            AlarmRuleFenceRelDO rel = new AlarmRuleFenceRelDO();
            BeanUtils.copyProperties(relCmd, rel);
            rel.setRuleId(rule.getId());
            rel.setCorpinfoId(defaultString(rel.getCorpinfoId(), rule.getCorpinfoId()));
            rel.setCorpinfoName(defaultIfBlank(rel.getCorpinfoName(), rule.getCorpinfoName()));
            rel.setRelType(defaultIfBlank(rel.getRelType(), REL_EFFECTIVE));
            fillFenceSnapshot(rel);
            alarmRuleFenceRelRepository.save(rel);
        }
    }

    public void rebuildRuleItems(AlarmRuleDO rule, List<AlarmRuleItemAddCmd> ruleItemList, boolean createDefaultWhenEmpty) {
        QueryWrapper<AlarmRuleItemDO> removeWrapper = new QueryWrapper<>();
        removeWrapper.eq("rule_id", rule.getId());
        alarmRuleItemRepository.remove(removeWrapper);

        if (ruleItemList == null || ruleItemList.isEmpty()) {
            if (createDefaultWhenEmpty) {
                AlarmRuleItemDO item = new AlarmRuleItemDO();
                item.setRuleId(rule.getId());
                item.setCorpinfoId(rule.getCorpinfoId());
                item.setCorpinfoName(rule.getCorpinfoName());
                item.setLevel(1);
                item.setEnable(rule.getEnable());
                alarmRuleItemRepository.save(item);
            }
            return;
        }

        for (AlarmRuleItemAddCmd itemCmd : ruleItemList) {
            AlarmRuleItemDO item = new AlarmRuleItemDO();
            BeanUtils.copyProperties(itemCmd, item);
            item.setRuleId(rule.getId());
            item.setCorpinfoId(defaultString(item.getCorpinfoId(), rule.getCorpinfoId()));
            item.setCorpinfoName(defaultIfBlank(item.getCorpinfoName(), rule.getCorpinfoName()));
            if (item.getLevel() == null) {
                item.setLevel(1);
            }
            if (item.getEnable() == null) {
                item.setEnable(rule.getEnable());
            }
            alarmRuleItemRepository.save(item);
        }
    }

    public void syncRuleItemEnable(Long ruleId, Integer enable) {
        QueryWrapper<AlarmRuleItemDO> wrapper = new QueryWrapper<>();
        wrapper.eq("rule_id", ruleId);
        List<AlarmRuleItemDO> items = alarmRuleItemRepository.list(wrapper);
        for (AlarmRuleItemDO item : items) {
            item.setEnable(enable);
            alarmRuleItemRepository.updateById(item);
        }
    }

    private void saveCompanyAreaFenceRelations(AlarmRuleDO rule) {
        QueryWrapper<FenceDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("fence_scope", FENCE_SCOPE_COMPANY_AREA);
        queryWrapper.eq("status", STATUS_ENABLED);
        queryWrapper.eq("delete_enum", "FALSE");
        if (rule.getCorpinfoId() != null) {
            queryWrapper.eq("corpinfo_id", rule.getCorpinfoId());
        } else if (StringUtils.hasText(rule.getCorpinfoName())) {
            queryWrapper.eq("corpinfo_name", rule.getCorpinfoName());
        } else {
            throw new BizException("公司区域告警需要所属公司");
        }
        List<FenceDO> fences = fenceRepository.list(queryWrapper);
        if (fences == null || fences.isEmpty()) {
            throw new BizException("未找到该公司的公司区域围栏");
        }
        for (FenceDO fence : fences) {
            AlarmRuleFenceRelDO rel = new AlarmRuleFenceRelDO();
            rel.setRuleId(rule.getId());
            rel.setFenceId(fence.getId());
            rel.setFenceName(fence.getFenceName());
            rel.setFindsFenceId(fence.getFindsFenceId());
            rel.setRelType(REL_EFFECTIVE);
            rel.setCorpinfoId(defaultString(rule.getCorpinfoId(), fence.getCorpinfoId()));
            rel.setCorpinfoName(defaultIfBlank(rule.getCorpinfoName(), fence.getCorpinfoName()));
            alarmRuleFenceRelRepository.save(rel);
        }
    }

    private void fillFenceSnapshot(AlarmRuleFenceRelDO rel) {
        if (rel.getFenceId() == null) {
            return;
        }
        FenceDO fence = fenceRepository.getById(rel.getFenceId());
        if (fence == null) {
            return;
        }
        rel.setFenceName(defaultIfBlank(rel.getFenceName(), fence.getFenceName()));
        rel.setFindsFenceId(defaultLong(rel.getFindsFenceId(), fence.getFindsFenceId()));
        rel.setCorpinfoId(defaultString(rel.getCorpinfoId(), fence.getCorpinfoId()));
        rel.setCorpinfoName(defaultIfBlank(rel.getCorpinfoName(), fence.getCorpinfoName()));
    }

    private String normalizeAlarmAttr(String value) {
        if (!StringUtils.hasText(value)) {
            throw new BizException("请选择告警属性");
        }
        String attr = value.trim();
        if ("公司区域告警".equals(attr)) {
            return ATTR_COMPANY_AREA;
        }
        if ("电子围栏告警".equals(attr)) {
            return ATTR_FENCE;
        }
        return attr;
    }

    private String normalizeAlarmCode(String alarmCode, String alarmName) {
        String value = StringUtils.hasText(alarmCode) ? alarmCode.trim() : alarmName;
        if (!StringUtils.hasText(value)) {
            throw new BizException("请选择告警类型");
        }
        if ("进入围栏告警".equals(value) || "禁入围栏告警".equals(value)) {
            return "CROSS_IN";
        }
        if ("离开围栏告警".equals(value) || "区域越界告警".equals(value)) {
            return "CROSS_OUT";
        }
        if ("超时停留告警".equals(value)) {
            return "RETENTION";
        }
        if ("脱岗告警".equals(value)) {
            return "LACKED";
        }
        return value.trim();
    }

    private String alarmNameOf(String alarmCode) {
        if ("CROSS_IN".equals(alarmCode)) {
            return "进入围栏告警";
        }
        if ("CROSS_OUT".equals(alarmCode)) {
            return "离开围栏告警";
        }
        if ("RETENTION".equals(alarmCode)) {
            return "超时停留告警";
        }
        if ("LACKED".equals(alarmCode)) {
            return "脱岗告警";
        }
        if ("STAY".equals(alarmCode)) {
            return "停留告警";
        }
        return alarmCode;
    }

    private String normalizeStatus(String ruleStatus, Integer enable) {
        if (StringUtils.hasText(ruleStatus)) {
            String status = ruleStatus.trim();
            if ("启用".equals(status) || "1".equals(status)) {
                return STATUS_ENABLED;
            }
            if ("停用".equals(status) || "0".equals(status)) {
                return STATUS_DISABLED;
            }
            return status;
        }
        return enable != null && enable == 0 ? STATUS_DISABLED : STATUS_ENABLED;
    }

    private String defaultIfBlank(String value, String defaultValue) {
        return StringUtils.hasText(value) ? value : defaultValue;
    }

    private Long defaultLong(Long value, Long defaultValue) {
        return value == null ? defaultValue : value;
    }

    private String defaultString(String value, String defaultValue) {
        return StringUtils.hasText(value) ? value : defaultValue;
    }
}
