package com.ruoyi.ems.domain;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.huashe.common.annotation.Excel;
import com.huashe.common.domain.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.util.Date;
import java.util.List;

/**
 * 告警记录对象 adm_op_alarm
 *
 * 【设计说明】
 * 1. 完整的告警生命周期：活动 → 确认 → 处置中 → 已解决/已关闭/已恢复
 * 2. 支持告警聚合（同一规则同一对象的重复告警）
 * 3. 记录告警来源（实时监测/巡检/手动上报）
 */
@Data
@EqualsAndHashCode(callSuper = true)
public class Alarm extends BaseEntity {
    private static final long serialVersionUID = 1L;

    private Long id;

    /** 告警唯一标识 */
    @Excel(name = "告警ID")
    private String alarmId;

    /** 区域代码 */
    private String areaCode;

    /** 区域名称 */
    @Excel(name = "区域")
    private String areaName;

    /** 子系统代码 */
    private String subsystemCode;

    /** 子系统名称 */
    @Excel(name = "子系统")
    private String subsystemName;

    /** 目标类型 0:区域 1:设施 2:设备 */
    private Integer targetType;

    /** 目标代码 */
    @Excel(name = "目标代码")
    private String targetCode;

    /** 目标名称 */
    @Excel(name = "目标名称")
    private String targetName;

    /** 设备模型 */
    private String deviceModel;

    /** 设备模型名称 */
    private String deviceModelName;

    /** 位置信息 */
    @Excel(name = "位置")
    private String location;

    /** 触发规则代码 */
    private String ruleCode;

    /** 触发规则名称 */
    @Excel(name = "触发规则")
    private String ruleName;

    /** 告警属性 */
    private String attrKey;

    /** 属性名称 */
    @Excel(name = "告警属性")
    private String attrName;

    /** 告警时属性值 */
    @Excel(name = "告警值")
    private String attrValue;

    /** 阈值 */
    @Excel(name = "阈值")
    private String thresholdValue;

    /** 告警级别 1:一般 2:重要 3:紧急 */
    @Excel(name = "告警级别", readConverterExp = "1=一般,2=重要,3=紧急")
    private Integer alarmLevel;

    /** 告警代码 */
    @Excel(name = "告警代码")
    private String alarmCode;

    /** 告警消息 */
    @Excel(name = "告警消息")
    private String alarmMsg;

    /** 告警来源 1:实时监测 2:自动巡检 3:手动上报 */
    @Excel(name = "告警来源", readConverterExp = "1=实时监测,2=自动巡检,3=手动上报")
    private Integer alarmSource;

    /** 来源关联(如巡检报告代码) */
    private String sourceRef;

    /** 告警时间 */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @Excel(name = "告警时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
    private Date alarmTime;

    /** 告警日期(便于分区和查询) */
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date alarmDate;

    /** 告警状态 0:活动 1:已确认 2:处置中 3:已解决 4:已关闭 5:已恢复 */
    @Excel(name = "告警状态", readConverterExp = "0=活动,1=已确认,2=处置中,3=已解决,4=已关闭,5=已恢复")
    private Integer alarmStatus;

    /** 确认时间 */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date confirmTime;

    /** 确认人 */
    private String confirmBy;

    /** 解决时间 */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date resolveTime;

    /** 解决人 */
    private String resolveBy;

    /** 解决备注 */
    private String resolveRemark;

    /** 自动恢复时间 */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date recoveryTime;

    /** 持续时长(秒) */
    private Integer duration;

    /** 重复次数(聚合) */
    private Integer repeatCount;

    /** 最后发生时间 */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date lastOccurTime;

    /** 是否已通知 0:否 1:是 */
    private Integer isNotified;

    /** 通知时间 */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date notifyTime;

    /** 处置记录列表(查询时关联) */
    private List<AlarmHandle> handleList;

    // ==================== 状态常量 ====================

    public static final int STATUS_ACTIVE = 0;      // 活动
    public static final int STATUS_CONFIRMED = 1;   // 已确认
    public static final int STATUS_HANDLING = 2;    // 处置中
    public static final int STATUS_RESOLVED = 3;    // 已解决
    public static final int STATUS_CLOSED = 4;      // 已关闭
    public static final int STATUS_RECOVERED = 5;   // 已恢复

    // ==================== 来源常量 ====================

    public static final int SOURCE_REALTIME = 1;    // 实时监测
    public static final int SOURCE_INSPECTION = 2;  // 自动巡检
    public static final int SOURCE_MANUAL = 3;      // 手动上报

    // ==================== 级别常量 ====================

    public static final int LEVEL_NORMAL = 1;       // 一般
    public static final int LEVEL_IMPORTANT = 2;    // 重要
    public static final int LEVEL_URGENT = 3;       // 紧急

    /**
     * 获取告警状态描述
     */
    public String getAlarmStatusDesc() {
        if (alarmStatus == null) {
            return "未知";
        }
        switch (alarmStatus) {
            case STATUS_ACTIVE:
                return "活动";
            case STATUS_CONFIRMED:
                return "已确认";
            case STATUS_HANDLING:
                return "处置中";
            case STATUS_RESOLVED:
                return "已解决";
            case STATUS_CLOSED:
                return "已关闭";
            case STATUS_RECOVERED:
                return "已恢复";
            default:
                return "未知";
        }
    }

    /**
     * 获取告警来源描述
     */
    public String getAlarmSourceDesc() {
        if (alarmSource == null) {
            return "未知";
        }
        switch (alarmSource) {
            case SOURCE_REALTIME:
                return "实时监测";
            case SOURCE_INSPECTION:
                return "自动巡检";
            case SOURCE_MANUAL:
                return "手动上报";
            default:
                return "未知";
        }
    }

    /**
     * 获取告警级别描述
     */
    public String getAlarmLevelDesc() {
        if (alarmLevel == null) {
            return "未知";
        }
        switch (alarmLevel) {
            case LEVEL_NORMAL:
                return "一般";
            case LEVEL_IMPORTANT:
                return "重要";
            case LEVEL_URGENT:
                return "紧急";
            default:
                return "未知";
        }
    }

    /**
     * 判断是否为活动告警
     */
    public boolean isActive() {
        return alarmStatus != null && alarmStatus == STATUS_ACTIVE;
    }

    /**
     * 判断是否已结束
     */
    public boolean isEnded() {
        return alarmStatus != null && (alarmStatus == STATUS_RESOLVED
            || alarmStatus == STATUS_CLOSED
            || alarmStatus == STATUS_RECOVERED);
    }

    /**
     * 计算持续时长(秒)
     */
    public Integer calculateDuration() {
        if (alarmTime == null) {
            return null;
        }
        Date endTime = recoveryTime != null ? recoveryTime :
            (resolveTime != null ? resolveTime : new Date());
        return (int) ((endTime.getTime() - alarmTime.getTime()) / 1000);
    }
}