"""Personality system for role-play profiles."""

from dataclasses import dataclass, field
from enum import Enum
import json
from pathlib import Path
from typing import Dict, List, Optional


class PersonalityTrait(Enum):
    """Personality traits."""

    FRIENDLY = "Friendly"
    PROFESSIONAL = "Professional"
    HUMOROUS = "Humorous"
    SERIOUS = "Serious"
    CREATIVE = "Creative"
    ANALYTICAL = "Analytical"
    EMPATHETIC = "Empathetic"
    DIRECT = "Direct"


@dataclass
class PersonalityProfile:
    """Single personality profile."""

    name: str
    description: str
    traits: List[PersonalityTrait]
    speaking_style: str
    example_responses: List[str] = field(default_factory=list)
    custom_instructions: str = ""

    def to_system_prompt(self) -> str:
        """Build plain-text system prompt."""

        traits_text = ", ".join([t.value for t in self.traits]) if self.traits else "Friendly"
        lines = [
            "Role Setting",
            f"You are {self.name}. {self.description}",
            f"Traits: {traits_text}",
            f"Speaking style: {self.speaking_style}",
            "Output rule: plain text only. Do not use Markdown syntax.",
        ]

        if self.example_responses:
            lines.append("Reference responses:")
            for idx, example in enumerate(self.example_responses, 1):
                lines.append(f"{idx}. {example}")

        if self.custom_instructions:
            lines.append(f"Additional instructions: {self.custom_instructions}")

        return "\n".join(lines)


class PersonalitySystem:
    """Personality management and persistence."""

    def __init__(self, config_path: Optional[Path] = None):
        self.config_path = config_path or Path("config/personalities.json")
        self.personalities: Dict[str, PersonalityProfile] = {}
        self.current_personality: Optional[PersonalityProfile] = None
        self._load_personalities()

    def _dict_to_profile(self, config: Dict) -> PersonalityProfile:
        trait_names = config.get("traits", [])
        traits: List[PersonalityTrait] = []

        for trait_name in trait_names:
            if trait_name in PersonalityTrait.__members__:
                traits.append(PersonalityTrait[trait_name])

        if not traits:
            traits = [PersonalityTrait.FRIENDLY]

        return PersonalityProfile(
            name=str(config.get("name", "Assistant")),
            description=str(config.get("description", "")),
            traits=traits,
            speaking_style=str(config.get("speaking_style", "Natural and concise")),
            example_responses=list(config.get("example_responses", [])),
            custom_instructions=str(config.get("custom_instructions", "")),
        )

    def _load_personalities(self):
        """Load personality config from disk or create defaults."""

        if self.config_path.exists():
            with open(self.config_path, "r", encoding="utf-8") as f:
                data = json.load(f)
                for key, config in data.items():
                    self.personalities[key] = self._dict_to_profile(config)

            if "default" in self.personalities:
                self.current_personality = self.personalities["default"]
            elif self.personalities:
                first_key = next(iter(self.personalities.keys()))
                self.current_personality = self.personalities[first_key]
            return

        self._create_default_personalities()

    def _create_default_personalities(self):
        """Create and persist built-in default profiles."""

        default = PersonalityProfile(
            name="Assistant",
            description="A friendly and practical AI assistant.",
            traits=[
                PersonalityTrait.FRIENDLY,
                PersonalityTrait.PROFESSIONAL,
                PersonalityTrait.EMPATHETIC,
            ],
            speaking_style="Warm, clear, and actionable.",
            example_responses=[
                "I understand. Let's solve this step by step.",
                "Here is the result first, then the key details.",
            ],
        )

        tech_expert = PersonalityProfile(
            name="Tech Expert",
            description="A senior engineer focused on correctness and maintainability.",
            traits=[
                PersonalityTrait.PROFESSIONAL,
                PersonalityTrait.ANALYTICAL,
                PersonalityTrait.DIRECT,
            ],
            speaking_style="Direct, structured, and implementation-oriented.",
        )

        creative = PersonalityProfile(
            name="Creative Partner",
            description="A collaborative creative role-play partner.",
            traits=[
                PersonalityTrait.CREATIVE,
                PersonalityTrait.HUMOROUS,
                PersonalityTrait.FRIENDLY,
            ],
            speaking_style="Lively, imaginative, and expressive.",
        )

        self.personalities = {
            "default": default,
            "tech_expert": tech_expert,
            "creative": creative,
        }
        self.current_personality = default
        self._save_personalities()

    def _save_personalities(self):
        """Persist personalities to disk."""

        self.config_path.parent.mkdir(parents=True, exist_ok=True)
        data = {}

        for key, profile in self.personalities.items():
            data[key] = {
                "name": profile.name,
                "description": profile.description,
                "traits": [trait.name for trait in profile.traits],
                "speaking_style": profile.speaking_style,
                "example_responses": profile.example_responses,
                "custom_instructions": profile.custom_instructions,
            }

        with open(self.config_path, "w", encoding="utf-8") as f:
            json.dump(data, f, ensure_ascii=False, indent=2)

    def set_personality(self, key: str) -> bool:
        """Switch active personality by key."""

        if key not in self.personalities:
            return False

        self.current_personality = self.personalities[key]
        return True

    def get_system_prompt(self) -> str:
        """Get current personality prompt."""

        if self.current_personality:
            return self.current_personality.to_system_prompt()
        return ""

    def add_personality(self, key: str, profile: PersonalityProfile) -> bool:
        """Add a new personality profile."""

        key = key.strip()
        if not key:
            return False

        self.personalities[key] = profile
        if not self.current_personality:
            self.current_personality = profile
        self._save_personalities()
        return True

    def remove_personality(self, key: str) -> bool:
        """Remove a personality profile."""

        if key == "default":
            return False

        if key not in self.personalities:
            return False

        removed_profile = self.personalities[key]
        del self.personalities[key]

        if self.current_personality == removed_profile:
            if "default" in self.personalities:
                self.current_personality = self.personalities["default"]
            elif self.personalities:
                first_key = next(iter(self.personalities.keys()))
                self.current_personality = self.personalities[first_key]
            else:
                self.current_personality = None

        self._save_personalities()
        return True

    def list_personalities(self) -> List[str]:
        """List all personality keys."""

        return sorted(self.personalities.keys())

    def get_personality(self, key: str) -> Optional[PersonalityProfile]:
        """Get personality by key."""

        return self.personalities.get(key)
