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

import com.aegis.common.exception.ServiceException;
import com.aegis.common.utils.StringUtils;
import com.aegis.emergency.plan.domain.Plan;
import com.aegis.emergency.plan.mapper.PlanMapper;
import com.aegis.emergency.plan.domain.PlanVersion;
import com.aegis.emergency.plan.service.IPlanParticipantService;
import com.aegis.emergency.plan.service.IPlanService;
import com.aegis.emergency.plan.service.IPlanStepResourceService;
import com.aegis.emergency.plan.service.IPlanStepService;
import com.aegis.emergency.plan.service.IPlanUsageService;
import com.aegis.emergency.plan.service.IPlanVersionService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import org.springframework.stereotype.Service;

/**
 * 预案 Service 实现
 */
@Service
public class PlanServiceImpl extends ServiceImpl<PlanMapper, Plan> implements IPlanService {

    private final IPlanParticipantService participantService;
    private final IPlanStepService stepService;
    private final IPlanStepResourceService stepResourceService;
    private final IPlanUsageService usageService;
    private final IPlanVersionService versionService;

    public PlanServiceImpl(IPlanParticipantService participantService,
                           IPlanStepService stepService,
                           IPlanStepResourceService stepResourceService,
                           IPlanUsageService usageService,
                           IPlanVersionService versionService) {
        this.participantService = participantService;
        this.stepService = stepService;
        this.stepResourceService = stepResourceService;
        this.usageService = usageService;
        this.versionService = versionService;
    }

    @Override
    public boolean save(Plan plan) {
        if (plan == null) {
            throw new ServiceException("预案信息不能为空");
        }
        
        // 验证预案编号唯一性（只检查未删除的记录）
        if (StringUtils.isNotBlank(plan.getPlanNo())) {
            LambdaQueryWrapper<Plan> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Plan::getPlanNo, plan.getPlanNo().trim());
            wrapper.eq(Plan::getDelFlag, "0"); // 只检查未删除的记录
            Plan existing = this.getOne(wrapper);
            if (existing != null) {
                throw new ServiceException("预案编号已存在: " + plan.getPlanNo());
            }
        }
        
