package com.zksy.drainage.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zksy.common.exception.ServiceException;
import com.zksy.drainage.domain.DrainageWarning;
import com.zksy.drainage.domain.WarningScopeUser;
import com.zksy.drainage.mapper.DrainageWarningMapper;
import com.zksy.drainage.mapper.WarningScopeUserMapper;
import com.zksy.drainage.service.DrainageWarningService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 排水预警信息 ServiceImpl
 */
@Slf4j
@Service
public class DrainageWarningServiceImpl extends ServiceImpl<DrainageWarningMapper, DrainageWarning>
        implements DrainageWarningService {

    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    private static final DateTimeFormatter WARNING_NO_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");

    @Autowired
    private WarningScopeUserMapper warningScopeUserMapper;

    private static final List<String> CURRENT_STATUSES = Arrays.asList("DRAFT", "PENDING", "PROCESSING", "RELEASED");
    private static final List<String> HISTORY_STATUSES = Arrays.asList("HANDLED", "CLOSED");

    @Override
    public Page<DrainageWarning> findByPage(long pageNum, long pageSize,
                                            Integer warningLevel, String warningType,
                                            String status, String startTime, String endTime) {
        Page<DrainageWarning> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<DrainageWarning> wrapper = buildQueryWrapper(warningLevel, warningType, status, startTime, endTime);
        wrapper.orderByDesc(DrainageWarning::getCreateTime);
        return this.page(page, wrapper);
    }

    @Override
    public Page<DrainageWarning> findCurrentPage(long pageNum, long pageSize,
                                                  Integer warningLevel, String warningType) {
        Page<DrainageWarning> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<DrainageWarning> wrapper = new LambdaQueryWrapper<>();
        // 当前预警：status IN ('DRAFT','PENDING','PROCESSING','RELEASED')
        wrapper.in(DrainageWarning::getStatus, CURRENT_STATUSES);
        // 附加筛选条件
        if (warningLevel != null) {
            wrapper.eq(DrainageWarning::getWarningLevel, warningLevel);
        }
        if (warningType != null && !warningType.isEmpty()) {
            wrapper.eq(DrainageWarning::getWarningType, warningType);
        }
        wrapper.orderByDesc(DrainageWarning::getCreateTime);
        return this.page(page, wrapper);
    }

    @Override
    public Page<DrainageWarning> findHistoryPage(long pageNum, long pageSize,
                                                  Integer warningLevel, String warningType,
                                                  String status, String startTime, String endTime,
                                                  boolean historyOnly, String equipmentName) {
        Page<DrainageWarning> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<DrainageWarning> wrapper = new LambdaQueryWrapper<>();
        // historyOnly=true 时不再自动添加 status IN (HISTORY_STATUSES) 条件
        // 由前端通过 status 参数控制状态过滤，避免数据库 status 值格式不匹配导致查不到数据
        // 附加筛选条件
        if (warningLevel != null) {
            wrapper.eq(DrainageWarning::getWarningLevel, warningLevel);
        }
        if (warningType != null && !warningType.isEmpty()) {
            wrapper.eq(DrainageWarning::getWarningType, warningType);
        }
        if (status != null && !status.isEmpty()) {
            wrapper.eq(DrainageWarning::getStatus, status);
        }
        if (equipmentName != null && !equipmentName.isEmpty()) {
            wrapper.like(DrainageWarning::getEquipmentName, equipmentName);
        }
        if (startTime != null && !startTime.isEmpty()) {
            wrapper.ge(DrainageWarning::getCreateTime, LocalDateTime.parse(startTime, DATE_TIME_FORMATTER));
        }
        if (endTime != null && !endTime.isEmpty()) {
            wrapper.le(DrainageWarning::getCreateTime, LocalDateTime.parse(endTime, DATE_TIME_FORMATTER));
        }
        wrapper.orderByDesc(DrainageWarning::getCreateTime);
        return this.page(page, wrapper);
    }

    @Override
    @Transactional
    public boolean saveWithCheck(DrainageWarning entity) {
        // 自动生成预警编号：WRN + 时间戳
        if (entity.getWarningNo() == null || entity.getWarningNo().isEmpty()) {
            entity.setWarningNo("WRN" + LocalDateTime.now().format(WARNING_NO_FORMATTER));
        }
        // 设置发布时间为当前时间
        entity.setPublishTime(LocalDateTime.now());
        // 默认状态为PENDING（待办）
        if (entity.getStatus() == null || entity.getStatus().isEmpty()) {
            entity.setStatus("PENDING");
        }
        return this.save(entity);
    }

    @Override
    @Transactional
    public boolean updateWithCheck(DrainageWarning entity) {
        String id = entity.getId();
        if (this.getById(id) == null) {
            throw new ServiceException("预警信息不存在，无法修改：" + id);
        }
        return this.updateById(entity);
    }

    @Override
    @Transactional
    public boolean updateStatus(String id, String status, String processor) {
        DrainageWarning existing = this.getById(id);
        if (existing == null) {
            throw new ServiceException("预警信息不存在：" + id);
        }
        DrainageWarning update = new DrainageWarning();
        update.setId(id);
        update.setStatus(status);
        update.setProcessor(processor);
        update.setProcessTime(LocalDateTime.now());
        return this.updateById(update);
    }

    @Override
    @Transactional
    public boolean removeWithCheck(String id) {
        if (this.getById(id) == null) {
            throw new ServiceException("预警信息不存在：" + id);
        }
        return this.removeById(id);
    }

    @Override
    @Transactional
    public void publishWarning(DrainageWarning warning, List<Long> userIds) {
        // 自动生成预警编号
        if (warning.getWarningNo() == null || warning.getWarningNo().isEmpty()) {
            warning.setWarningNo("WRN" + LocalDateTime.now().format(WARNING_NO_FORMATTER));
        }
        warning.setPublishTime(LocalDateTime.now());
        // 默认状态为PENDING（待办）
        warning.setStatus("PENDING");
        this.save(warning);

        // publish_scope=3 指定人员：保存接收人员记录
        if (warning.getPublishScope() != null && warning.getPublishScope() == 3
                && userIds != null && !userIds.isEmpty()) {
            for (Long uid : userIds) {
                WarningScopeUser scopeUser = new WarningScopeUser();
                scopeUser.setWarningId(warning.getId());
                scopeUser.setUserId(uid);
                scopeUser.setApproved(0);
                warningScopeUserMapper.insert(scopeUser);
            }
        }
    }

    @Override
    public Page<DrainageWarning> findVisibleCurrentPage(long pageNum, long pageSize,
                                                         Long userId, Long deptId, boolean isAdmin,
                                                         Integer warningLevel, String warningType,
                                                         String status, boolean currentOnly,
                                                         String equipmentName, String startTime, String endTime) {
        Page<DrainageWarning> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<DrainageWarning> wrapper = new LambdaQueryWrapper<>();

        // 管理员模式：不做任何权限过滤，仅按基本条件查询
        // early_warning 表无 del_flag 字段，无需逻辑删除过滤

        // 状态筛选：status 参数优先，currentOnly=true 时限定当前预警状态
        if (status != null && !status.isEmpty()) {
            wrapper.eq(DrainageWarning::getStatus, status);
        } else if (currentOnly) {
            wrapper.in(DrainageWarning::getStatus, CURRENT_STATUSES);
        }

        // 附加筛选条件
        if (warningLevel != null) {
            wrapper.eq(DrainageWarning::getWarningLevel, warningLevel);
        }
        if (warningType != null && !warningType.isEmpty()) {
            wrapper.eq(DrainageWarning::getWarningType, warningType);
        }
        if (equipmentName != null && !equipmentName.isEmpty()) {
            wrapper.like(DrainageWarning::getEquipmentName, equipmentName);
        }
        if (startTime != null && !startTime.isEmpty()) {
            wrapper.ge(DrainageWarning::getCreateTime, LocalDateTime.parse(startTime, DATE_TIME_FORMATTER));
        }
        if (endTime != null && !endTime.isEmpty()) {
            wrapper.le(DrainageWarning::getCreateTime, LocalDateTime.parse(endTime, DATE_TIME_FORMATTER));
        }

        wrapper.orderByDesc(DrainageWarning::getCreateTime);
        return this.page(page, wrapper);
    }

    @Override
    @Transactional
    public void firstApprove(String warningId, Long userId, String userName) {
        DrainageWarning existing = this.getById(warningId);
        if (existing == null) {
            throw new ServiceException("预警信息不存在：" + warningId);
        }
        if (existing.getStatus() == null || !"PENDING".equals(existing.getStatus())) {
            throw new ServiceException("预警状态非待办，无法处理");
        }

        DrainageWarning update = new DrainageWarning();
        update.setId(warningId);
        update.setStatus("PROCESSING");
        update.setFirstApprover(userId);
        update.setFirstApproverName(userName);
        update.setFirstApproveTime(LocalDateTime.now());
        this.updateById(update);

        // 更新scope user的审批状态
        WarningScopeUser scopeUpdate = new WarningScopeUser();
        scopeUpdate.setApproved(1);
        scopeUpdate.setApproveTime(LocalDateTime.now());
        warningScopeUserMapper.update(scopeUpdate,
                new LambdaQueryWrapper<WarningScopeUser>()
                        .eq(WarningScopeUser::getWarningId, warningId)
                        .eq(WarningScopeUser::getUserId, userId));
    }

    @Override
    @Transactional
    public void finalApprove(String warningId, Long userId, String userName) {
        DrainageWarning existing = this.getById(warningId);
        if (existing == null) {
            throw new ServiceException("预警信息不存在：" + warningId);
        }
        if (existing.getStatus() == null || !"PROCESSING".equals(existing.getStatus())) {
            throw new ServiceException("预警状态非处置中，无法审批");
        }

        DrainageWarning update = new DrainageWarning();
        update.setId(warningId);
        update.setStatus("RELEASED");
        update.setFinalApprover(userId);
        update.setFinalApproverName(userName);
        update.setFinalApproveTime(LocalDateTime.now());
        this.updateById(update);
    }

    @Override
    public List<WarningScopeUser> findScopeUsers(String warningId) {
        return warningScopeUserMapper.selectList(
                new LambdaQueryWrapper<WarningScopeUser>()
                        .eq(WarningScopeUser::getWarningId, warningId));
    }

    /**
     * 构建通用查询条件
     */
    private LambdaQueryWrapper<DrainageWarning> buildQueryWrapper(Integer warningLevel, String warningType,
                                                                   String status, String startTime, String endTime) {
        LambdaQueryWrapper<DrainageWarning> wrapper = new LambdaQueryWrapper<>();
        if (warningLevel != null) {
            wrapper.eq(DrainageWarning::getWarningLevel, warningLevel);
        }
        if (warningType != null && !warningType.isEmpty()) {
            wrapper.eq(DrainageWarning::getWarningType, warningType);
        }
        if (status != null && !status.isEmpty()) {
            wrapper.eq(DrainageWarning::getStatus, status);
        }
        if (startTime != null && !startTime.isEmpty()) {
            wrapper.ge(DrainageWarning::getCreateTime, LocalDateTime.parse(startTime, DATE_TIME_FORMATTER));
        }
        if (endTime != null && !endTime.isEmpty()) {
            wrapper.le(DrainageWarning::getCreateTime, LocalDateTime.parse(endTime, DATE_TIME_FORMATTER));
        }
        return wrapper;
    }
}
