"""VidPuls Artist – feste Charaktere wie 7ART (Face, Look, Stimme)."""

from __future__ import annotations

import json
from dataclasses import asdict, dataclass
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
CONFIG = ROOT / "data" / "vidpuls-characters.json"


@dataclass
class ArtistCharacter:
    id: str
    name: str
    age: int
    gender: str
    look: str
    outfit: str
    hair: str
    voice_speaker: str
    render_style: str = "3D Pixar CGI animated movie, trickfilm quality"

    def prompt_anchor(self) -> str:
        return (
            f"{self.name}, {self.age} years old, {self.gender}, "
            f"{self.hair}, wearing {self.outfit}, {self.look}"
        )

    def ref_prompt(self, *, facing: str) -> str:
        direction = "facing right toward another person" if facing == "right" else "facing left toward another person"
        return (
            f"{self.render_style}. Character portrait {direction}. "
            f"{self.prompt_anchor()}. "
            "Half body, cozy modern apartment soft background, cinematic lighting, "
            "high detail 3D render, no text, no watermark"
        )


SARAH = ArtistCharacter(
    id="sarah",
    name="Sarah",
    age=26,
    gender="young woman",
    hair="brown wavy shoulder-length hair",
    outfit="coral pink knit sweater",
    look="warm energetic expression, friendly eyes",
    voice_speaker="sarah",
)

LAURA = ArtistCharacter(
    id="laura",
    name="Laura",
    age=25,
    gender="young woman",
    hair="blonde straight hair",
    outfit="teal blouse",
    look="expressive curious expression",
    voice_speaker="laura",
)

CAST: dict[str, ArtistCharacter] = {
    "sarah": SARAH,
    "laura": LAURA,
    "female": SARAH,
    "lisa": SARAH,
}


def characters_root() -> Path:
    try:
        from jam.jampulse_desktop import ai_root

        p = ai_root() / "Characters"
    except ImportError:
        p = Path.home() / "Desktop" / "VidPuls" / "Characters"
    p.mkdir(parents=True, exist_ok=True)
    return p


def get_character(speaker: str) -> ArtistCharacter:
    sp = (speaker or "sarah").strip().lower()
    return CAST.get(sp, SARAH)


def load_cast() -> dict[str, ArtistCharacter]:
    if CONFIG.is_file():
        try:
            data = json.loads(CONFIG.read_text(encoding="utf-8"))
            out: dict[str, ArtistCharacter] = {}
            for row in data.get("characters") or []:
                c = ArtistCharacter(**row)
                out[c.id] = c
                if c.voice_speaker:
                    out[c.voice_speaker] = c
            if out:
                return out
        except (json.JSONDecodeError, OSError, TypeError):
            pass
    return dict(CAST)


def save_default_cast() -> Path:
    CONFIG.parent.mkdir(parents=True, exist_ok=True)
    payload = {"characters": [asdict(SARAH), asdict(LAURA)]}
    CONFIG.write_text(json.dumps(payload, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
    return CONFIG


def ref_path(char_id: str) -> Path:
    return characters_root() / char_id / "ref.png"


def ensure_character_refs(*, force: bool = False) -> dict[str, Path]:
    """Referenz-Portraits für konsistente KI-Generierung (Artist Elements)."""
    from jam.dialogue_scene import _try_openai_image

    save_default_cast()
    cast = load_cast()
    refs: dict[str, Path] = {}
    for cid in ("sarah", "laura"):
        char = cast.get(cid) or CAST[cid]
        dest = ref_path(cid)
        dest.parent.mkdir(parents=True, exist_ok=True)
        facing = "right" if cid == "sarah" else "left"
        if force or not dest.is_file() or dest.stat().st_size < 8000:
            if not _try_openai_image(char.ref_prompt(facing=facing), dest):
                continue
        if dest.is_file():
            refs[cid] = dest
    return refs
