package tech.easyflow.ai.publish;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tech.easyflow.ai.enums.PublishStatus;
import tech.easyflow.approval.entity.ApprovalInstance;
import tech.easyflow.approval.entity.vo.ApprovalActionResult;
import tech.easyflow.approval.entity.vo.ApprovalFlowDetailVo;
import tech.easyflow.approval.entity.vo.ApprovalSubmitRequest;
import tech.easyflow.approval.enums.ApprovalActionType;
import tech.easyflow.approval.service.ApprovalInstanceService;
import tech.easyflow.approval.service.ApprovalMatchService;
import tech.easyflow.approval.service.ApprovalResultHandler;
import tech.easyflow.common.web.exceptions.BusinessException;

import java.math.BigInteger;
import java.util.List;
import java.util.Map;

/**
 * AI 资源生命周期统一状态机实现。
 */
@Service
public class AiResourceLifecycleServiceImpl implements AiResourceLifecycleService, ApprovalResultHandler {

    private static final String SNAPSHOT_KEY = "resourceSnapshot";
    private static final String PREVIOUS_STATUS_KEY = "previousPublishStatus";

    private final List<AiResourceLifecycleHandler> handlers;
    private final ApprovalMatchService approvalMatchService;
    private final ApprovalInstanceService approvalInstanceService;

    public AiResourceLifecycleServiceImpl(List<AiResourceLifecycleHandler> handlers,
                                          ApprovalMatchService approvalMatchService,
                                          ApprovalInstanceService approvalInstanceService) {
        this.handlers = handlers;
        this.approvalMatchService = approvalMatchService;
        this.approvalInstanceService = approvalInstanceService;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ApprovalActionResult submitAction(String resourceType, BigInteger resourceId, String actionType, BigInteger operatorId) {
        AiResourceLifecycleHandler handler = getHandler(resourceType);
        ApprovalSubmitRequest request = handler.buildSubmitRequest(resourceId, actionType, operatorId);
        ApprovalFlowDetailVo flow = approvalMatchService.matchFlowOrNull(request);
        if (flow == null) {
            handler.applyApprovedAction(actionType, resourceId, readResourceSnapshot(request.getSnapshotJson()), operatorId);
            return ApprovalActionResult.direct();
        }
        BigInteger instanceId = approvalInstanceService.submitApproval(request);
        handler.updatePendingState(
                resourceId,
                resolveSubmittedStatus(actionType, resolvePreviousStatus(request.getSnapshotJson())),
                instanceId
        );
        return ApprovalActionResult.required(instanceId);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void handleApproved(ApprovalInstance instance, BigInteger operatorId, String comment) {
        getHandler(instance.getResourceType()).applyApprovedAction(
                instance.getActionType(),
                instance.getResourceId(),
                readResourceSnapshot(instance.getSnapshotJson()),
                operatorId
        );
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void handleRejected(ApprovalInstance instance, BigInteger operatorId, String comment) {
        getHandler(instance.getResourceType()).restoreState(
                instance.getResourceId(),
                resolvePreviousStatus(instance.getSnapshotJson())
        );
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void handleRevoked(ApprovalInstance instance, BigInteger operatorId, String comment) {
        getHandler(instance.getResourceType()).restoreState(
                instance.getResourceId(),
                resolvePreviousStatus(instance.getSnapshotJson())
        );
    }

    private AiResourceLifecycleHandler getHandler(String resourceType) {
        return handlers.stream()
                .filter(item -> item.resourceType().equals(resourceType))
                .findFirst()
                .orElseThrow(() -> new BusinessException("未找到资源生命周期处理器: " + resourceType));
    }

    /**
     * 解析提交动作后的真实持久化状态。
     *
     * @param actionType 动作类型
     * @param previousStatus 提交前真实状态
     * @return 提交后应写入的状态
     */
    private PublishStatus resolveSubmittedStatus(String actionType, PublishStatus previousStatus) {
        if (ApprovalActionType.PUBLISH.getCode().equals(actionType) && previousStatus == PublishStatus.PUBLISHED) {
            return PublishStatus.PUBLISHED;
        }
        if (ApprovalActionType.DELETE.getCode().equals(actionType)) {
            return PublishStatus.DELETE_PENDING;
        }
        if (ApprovalActionType.OFFLINE.getCode().equals(actionType)) {
            return PublishStatus.OFFLINE_PENDING;
        }
        return PublishStatus.PUBLISH_PENDING;
    }

    /**
     * 从审批快照解析提交前真实状态。
     *
     * @param snapshotJson 审批冻结快照
     * @return 提交前真实状态
     */
    private PublishStatus resolvePreviousStatus(Map<String, Object> snapshotJson) {
        Object status = snapshotJson == null ? null : snapshotJson.get(PREVIOUS_STATUS_KEY);
        if (status instanceof String value && !value.isBlank()) {
            return PublishStatus.from(value);
        }
        return PublishStatus.DRAFT;
    }

    /**
     * 从审批快照中提取冻结资源内容。
     *
     * @param snapshotJson 审批冻结快照
     * @return 冻结资源内容
     */
    @SuppressWarnings("unchecked")
    private Map<String, Object> readResourceSnapshot(Map<String, Object> snapshotJson) {
        Object snapshot = snapshotJson == null ? null : snapshotJson.get(SNAPSHOT_KEY);
        if (!(snapshot instanceof Map<?, ?> map)) {
            throw new BusinessException("审批快照缺少资源内容");
        }
        return (Map<String, Object>) map;
    }
}
