"""
AutoPOE2 - Ange Currency Exchange Routine (Doc 43 P2-2)
=======================================================
Tự động tiếp cận NPC Ange tại Hideout/Town để đổi Exalted Orb lấy Orb of Alchemy
khi túi đồ cạn kiệt currency craft bản đồ.

Tuân thủ bất biến kiến trúc:
- INV-ANGE-EXCHANGE-01 (Reserve Interlock & Anti-Depletion):
  * Ngưỡng sàn bảo vệ: Tuyệt đối CẤM tiêu Exalted Orb nếu tổng số <= min_exalted_reserve (mặc định 5).
  * Định mức cứng: Mỗi lần đổi tối đa duy nhất 1 Exalted Orb (batch_size = 1).
  * Khóa ngắt mạch (Circuit Breaker): 2 lần đổi liên tiếp không tăng Alchemy -> Khóa 10 phút.
  * Giới hạn tần suất: Cooldown tối thiểu 60,000ms giữa 2 chu kỳ đổi.
  * Tỷ giá sàn: Chỉ chấp nhận giao dịch nếu tỷ giá >= min_alchemy_per_exalt (mặc định 10).
"""

import time
from dataclasses import dataclass
from enum import Enum
from typing import Dict, Optional, Tuple


class ExchangeStatus(Enum):
    SUCCESS = "SUCCESS"
    REJECTED_LOW_RESERVE = "REJECTED_LOW_RESERVE"
    REJECTED_COOLDOWN = "REJECTED_COOLDOWN"
    REJECTED_LOW_RATE = "REJECTED_LOW_RATE"
    CIRCUIT_BREAKER_ACTIVE = "CIRCUIT_BREAKER_ACTIVE"
    UNSAFE_AREA = "UNSAFE_AREA"


@dataclass
class ExchangeDecision:
    allowed: bool
    status: ExchangeStatus
    exalted_to_spend: int
    reason: str


@dataclass
class AngeExchangeConfig:
    min_exalted_reserve: int = 5
    batch_size: int = 1
    cooldown_ms: int = 60000          # 60s
    circuit_breaker_timeout_ms: int = 600000  # 10 phút
    min_alchemy_per_exalt: int = 10
    max_consecutive_failures: int = 2


class AngeCurrencyExchangeManager:
    """
    Bộ điều phối giao dịch đổi tiền tại NPC Ange có tầng bảo vệ tài nguyên an toàn.
    """

    def __init__(self, config: Optional[AngeExchangeConfig] = None):
        self.config = config or AngeExchangeConfig()
        self.last_exchange_time_ms: int = 0
        self.consecutive_failures: int = 0
        self.circuit_breaker_until_ms: int = 0
        self.total_exchanged_exalts: int = 0
        self.total_received_alchemies: int = 0

    def evaluate_exchange(
        self,
        current_exalted_count: int,
        alchemy_rate_per_exalt: int,
        is_in_safe_area: bool = True,
        now_ms: Optional[int] = None,
    ) -> ExchangeDecision:
        """
        Đánh giá tiền điều kiện trước khi phát lệnh tương tác đổi tiền.
        """
        if now_ms is None:
            now_ms = int(time.time() * 1000)

        # 1. Kiểm tra an toàn khu vực
        if not is_in_safe_area:
            return ExchangeDecision(
                allowed=False,
                status=ExchangeStatus.UNSAFE_AREA,
                exalted_to_spend=0,
                reason="Vi phạm an toàn: Không ở trong Hideout hoặc Town.",
            )

        # 2. Kiểm tra Circuit Breaker
        if now_ms < self.circuit_breaker_until_ms:
            remaining_sec = (self.circuit_breaker_until_ms - now_ms) // 1000
            return ExchangeDecision(
                allowed=False,
                status=ExchangeStatus.CIRCUIT_BREAKER_ACTIVE,
                exalted_to_spend=0,
                reason=f"Circuit Breaker đang kích hoạt. Tạm dừng đổi tiền trong {remaining_sec}s.",
            )

        # 3. Kiểm tra bất biến INV-ANGE-EXCHANGE-01: Ngưỡng sàn dự trữ sinh tồn
        if current_exalted_count <= self.config.min_exalted_reserve:
            return ExchangeDecision(
                allowed=False,
                status=ExchangeStatus.REJECTED_LOW_RESERVE,
                exalted_to_spend=0,
                reason=(
                    f"Vi phạm INV-ANGE-EXCHANGE-01: Số Exalted Orb ({current_exalted_count}) "
                    f"<= ngưỡng sàn an toàn ({self.config.min_exalted_reserve}). CẤM TIÊU DỰ TRỮ!"
                ),
            )

        # 4. Kiểm tra Cooldown tần suất (60s)
        if (now_ms - self.last_exchange_time_ms) < self.config.cooldown_ms:
            wait_ms = self.config.cooldown_ms - (now_ms - self.last_exchange_time_ms)
            return ExchangeDecision(
                allowed=False,
                status=ExchangeStatus.REJECTED_COOLDOWN,
                exalted_to_spend=0,
                reason=f"Đang trong thời gian giãn cách đổi tiền (chờ thêm {wait_ms}ms).",
            )

        # 5. Kiểm tra tỷ giá quy đổi tối thiểu
        if alchemy_rate_per_exalt < self.config.min_alchemy_per_exalt:
            return ExchangeDecision(
                allowed=False,
                status=ExchangeStatus.REJECTED_LOW_RATE,
                exalted_to_spend=0,
                reason=(
                    f"Tỷ giá đổi quá thấp ({alchemy_rate_per_exalt} Alchemy/Exalt < "
                    f"ngưỡng sàn {self.config.min_alchemy_per_exalt}). Hủy giao dịch."
                ),
            )

        # Đủ điều kiện: Cho phép đổi ĐÚNG 1 Exalted Orb
        return ExchangeDecision(
            allowed=True,
            status=ExchangeStatus.SUCCESS,
            exalted_to_spend=self.config.batch_size,
            reason="Thỏa mãn toàn bộ bất biến an toàn. Cho phép đổi 1 Exalted Orb.",
        )

    def record_exchange_result(
        self,
        success: bool,
        received_alchemy: int = 0,
        now_ms: Optional[int] = None,
    ):
        """
        Ghi nhận kết quả giao dịch để cập nhật trạng thái Cooldown hoặc Circuit Breaker.
        """
        if now_ms is None:
            now_ms = int(time.time() * 1000)

        if success and received_alchemy > 0:
            self.consecutive_failures = 0
            self.last_exchange_time_ms = now_ms
            self.total_exchanged_exalts += self.config.batch_size
            self.total_received_alchemies += received_alchemy
        else:
            self.consecutive_failures += 1
            if self.consecutive_failures >= self.config.max_consecutive_failures:
                # Kích hoạt Circuit Breaker 10 phút
                self.circuit_breaker_until_ms = now_ms + self.config.circuit_breaker_timeout_ms
