"""
Character management service for FreeExile.
Handles Level 1 character creation from scratch, season binding, and starting home zone assignment.
"""

from __future__ import annotations
import enum
import json
import re
import time
import uuid
from typing import Any, Dict, List, Optional
from dataclasses import dataclass, field

from server.auth.database import DatabaseAccountRepository


class CharacterClass(enum.Enum):
    SWORD_MASTER = "sword_master"        # Kiếm Tu (Nhanh nhẹn, né tránh, kiếm khí)
    FERAL_BERSERKER = "feral_berserker"  # Cuồng Đao (Thể phách, chém lan, hút máu)
    WILD_ARCHER = "wild_archer"          # Man Hoang Xạ Thủ (Tầm xa, bẫy rập, bạo kích)
    BONE_HEXER = "bone_hexer"            # Cốt Thuật Sư (Dị biến tà cốt, nguyền rủa, triệu hồi)


@dataclass(slots=True)
class Character:
    """Core player character entity in FreeExile."""
    character_id: str
    account_id: str
    name: str
    class_type: CharacterClass
    level: int = 1
    season_id: str = "season_01_minh_nguyet"
    experience: int = 0
    current_hp: int = 100
    max_hp: int = 100
    current_mana: int = 50
    max_mana: int = 50
    current_zone_id: str = "zone_boundless_sanctuary"
    pos_x: float = 0.0
    pos_y: float = 10.0
    inventory_json: str = "[]"
    created_at: float = field(default_factory=time.time)


@dataclass(slots=True, frozen=True)
class CharacterCreationResult:
    """Result of character creation."""
    success: bool
    message: str
    character: Optional[Character] = None


class CharacterService:
    """Manages character creation, listing, season binding, and starting location."""

    NAME_REGEX = re.compile(r"^[\w\s\u00C0-\u1EF9]{3,24}$", re.UNICODE)

    def __init__(self, repository: DatabaseAccountRepository) -> None:
        self.repository = repository

    def _row_to_character(self, row: Any) -> Character:
        return Character(
            character_id=row["character_id"],
            account_id=row["account_id"],
            name=row["name"],
            class_type=CharacterClass(row["class_type"]),
            level=row["level"],
            season_id=row["season_id"],
            experience=row["experience"],
            current_hp=row["current_hp"],
            max_hp=row["max_hp"],
            current_mana=row["current_mana"],
            max_mana=row["max_mana"],
            current_zone_id=row["current_zone_id"],
            pos_x=row["pos_x"],
            pos_y=row["pos_y"],
            inventory_json=row["inventory_json"],
            created_at=row["created_at"],
        )

    def create_character(
        self,
        account_id: str,
        name: str,
        class_type: CharacterClass,
        season_id: str = "season_01_minh_nguyet",
    ) -> CharacterCreationResult:
        """Create a new Level 1 character bound to active season and starting map."""
        cleaned_name = name.strip()

        # Validate name
        if not self.NAME_REGEX.match(cleaned_name):
            return CharacterCreationResult(
                success=False,
                message="Character name must be between 3 and 24 characters with valid alphanumeric letters.",
            )

        # Check account exists
        account = self.repository.get_by_id(account_id)
        if not account:
            return CharacterCreationResult(success=False, message="Account does not exist.")

        # Check name uniqueness across entire server
        with self.repository._get_connection() as conn:
            cur = conn.execute("SELECT character_id FROM characters WHERE LOWER(name) = ?", (cleaned_name.lower(),))
            if cur.fetchone():
                return CharacterCreationResult(
                    success=False,
                    message=f"Character name '{cleaned_name}' is already taken. Please choose another.",
                )

        character_id = f"char_{uuid.uuid4().hex[:16]}"
        now = time.time()

        # Starting home location: Sanctuary with only canonical NPCs, zero initial clutter
        starting_zone = "zone_boundless_sanctuary"
        start_x, start_y = 0.0, 10.0

        # Starter novice gear
        starter_inventory = [
            {"item_id": "wpn_novice_bone_blade", "slot": "main_hand", "quantity": 1},
            {"item_id": "armor_coarse_tunic", "slot": "chest", "quantity": 1},
        ]
        inventory_json = json.dumps(starter_inventory)

        with self.repository._get_connection() as conn:
            conn.execute(
                """
                INSERT INTO characters (
                    character_id, account_id, name, class_type, level, season_id,
                    experience, current_hp, max_hp, current_mana, max_mana,
                    current_zone_id, pos_x, pos_y, inventory_json, created_at
                ) VALUES (?, ?, ?, ?, 1, ?, 0, 100, 100, 50, 50, ?, ?, ?, ?, ?)
                """,
                (
                    character_id,
                    account_id,
                    cleaned_name,
                    class_type.value,
                    season_id,
                    starting_zone,
                    start_x,
                    start_y,
                    inventory_json,
                    now,
                ),
            )
            conn.commit()

        character = Character(
            character_id=character_id,
            account_id=account_id,
            name=cleaned_name,
            class_type=class_type,
            level=1,
            season_id=season_id,
            experience=0,
            current_hp=100,
            max_hp=100,
            current_mana=50,
            max_mana=50,
            current_zone_id=starting_zone,
            pos_x=start_x,
            pos_y=start_y,
            inventory_json=inventory_json,
            created_at=now,
        )

        return CharacterCreationResult(
            success=True,
            message="Character created successfully at Level 1.",
            character=character,
        )

    def list_characters(self, account_id: str) -> List[Character]:
        """List all characters belonging to an account."""
        with self.repository._get_connection() as conn:
            cur = conn.execute(
                "SELECT * FROM characters WHERE account_id = ? ORDER BY created_at ASC",
                (account_id,),
            )
            return [self._row_to_character(r) for r in cur.fetchall()]

    def get_character(self, character_id: str) -> Optional[Character]:
        """Fetch character by ID."""
        with self.repository._get_connection() as conn:
            cur = conn.execute("SELECT * FROM characters WHERE character_id = ?", (character_id,))
            row = cur.fetchone()
            if row:
                return self._row_to_character(row)
        return None

    def delete_character(self, character_id: str, account_id: str) -> bool:
        """Delete a character owned by the account."""
        with self.repository._get_connection() as conn:
            cur = conn.execute(
                "DELETE FROM characters WHERE character_id = ? AND account_id = ?",
                (character_id, account_id),
            )
            conn.commit()
            return cur.rowcount > 0
