package com.erp.order.statemachine;

import com.erp.order.entity.Order;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.*;

/**
 * 订单状态机
 *
 * 状态流转图:
 *
 *   [订单创建]
 *      |
 *      v
 *   pending (待处理/待审核)
 *      |
 *      | 审核通过
 *      v
 *   auditing (审核中/待发货)
 *      |
 *      | 发货
 *      v
 *   shipped (已发货)
 *      |
 *      | 确认收货/完成
 *      v
 *   completed (已完成)
 *
 *   取消路径:
 *   pending --> cancelled (取消/驳回)
 *   auditing --> cancelled (取消/驳回)
 *
 *   状态维度:
 *   - order_status: 订单主状态 (pending/auditing/shipped/completed/cancelled)
 *   - audit_status: 审核状态 (pending/approved/rejected)
 *   - delivery_status: 发货状态 (pending/delivered)
 */
@Slf4j
@Component
public class OrderStateMachine {

    /** 订单状态常量 */
    public static final String STATUS_PENDING = "pending";
    public static final String STATUS_AUDITING = "auditing";
    public static final String STATUS_SHIPPED = "shipped";
    public static final String STATUS_COMPLETED = "completed";
    public static final String STATUS_CANCELLED = "cancelled";

    /** 审核状态常量 */
    public static final String AUDIT_PENDING = "pending";
    public static final String AUDIT_APPROVED = "approved";
    public static final String AUDIT_REJECTED = "rejected";

    /** 发货状态常量 */
    public static final String DELIVERY_PENDING = "pending";
    public static final String DELIVERY_DELIVERED = "delivered";

    /** 允许的状态转换 */
    private static final Map<String, Set<String>> ALLOWED_TRANSITIONS = new LinkedHashMap<>();

    static {
        // pending 可以转为 auditing (审核通过) 或 cancelled (取消/驳回)
        ALLOWED_TRANSITIONS.put(STATUS_PENDING,
                new HashSet<>(Arrays.asList(STATUS_AUDITING, STATUS_CANCELLED)));

        // auditing 可以转为 shipped (发货) 或 cancelled (取消)
        ALLOWED_TRANSITIONS.put(STATUS_AUDITING,
                new HashSet<>(Arrays.asList(STATUS_SHIPPED, STATUS_CANCELLED)));

        // shipped 可以转为 completed (完成) 或 cancelled (取消/退款)
        ALLOWED_TRANSITIONS.put(STATUS_SHIPPED,
                new HashSet<>(Arrays.asList(STATUS_COMPLETED, STATUS_CANCELLED)));

        // completed 是终态
        ALLOWED_TRANSITIONS.put(STATUS_COMPLETED, new HashSet<>());

        // cancelled 是终态
        ALLOWED_TRANSITIONS.put(STATUS_CANCELLED, new HashSet<>());
    }

    /**
     * 验证状态转换是否合法
     */
    public boolean canTransition(String fromStatus, String toStatus) {
        if (fromStatus == null || toStatus == null) {
            return false;
        }
        Set<String> allowed = ALLOWED_TRANSITIONS.get(fromStatus);
        return allowed != null && allowed.contains(toStatus);
    }

    /**
     * 执行状态转换，返回转换后的订单
     */
    public Order transition(Order order, String toStatus, String operator, String comment) {
        String fromStatus = order.getOrderStatus();

        if (!canTransition(fromStatus, toStatus)) {
            throw new com.erp.order.exception.OrderStateException(
                    String.format("订单[%s]状态不允许从[%s]转换到[%s]", order.getShortId(), fromStatus, toStatus));
        }

        log.info("订单状态转换: {} -> {}, 操作人: {}, 订单ID: {}",
                fromStatus, toStatus, operator, order.getShortId());

        order.setOrderStatus(toStatus);

        // 根据目标状态更新审核和发货状态
        switch (toStatus) {
            case STATUS_AUDITING:
                order.setAuditStatus(AUDIT_APPROVED);
                order.setAuditComment(comment);
                break;
            case STATUS_CANCELLED:
                order.setAuditStatus(AUDIT_REJECTED);
                order.setAuditComment(comment != null ? comment : "订单已取消");
                break;
            case STATUS_SHIPPED:
                order.setDeliveryStatus(DELIVERY_DELIVERED);
                break;
            case STATUS_COMPLETED:
                order.setEndTime(java.time.LocalDateTime.now());
                break;
        }

        return order;
    }

    /**
     * 检查是否可以执行审核
     */
    public boolean canAudit(Order order) {
        return STATUS_PENDING.equals(order.getOrderStatus())
                && (order.getAuditStatus() == null || AUDIT_PENDING.equals(order.getAuditStatus()));
    }

    /**
     * 检查是否可以发货
     */
    public boolean canShip(Order order) {
        return STATUS_AUDITING.equals(order.getOrderStatus())
                && AUDIT_APPROVED.equals(order.getAuditStatus())
                && order.getWarehouseId() != null;
    }

    /**
     * 检查是否可以完成
     */
    public boolean canComplete(Order order) {
        return STATUS_SHIPPED.equals(order.getOrderStatus());
    }

    /**
     * 检查是否可以取消
     */
    public boolean canCancel(Order order) {
        return STATUS_PENDING.equals(order.getOrderStatus())
                || STATUS_AUDITING.equals(order.getOrderStatus());
    }

    /**
     * 获取可用的目标状态列表
     */
    public Set<String> getAvailableTransitions(String currentStatus) {
        return ALLOWED_TRANSITIONS.getOrDefault(currentStatus, Collections.emptySet());
    }

    /**
     * 判断是否为终态
     */
    public boolean isFinalState(String status) {
        return STATUS_COMPLETED.equals(status) || STATUS_CANCELLED.equals(status);
    }
}
