"""
FreeExile Quest & Milestone Data Types and Enums.
Strictly typed dataclasses and domain enums for quest models.
"""

from __future__ import annotations
from enum import Enum
from typing import Dict, List, Optional
from dataclasses import dataclass, field


class QuestType(Enum):
    NORMAL = "NORMAL"          # Main and Side quests
    HIDDEN = "HIDDEN"          # Cryptic quests discovered through secret triggers
    HIGH_TIER = "HIGH_TIER"    # Epic/Astral endgame trials and keystones


class QuestStatus(Enum):
    LOCKED = "LOCKED"          # Prerequisites not yet met
    AVAILABLE = "AVAILABLE"    # Can be accepted
    IN_PROGRESS = "IN_PROGRESS"# Currently active
    COMPLETED = "COMPLETED"    # All objectives fulfilled, awaiting reward claim
    CLAIMED = "CLAIMED"        # Reward claimed, finalized
    FAILED = "FAILED"          # Expired or failed condition


class ObjectiveType(Enum):
    KILL_MONSTER = "KILL_MONSTER"
    COLLECT_ITEM = "COLLECT_ITEM"
    CRAFT_ITEM = "CRAFT_ITEM"
    DISCOVER_LOCATION = "DISCOVER_LOCATION"
    ACTIVATE_MERIDIAN = "ACTIVATE_MERIDIAN"
    PERFORM_ACTION = "PERFORM_ACTION"
    TALK_NPC = "TALK_NPC"
    DELIVER_TO_NPC = "DELIVER_TO_NPC"
    EXPLORE_MAP_ROOMS = "EXPLORE_MAP_ROOMS"
    CLEAR_FOG_PERCENT = "CLEAR_FOG_PERCENT"
    BREACH_BOSS_GATE = "BREACH_BOSS_GATE"
    DESTROY_OBSTACLES = "DESTROY_OBSTACLES"


class HiddenTriggerType(Enum):
    EVASION_NEAR_DEATH = "EVASION_NEAR_DEATH"
    SECRET_ALTAR_INTERACTION = "SECRET_ALTAR_INTERACTION"
    FIVE_ELEMENTS_STREAK = "FIVE_ELEMENTS_STREAK"
    RELIC_OFFERING = "RELIC_OFFERING"
    NPC_DIALOGUE_CHOICE = "NPC_DIALOGUE_CHOICE"
    NPC_GIFT_OFFERING = "NPC_GIFT_OFFERING"


@dataclass(slots=True, frozen=True)
class RewardItem:
    item_id: str
    name: str
    quantity: int


@dataclass(slots=True, frozen=True)
class QuestReward:
    exp: int
    spirit_stones: List[RewardItem] = field(default_factory=list)
    meridian_points: int = 0
    title: Optional[str] = None


@dataclass(slots=True, frozen=True)
class ObjectiveState:
    objective_id: str
    description: str
    obj_type: ObjectiveType
    target_id: str
    target_count: int
    current_count: int = 0
    is_completed: bool = False

    def with_increment(self, amount: int) -> ObjectiveState:
        new_count = min(self.target_count, self.current_count + amount)
        return ObjectiveState(
            objective_id=self.objective_id,
            description=self.description,
            obj_type=self.obj_type,
            target_id=self.target_id,
            target_count=self.target_count,
            current_count=new_count,
            is_completed=(new_count >= self.target_count),
        )

    def with_gauge_value(self, value: int) -> ObjectiveState:
        new_count = min(self.target_count, max(self.current_count, value))
        return ObjectiveState(
            objective_id=self.objective_id,
            description=self.description,
            obj_type=self.obj_type,
            target_id=self.target_id,
            target_count=self.target_count,
            current_count=new_count,
            is_completed=(new_count >= self.target_count),
        )


@dataclass(slots=True, frozen=True)
class HiddenTrigger:
    trigger_type: HiddenTriggerType
    required_zone: Optional[str] = None
    required_hp_percent: Optional[float] = None
    required_item_id: Optional[str] = None
    description: str = ""


@dataclass(slots=True, frozen=True)
class QuestDefinition:
    quest_id: str
    title: str
    description: str
    quest_type: QuestType
    required_level: int
    prerequisite_quest_ids: List[str]
    objectives: List[ObjectiveState]
    reward: QuestReward
    hidden_trigger: Optional[HiddenTrigger] = None
    act_id: Optional[str] = None
    story_chapter: Optional[int] = None


@dataclass(slots=True)
class PlayerQuestProgress:
    player_id: str
    quest_id: str
    status: QuestStatus
    objectives: Dict[str, ObjectiveState]
    started_at: float
    completed_at: Optional[float] = None
    claimed_at: Optional[float] = None


@dataclass(slots=True, frozen=True)
class MilestoneTier:
    milestone_id: str
    title: str
    description: str
    required_total_completed: int
    required_hidden_completed: int
    required_high_tier_completed: int
    reward: QuestReward