        if (StringUtils.isBlank(plan.getStatus())) {
            plan.setStatus("draft");
        }
        if (plan.getIsCurrent() == null) {
            plan.setIsCurrent(Boolean.TRUE);
        }
        if (StringUtils.isBlank(plan.getVersion())) {
            plan.setVersion("v1.0");
        }
        plan.setDelFlag("0");
        Date now = new Date();
        plan.setCreateTime(now);
        plan.setUpdateTime(now);
        return super.save(plan);
    }

    @Override
    public boolean updateById(Plan plan) {
        if (plan == null || plan.getId() == null) {
            throw new ServiceException("预案ID不能为空");
        }
        Plan existing = this.getById(plan.getId());
        if (existing == null || "2".equals(existing.getDelFlag())) {
            throw new ServiceException("预案不存在或已删除");
        }
        
        // 如果预案编号被修改，检查新编号是否已存在
        if (StringUtils.isNotBlank(plan.getPlanNo()) && 
            !plan.getPlanNo().trim().equals(existing.getPlanNo())) {
            LambdaQueryWrapper<Plan> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Plan::getPlanNo, plan.getPlanNo().trim());
            wrapper.eq(Plan::getDelFlag, "0"); // 只检查未删除的记录
            wrapper.ne(Plan::getId, plan.getId()); // 排除当前记录
            Plan duplicate = this.getOne(wrapper);
            if (duplicate != null) {
                throw new ServiceException("预案编号已存在: " + plan.getPlanNo());
            }
        }
        
        // 如果编辑已发布的预案，先创建版本快照，然后改为草稿状态
        boolean isEditingPublished = "published".equals(existing.getStatus()) && 
                                    (plan.getStatus() == null || "published".equals(plan.getStatus()));
        if (isEditingPublished) {
            // 创建版本快照（保存当前已发布的状态）
            try {
                createVersionSnapshot(existing.getId(), existing.getVersion(), 
                    "编辑已发布预案，自动创建版本快照", true);
            } catch (Exception e) {
                throw new ServiceException("无法编辑已发布预案：创建版本快照失败 - " + e.getMessage());
            }
            // 将状态改为草稿，使修改后的内容不对用户可见
            existing.setStatus("draft");
        } else {
            // 其他情况，按原有逻辑处理
            boolean shouldCreateVersion = shouldCreateVersion(existing, plan);
            if (shouldCreateVersion) {
                boolean isPublishing = StringUtils.isNotBlank(plan.getStatus()) && 
                                       "published".equals(plan.getStatus()) && 
                                       !"published".equals(existing.getStatus());
                try {
                    createVersionSnapshot(existing.getId(), existing.getVersion(), plan.getChangeLog(), isPublishing);
                } catch (Exception e) {
                    if (isPublishing) {
                        // 发布时版本创建失败，阻止更新
                        throw new ServiceException("无法发布预案：创建版本快照失败 - " + e.getMessage());
                    }
                    // 其他情况，记录日志但不阻止更新
                    System.err.println("创建版本快照失败（非发布操作）: " + e.getMessage());
                }
            }
        }
        
        if (StringUtils.isNotBlank(plan.getPlanName())) {
            existing.setPlanName(plan.getPlanName());
        }
        if (StringUtils.isNotBlank(plan.getPlanType())) {
            existing.setPlanType(plan.getPlanType());
        }
        if (StringUtils.isNotBlank(plan.getEventType())) {
            existing.setEventType(plan.getEventType());
        }
        if (StringUtils.isNotBlank(plan.getEventLevel())) {
            existing.setEventLevel(plan.getEventLevel());
        }
        if (StringUtils.isNotBlank(plan.getDescription())) {
            existing.setDescription(plan.getDescription());
        }
        // 如果正在编辑已发布的预案，状态已经被设置为 draft，不应该再覆盖
        if (StringUtils.isNotBlank(plan.getStatus()) && !isEditingPublished) {
            existing.setStatus(plan.getStatus());
        }
        if (StringUtils.isNotBlank(plan.getVersion())) {
            existing.setVersion(plan.getVersion());
        }
        if (StringUtils.isNotBlank(plan.getChangeLog())) {
            existing.setChangeLog(plan.getChangeLog());
        }
        if (plan.getIsCurrent() != null) {
            existing.setIsCurrent(plan.getIsCurrent());
        }
        if (plan.getPublishTime() != null) {
            existing.setPublishTime(plan.getPublishTime());
        }
        if (plan.getApprovalTime() != null) {
            existing.setApprovalTime(plan.getApprovalTime());
        }
        if (plan.getApproverId() != null) {
            existing.setApproverId(plan.getApproverId());
        }
        existing.setUpdateTime(new Date());
        return super.updateById(existing);
    }

    @Override
    public boolean removeById(Serializable id) {
        if (id == null) {
            throw new ServiceException("预案ID不能为空");
        }
        Long planId = (Long) id;
        Plan plan = this.getById(planId);
        if (plan == null || "2".equals(plan.getDelFlag())) {
            return false;
        }
        // Cascade delete related data
        participantService.removeByPlanId(planId);
        stepResourceService.removeByPlanId(planId);
        stepService.removeByPlanId(planId);
        usageService.removeByPlanId(planId);

        plan.setDelFlag("2");
        plan.setUpdateTime(new Date());
        return super.updateById(plan);
    }

    @Override
    public boolean publishPlan(Long planId) {
        Plan plan = this.getById(planId);
        if (plan == null || "2".equals(plan.getDelFlag())) {
            throw new ServiceException("预案不存在");
        }
        
        // 保存当前版本号用于创建快照
        String versionToSnapshot = plan.getVersion();
        String newVersion = plan.getVersion();
        
        // 如果是重新发布（从草稿状态发布，之前已经发布过），自动递增版本号
        boolean isRepublishing = "draft".equals(plan.getStatus());
        if (isRepublishing) {
            // 查找已发布版本记录中的最新版本号
            List<PlanVersion> publishedVersions = versionService.listByPlanId(planId);
            String latestPublishedVersion = plan.getVersion(); // 默认使用当前版本号
            
            if (publishedVersions != null && !publishedVersions.isEmpty()) {
                // 找到最新的版本号（按版本号排序，取最大的）
                latestPublishedVersion = publishedVersions.stream()
                    .map(PlanVersion::getVersion)
                    .filter(v -> v != null && !v.trim().isEmpty())
                    .max((v1, v2) -> compareVersions(v1, v2))
                    .orElse(plan.getVersion());
            }
            
            // 基于最新已发布版本号递增
            newVersion = incrementVersion(latestPublishedVersion);
            plan.setVersion(newVersion);
        }
        
        // Create version snapshot before publishing (required)
        try {
            createVersionSnapshot(planId, versionToSnapshot, "发布预案", true);
        } catch (Exception e) {
            // 发布时版本创建失败，阻止发布操作
            throw new ServiceException("发布失败：无法创建版本快照 - " + e.getMessage());
        }
        
        plan.setStatus("published");
        plan.setPublishTime(new Date());
        plan.setUpdateTime(new Date());
        return super.updateById(plan);
    }
    
    /**
     * 递增版本号
     * @param currentVersion 当前版本号，例如 "v1.0", "v1.1", "v2.0"
     * @return 递增后的版本号，例如 "v1.0" -> "v1.1", "v1.1" -> "v1.2", "v2.0" -> "v2.1"
     */
    private String incrementVersion(String currentVersion) {
        if (StringUtils.isBlank(currentVersion)) {
            return "v1.0";
        }
        
        // 移除 "v" 前缀
        String versionStr = currentVersion.trim();
        if (versionStr.startsWith("v") || versionStr.startsWith("V")) {
            versionStr = versionStr.substring(1);
        }
        
        // 解析版本号（支持 x.y 格式）
        String[] parts = versionStr.split("\\.");
        if (parts.length >= 2) {
            try {
                int major = Integer.parseInt(parts[0]);
                int minor = Integer.parseInt(parts[1]);
                // 递增小版本号
                minor++;
                return "v" + major + "." + minor;
            } catch (NumberFormatException e) {
                // 如果解析失败，返回默认值
                return "v1.0";
            }
        } else if (parts.length == 1) {
            try {
                int major = Integer.parseInt(parts[0]);
                return "v" + major + ".1";
            } catch (NumberFormatException e) {
                return "v1.0";
            }
        }
        
        return "v1.0";
    }
    
    /**
     * 比较两个版本号
     * @param v1 版本号1
     * @param v2 版本号2
     * @return 负数表示 v1 < v2，正数表示 v1 > v2，0 表示相等
     */
    private int compareVersions(String v1, String v2) {
        if (v1 == null && v2 == null) return 0;
        if (v1 == null) return -1;
        if (v2 == null) return 1;
        
        // 移除 "v" 前缀
        String v1Str = v1.trim().replaceFirst("^[vV]", "");
        String v2Str = v2.trim().replaceFirst("^[vV]", "");
        
        String[] parts1 = v1Str.split("\\.");
        String[] parts2 = v2Str.split("\\.");
        
        try {
            int major1 = parts1.length > 0 ? Integer.parseInt(parts1[0]) : 0;
            int minor1 = parts1.length > 1 ? Integer.parseInt(parts1[1]) : 0;
            int major2 = parts2.length > 0 ? Integer.parseInt(parts2[0]) : 0;
            int minor2 = parts2.length > 1 ? Integer.parseInt(parts2[1]) : 0;
            
            if (major1 != major2) {
                return Integer.compare(major1, major2);
            }
            return Integer.compare(minor1, minor2);
        } catch (NumberFormatException e) {
            return v1.compareTo(v2);
        }
    }
    
    /**
     * 判断是否需要创建版本快照
     */
    private boolean shouldCreateVersion(Plan existing, Plan updated) {
        // 如果版本号改变，创建快照
        if (StringUtils.isNotBlank(updated.getVersion()) && 
            !updated.getVersion().equals(existing.getVersion())) {
            return true;
        }
        // 如果状态改变为已发布，创建快照
        if (StringUtils.isNotBlank(updated.getStatus()) && 
            "published".equals(updated.getStatus()) && 
            !"published".equals(existing.getStatus())) {
            return true;
        }
        // 如果明确提供了变更日志，创建快照
        if (StringUtils.isNotBlank(updated.getChangeLog())) {
            return true;
        }
        // 默认不自动创建版本（避免每次小修改都创建版本）
        return false;
    }
    
    /**
     * 创建版本快照
     * @param planId 预案ID
     * @param version 版本号
     * @param changeLog 变更日志
     * @param required 是否必须成功（true：失败时抛出异常；false：失败时只记录日志）
     * @throws ServiceException 如果 required=true 且创建失败
     */
    private void createVersionSnapshot(Long planId, String version, String changeLog, boolean required) {
        try {
            PlanVersion planVersion = new PlanVersion();
            planVersion.setPlanId(planId);
            planVersion.setVersion(version != null ? version : "v1.0");
            planVersion.setChangeLog(changeLog != null ? changeLog : "自动创建版本快照");
            planVersion.setDelFlag("0");
            versionService.createVersion(planVersion);
        } catch (Exception e) {
            String errorMsg = "创建版本快照失败: " + e.getMessage();
            System.err.println(errorMsg);
            if (required) {
                // 必须成功时，抛出异常
                throw new ServiceException(errorMsg).setDetailMessage(e.getClass().getSimpleName() + ": " + e.getMessage());
            }
            // 非必须时，只记录日志
        }
    }

    @Override
    public List<Plan> listByCondition(Plan condition, Date beginTime, Date endTime) {
        LambdaQueryWrapper<Plan> wrapper = new LambdaQueryWrapper<>();
        if (condition != null) {
            if (StringUtils.isNotBlank(condition.getPlanName())) {
                wrapper.like(Plan::getPlanName, condition.getPlanName().trim());
            }
            if (StringUtils.isNotBlank(condition.getPlanNo())) {
                wrapper.eq(Plan::getPlanNo, condition.getPlanNo().trim());
            }
            if (StringUtils.isNotBlank(condition.getPlanType())) {
                wrapper.eq(Plan::getPlanType, condition.getPlanType());
            }
            if (StringUtils.isNotBlank(condition.getEventType())) {
                wrapper.eq(Plan::getEventType, condition.getEventType());
            }
            if (StringUtils.isNotBlank(condition.getEventLevel())) {
                wrapper.eq(Plan::getEventLevel, condition.getEventLevel());
            }
            if (StringUtils.isNotBlank(condition.getStatus())) {
                wrapper.eq(Plan::getStatus, condition.getStatus());
            }
            if (condition.getIsCurrent() != null) {
                wrapper.eq(Plan::getIsCurrent, condition.getIsCurrent());
            }
        }
        if (beginTime != null) {
            wrapper.ge(Plan::getCreateTime, beginTime);
        }
        if (endTime != null) {
            wrapper.le(Plan::getCreateTime, endTime);
        }
        wrapper.eq(Plan::getDelFlag, "0");
        wrapper.orderByDesc(Plan::getUpdateTime);
        return this.list(wrapper);
    }
}