package com.aegis.emergency.alert.service.impl;

import java.util.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.aegis.common.exception.ServiceException;
import com.aegis.common.utils.SecurityUtils;
import com.aegis.common.utils.StringUtils;
import com.aegis.common.utils.uuid.Seq;
import com.aegis.emergency.alert.constant.AlertInitialLevel;
import com.aegis.emergency.alert.constant.AlertLogAction;
import com.aegis.emergency.alert.constant.AlertSourceChannel;
import com.aegis.emergency.alert.constant.AlertStatus;
import com.aegis.emergency.alert.domain.DutyAlert;
import com.aegis.emergency.alert.service.DutyAlertLogService;
import com.aegis.emergency.alert.mapper.DutyAlertMapper;
import com.aegis.emergency.alert.service.DutyAlertService;

/**
 * 警情Service业务层处理
 * 
 * @author aegis
 */
@Service
public class DutyAlertServiceImpl extends ServiceImpl<DutyAlertMapper, DutyAlert> implements DutyAlertService {

    @Autowired
    private DutyAlertLogService alertLogService;

    /**
     * 根据条件查询警情列表
     * 
     * @param condition 警情信息
     * @return 警情集合
     */
    @Override
    public List<DutyAlert> listByCondition(DutyAlert condition) {
        LambdaQueryWrapper<DutyAlert> wrapper = new LambdaQueryWrapper<>();
        if (condition != null) {
            if (StringUtils.isNotEmpty(condition.getAlertNo())) {
                wrapper.eq(DutyAlert::getAlertNo, condition.getAlertNo());
            }
            if (StringUtils.isNotEmpty(condition.getSourceChannel())) {
                wrapper.eq(DutyAlert::getSourceChannel, condition.getSourceChannel());
            }
            if (StringUtils.isNotEmpty(condition.getStatus())) {
                wrapper.eq(DutyAlert::getStatus, condition.getStatus());
            }
            if (StringUtils.isNotEmpty(condition.getInitialLevel())) {
                wrapper.eq(DutyAlert::getInitialLevel, condition.getInitialLevel());
            }
            if (StringUtils.isNotEmpty(condition.getCallerNumber())) {
                wrapper.eq(DutyAlert::getCallerNumber, condition.getCallerNumber());
            }
            // 发生时间范围查询（优先于精确时间查询）
            if (condition.getBeginOccurredAt() != null && condition.getEndOccurredAt() != null) {
                wrapper.between(DutyAlert::getOccurredAt, condition.getBeginOccurredAt(), condition.getEndOccurredAt());
            } else if (condition.getBeginOccurredAt() != null) {
                wrapper.ge(DutyAlert::getOccurredAt, condition.getBeginOccurredAt());
            } else if (condition.getEndOccurredAt() != null) {
                wrapper.le(DutyAlert::getOccurredAt, condition.getEndOccurredAt());
            } else if (condition.getOccurredAt() != null) {
                // 精确时间查询（当没有范围查询时）
                wrapper.eq(DutyAlert::getOccurredAt, condition.getOccurredAt());
            }
        }
        wrapper.eq(DutyAlert::getDelFlag, "0"); // 只查询未删除的记录
        wrapper.orderByDesc(DutyAlert::getOccurredAt); // 按发生时间倒序
        return list(wrapper);
    }

    /**
     * 根据ID查询警情（重写IService的getById方法，增加逻辑删除检查）
     * 
     * @param id 警情ID
     * @return 警情信息
     */
    @Override
    public DutyAlert getById(java.io.Serializable id) {
        if (id == null) {
            throw new ServiceException("警情ID不能为空");
        }
        DutyAlert alert = super.getById(id);
        if (alert != null && "2".equals(alert.getDelFlag())) {
            return null; // 已删除的记录返回 null
        }
        return alert;
    }

