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

import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import com.aegis.common.exception.ServiceException;
import com.aegis.common.utils.SecurityUtils;
import com.aegis.common.utils.StringUtils;
import com.aegis.emergency.dispatch.constant.DispatchTaskStepStatus;
import com.aegis.emergency.dispatch.domain.DispatchTaskStep;
import com.aegis.emergency.dispatch.mapper.DispatchTaskStepMapper;
import com.aegis.emergency.dispatch.service.IDispatchTaskStepService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 调度任务行动项 Service 实现
 *
 * @author aegis
 */
@Service
public class DispatchTaskStepServiceImpl extends ServiceImpl<DispatchTaskStepMapper, DispatchTaskStep>
        implements IDispatchTaskStepService {

    @Override
    public List<DispatchTaskStep> listByTaskId(Long taskId) {
        if (taskId == null) {
            return Collections.emptyList();
        }
        return this.list(new LambdaQueryWrapper<DispatchTaskStep>()
            .eq(DispatchTaskStep::getTaskId, taskId)
            .eq(DispatchTaskStep::getDelFlag, "0")
            .orderByAsc(DispatchTaskStep::getStepOrder)
            .orderByAsc(DispatchTaskStep::getCreateTime));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addSteps(Long taskId, List<DispatchTaskStep> steps) {
        if (taskId == null) {
            throw new ServiceException("任务ID不能为空");
        }
        if (CollectionUtils.isEmpty(steps)) {
            return;
        }

        String operator = SecurityUtils.getUsername();
        Date now = new Date();

        List<DispatchTaskStep> payload = steps.stream()
            .filter(step -> step != null)
            .peek(step -> {
                step.setTaskId(taskId);
                if (step.getStepOrder() == null) {
                    step.setStepOrder(0);
                }
                if (StringUtils.isEmpty(step.getStatus())) {
                    step.setStatus(DispatchTaskStepStatus.PENDING.getCode());
                }
                step.setDelFlag("0");
                step.setCreateBy(operator);
                step.setCreateTime(now);
                step.setUpdateBy(operator);
                step.setUpdateTime(now);
            })
            .collect(Collectors.toList());

        if (payload.isEmpty()) {
            return;
        }

        this.saveBatch(payload);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void reorderSteps(Long taskId, List<Long> orderedStepIds) {
        if (taskId == null) {
            throw new ServiceException("任务ID不能为空");
        }
        if (CollectionUtils.isEmpty(orderedStepIds)) {
            return;
        }
        List<DispatchTaskStep> steps = this.list(new LambdaQueryWrapper<DispatchTaskStep>()
            .eq(DispatchTaskStep::getTaskId, taskId)
            .eq(DispatchTaskStep::getDelFlag, "0"));
        if (steps.isEmpty()) {
            return;
        }

        // 验证传入 ID 是否属于该任务
        List<Long> existingIds = steps.stream()
            .map(DispatchTaskStep::getId)
            .collect(Collectors.toList());
        for (Long id : orderedStepIds) {
            if (!existingIds.contains(id)) {
                throw new ServiceException("行动项不属于该任务: " + id);
            }
        }

        String operator = SecurityUtils.getUsername();
        Date now = new Date();
        for (int i = 0; i < orderedStepIds.size(); i++) {
            Long stepId = orderedStepIds.get(i);
            DispatchTaskStep step = steps.stream()
                .filter(s -> s.getId().equals(stepId))
                .findFirst()
                .orElse(null);
            if (step != null) {
                step.setStepOrder(i + 1);
                step.setUpdateBy(operator);
                step.setUpdateTime(now);
            }
        }
        this.updateBatchById(steps);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean startStep(Long taskId, Long stepId) {
        DispatchTaskStep step = validateStep(taskId, stepId);
        if (!DispatchTaskStepStatus.PENDING.getCode().equals(step.getStatus())) {
            throw new ServiceException("只有待执行的行动项才能开始");
        }
        return updateStepStatus(step, DispatchTaskStepStatus.IN_PROGRESS.getCode(), null);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean completeStep(Long taskId, Long stepId, String remark) {
        DispatchTaskStep step = validateStep(taskId, stepId);
        if (!DispatchTaskStepStatus.IN_PROGRESS.getCode().equals(step.getStatus())
            && !DispatchTaskStepStatus.PENDING.getCode().equals(step.getStatus())) {
            throw new ServiceException("只有待执行或执行中的行动项才能完成");
        }
        return updateStepStatus(step, DispatchTaskStepStatus.COMPLETED.getCode(), remark);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean failStep(Long taskId, Long stepId, String reason) {
        DispatchTaskStep step = validateStep(taskId, stepId);
        if (DispatchTaskStepStatus.COMPLETED.getCode().equals(step.getStatus())) {
            throw new ServiceException("已完成的行动项不可标记失败");
        }
        return updateStepStatus(step, DispatchTaskStepStatus.FAILED.getCode(), reason);
    }

    private DispatchTaskStep validateStep(Long taskId, Long stepId) {
        if (taskId == null || stepId == null) {
            throw new ServiceException("任务ID和行动项ID不能为空");
        }
        DispatchTaskStep step = this.getById(stepId);
        if (step == null || !"0".equals(step.getDelFlag())) {
            throw new ServiceException("行动项不存在");
        }
        if (!taskId.equals(step.getTaskId())) {
            throw new ServiceException("行动项不属于该任务");
        }
        return step;
    }

    private boolean updateStepStatus(DispatchTaskStep step, String newStatus, String remark) {
        step.setStatus(newStatus);
        if (StringUtils.isNotBlank(remark)) {
            step.setRemark(remark);
        }
        String operator = SecurityUtils.getUsername();
        step.setUpdateBy(operator);
        step.setUpdateTime(new Date());
        return this.updateById(step);
    }
}