    /**
     * 根据警情编号查询警情
     * 
     * @param alertNo 警情编号
     * @return 警情信息
     */
    @Override
    public DutyAlert getByAlertNo(String alertNo) {
        if (StringUtils.isEmpty(alertNo)) {
            throw new ServiceException("警情编号不能为空");
        }
        LambdaQueryWrapper<DutyAlert> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DutyAlert::getAlertNo, alertNo);
        wrapper.eq(DutyAlert::getDelFlag, "0");
        return getOne(wrapper);
    }

    /**
     * 新增警情（重写 IService.save）
     * 
     * @param alert 警情信息
     * @return 是否保存成功
     */
    @Override
    @Transactional
    public boolean save(DutyAlert alert) {
        if (alert == null) {
            throw new ServiceException("警情信息不能为空");
        }
        
        // 验证来源渠道
        if (StringUtils.isNotEmpty(alert.getSourceChannel())) {
            if (AlertSourceChannel.fromCode(alert.getSourceChannel()) == null) {
                throw new ServiceException("来源渠道无效");
            }
        }
        
        // 验证初判等级
        if (StringUtils.isNotEmpty(alert.getInitialLevel())) {
            if (AlertInitialLevel.fromCode(alert.getInitialLevel()) == null) {
                throw new ServiceException("初判等级无效，可选值：level1-一级，level2-二级，level3-三级，level4-四级");
            }
        }
        
        // 验证状态
        if (StringUtils.isNotEmpty(alert.getStatus())) {
            if (AlertStatus.fromCode(alert.getStatus()) == null) {
                throw new ServiceException("警情状态无效");
            }
        }
        
        // 生成警情编号（如果未提供）
        if (StringUtils.isEmpty(alert.getAlertNo())) {
            alert.setAlertNo("ALERT" + Seq.getId());
        } else {
            // 检查警情编号是否已存在
            DutyAlert existing = getByAlertNo(alert.getAlertNo());
            if (existing != null) {
                throw new ServiceException("警情编号已存在：" + alert.getAlertNo());
            }
        }
        
        String operator = SecurityUtils.getUsername();
        alert.setCreateBy(operator);
        alert.setCreateTime(new Date());
        alert.setUpdateBy(operator);
        alert.setUpdateTime(new Date());
        
        // 设置默认值
        if (StringUtils.isEmpty(alert.getStatus())) {
            alert.setStatus(AlertStatus.DRAFT.getCode());
        }
        if (StringUtils.isEmpty(alert.getDelFlag())) {
            alert.setDelFlag("0");
        }
        
        boolean saved = super.save(alert);
        if (saved) {
            alertLogService.recordLog(alert.getId(), AlertLogAction.ALERT_CREATE, alert);
        }
        return saved;
    }

    /**
     * 修改警情（重写IService的updateById方法，增加业务校验）
     * 
     * @param alert 警情信息
     * @return 是否更新成功
     */
    @Override
    @Transactional
    public boolean updateById(DutyAlert alert) {
        boolean updated = updateAlertSilently(alert);
        if (updated) {
            alertLogService.recordLog(alert.getId(), AlertLogAction.ALERT_UPDATE, alert);
        }
        return updated;
    }

    /**
     * 删除警情（重写IService的removeById方法，实现逻辑删除）
     * 
     * @param id 警情ID
     * @return 是否删除成功
     */
    @Override
    @Transactional
    public boolean removeById(java.io.Serializable id) {
        if (id == null) {
            throw new ServiceException("警情ID不能为空");
        }
        
        DutyAlert alert = getById(id);
        if (alert == null || "2".equals(alert.getDelFlag())) {
            throw new ServiceException("警情不存在或已删除");
        }
        
        // 逻辑删除警情
        alert.setDelFlag("2");
        String operator = SecurityUtils.getUsername();
        alert.setUpdateBy(operator);
        alert.setUpdateTime(new Date());
        
        boolean removed = super.updateById(alert);
        if (removed) {
            alertLogService.recordLog(alert.getId(), AlertLogAction.ALERT_CLOSE, alert);
        }
        return removed;
    }

    /**
     * 提交警情（从草稿状态变为已接警状态）
     * 
     * @param id 警情ID
     * @param alertData 警情更新数据（可选，如果提供则先更新数据再改变状态）
     * @return 是否提交成功
     */
    @Override
    @Transactional
    public boolean submitAlert(Long id, DutyAlert alertData) {
        if (id == null) {
            throw new ServiceException("警情ID不能为空");
        }
        
        DutyAlert alert = getById(id);
        if (alert == null || "2".equals(alert.getDelFlag())) {
            throw new ServiceException("警情不存在或已删除");
        }
        
        // 业务规则：只能提交草稿状态的警情
        if (!AlertStatus.DRAFT.getCode().equals(alert.getStatus())) {
            throw new ServiceException("只能提交草稿状态的警情，当前状态：" + alert.getStatus());
        }
        
        // 如果提供了更新数据，先更新数据（复用验证逻辑，但不记录日志）
        if (alertData != null) {
            // 设置ID以便 updateAlertSilently 能正确识别
            alertData.setId(id);
            // 临时保存当前状态，避免状态验证问题
            String originalStatus = alert.getStatus();
            alertData.setStatus(originalStatus);
            
            // 使用 updateAlertSilently 来更新数据（验证并更新字段，但不记录日志）
            updateAlertSilently(alertData);
            
            // 重新获取更新后的警情
            alert = getById(id);
        }
        
        // 更新状态为已接警
        alert.setStatus(AlertStatus.RECEIVED.getCode());
        String operator = SecurityUtils.getUsername();
        alert.setUpdateBy(operator);
        alert.setUpdateTime(new Date());
        
        // 使用 super.updateById() 直接更新状态，避免触发 ALERT_UPDATE 日志
        // 因为我们会在下面记录 ALERT_RECEIVED 日志
        boolean updated = super.updateById(alert);
        if (updated) {
            // 记录操作日志
            alertLogService.recordLog(id, AlertLogAction.ALERT_RECEIVED, alert);
        }
        return updated;
    }

    /**
     * 关闭警情（将状态变为已关闭）
     * 
     * @param id 警情ID
     * @return 是否关闭成功
     */
    @Override
    @Transactional
    public boolean closeAlert(Long id) {
        if (id == null) {
            throw new ServiceException("警情ID不能为空");
        }
        
        DutyAlert alert = getById(id);
        if (alert == null || "2".equals(alert.getDelFlag())) {
            throw new ServiceException("警情不存在或已删除");
        }
        
        // 业务规则：不能关闭已关闭的警情
        if (AlertStatus.CLOSED.getCode().equals(alert.getStatus())) {
            throw new ServiceException("警情已关闭");
        }
        
        alert.setStatus(AlertStatus.CLOSED.getCode());
        String operator = SecurityUtils.getUsername();
        alert.setUpdateBy(operator);
        alert.setUpdateTime(new Date());
        
        boolean updated = super.updateById(alert);
        if (updated) {
            // 记录操作日志
            alertLogService.recordLog(id, AlertLogAction.ALERT_CLOSE, alert);
        }
        return updated;
    }

    /**
     * 更新警情（不记录日志，供内部方法使用）
     * 
     * @param alert 警情信息
     * @return 是否更新成功
     */
    private boolean updateAlertSilently(DutyAlert alert) {
        if (alert == null || alert.getId() == null) {
            throw new ServiceException("警情信息或ID不能为空");
        }
        
        // 检查警情是否存在
        DutyAlert existingAlert = getById(alert.getId());
        if (existingAlert == null || "2".equals(existingAlert.getDelFlag())) {
            throw new ServiceException("警情不存在或已删除");
        }
        
        // 验证来源渠道
        if (StringUtils.isNotEmpty(alert.getSourceChannel())) {
            if (AlertSourceChannel.fromCode(alert.getSourceChannel()) == null) {
                throw new ServiceException("来源渠道无效");
            }
        }
        
        // 验证初判等级
        if (StringUtils.isNotEmpty(alert.getInitialLevel())) {
            if (AlertInitialLevel.fromCode(alert.getInitialLevel()) == null) {
                throw new ServiceException("初判等级无效，可选值：level1-一级，level2-二级，level3-三级，level4-四级");
            }
        }
        
        // 验证状态
        if (StringUtils.isNotEmpty(alert.getStatus())) {
            AlertStatus newStatus = AlertStatus.fromCode(alert.getStatus());
            if (newStatus == null) {
                throw new ServiceException("警情状态无效");
            }
            
            // 防止状态回退：一旦警情已提交（received/transferred/converted/closed），不能再回到草稿状态
            AlertStatus currentStatus = AlertStatus.fromCode(existingAlert.getStatus());
            if (currentStatus != null && newStatus == AlertStatus.DRAFT) {
                // 如果当前状态不是草稿，但试图改为草稿，则拒绝
                if (currentStatus != AlertStatus.DRAFT) {
                    throw new ServiceException("警情已提交，不能回退到草稿状态。当前状态：" + currentStatus.getLabel());
                }
            }
        }
        
        // 如果修改了警情编号，检查是否重复
        if (StringUtils.isNotEmpty(alert.getAlertNo()) 
                && !alert.getAlertNo().equals(existingAlert.getAlertNo())) {
            DutyAlert duplicate = getByAlertNo(alert.getAlertNo());
            if (duplicate != null && !duplicate.getId().equals(alert.getId())) {
                throw new ServiceException("警情编号已存在：" + alert.getAlertNo());
            }
        }
        
        String operator = SecurityUtils.getUsername();
        alert.setUpdateBy(operator);
        alert.setUpdateTime(new Date());
        
        return super.updateById(alert);
    }
}