"""Convert V2 strategic briefs and script inputs into V2 candidates."""

from __future__ import annotations

from dataclasses import dataclass
import re
import unicodedata
from typing import Any

from autoshorts.strategy.spine_v2 import (
    ContentBriefV2,
    RenderBackendCandidate,
    VideoCandidateV2,
    _platform_id,
)


@dataclass(frozen=True)
class ScriptInputV2:
    title: str
    hook: str
    first_frame: str
    visible_fail: str
    mechanism: str
    fix: str
    before_after: str
    takeaway: str
    save_reason: str
    share_reason: str
    follow_reason: str
    human_texture_note: str
    claims: tuple[Any, ...]
    platform_fit: dict[str, str]
    risks: tuple[str, ...]
    visual_structure: str
    anti_example: str = ""
    plausible_nonsense_example: str = ""
    concrete_scene: str = ""
    linkedin_title: str = ""
    linkedin_caption: str = ""
    render_backend_candidate: RenderBackendCandidate | str = RenderBackendCandidate.PYTHON_MOTION
    series_id_override: str | None = None
    human_texture: object | None = None
    saturation_risk: object | None = None


def _slugify(text: str, *, max_words: int = 8) -> str:
    normalized = unicodedata.normalize("NFKD", text or "")
    ascii_text = normalized.encode("ascii", "ignore").decode("ascii")
    tokens = re.findall(r"[a-z0-9]+", ascii_text.casefold())
    return "-".join(tokens[:max_words]) or "untitled"


def convert_to_candidate_v2(brief: ContentBriefV2, script: ScriptInputV2, *, version: str = "v2.0.0") -> VideoCandidateV2:
    series_id = script.series_id_override if script.series_id_override is not None else brief.series_id
    platforms = tuple(_platform_id(platform) for platform in brief.platforms)
    return VideoCandidateV2(
        candidate_id=f"{series_id.replace('_', '-')}-{_slugify(script.title)}-{brief.target_duration_seconds}s",
        version=version,
        title=script.title,
        series_id=series_id,
        platforms=platforms,
        duration_seconds=brief.target_duration_seconds,
        audience_need=brief.audience_need,
        job_to_be_done=brief.job_to_be_done,
        viewer_identity=brief.viewer_identity,
        emotion_before=brief.emotion_before,
        emotion_after=brief.emotion_after,
        hook=script.hook,
        first_frame=script.first_frame,
        visible_fail=script.visible_fail,
        mechanism=script.mechanism,
        fix=script.fix,
        before_after=script.before_after,
        takeaway=script.takeaway,
        save_reason=script.save_reason,
        share_reason=script.share_reason,
        follow_reason=script.follow_reason,
        search_intent_phrase=brief.search_intent_phrase,
        saturation_risk=script.saturation_risk if script.saturation_risk is not None else brief.saturation_risk,
        human_texture=script.human_texture if script.human_texture is not None else brief.human_texture,
        claim_risk=brief.claim_risk,
        claims=script.claims,
        ai_disclosure_required=brief.ai_disclosure_required,
        experiment_hypothesis=brief.experiment_hypothesis,
        expected_winning_metric=brief.experiment_hypothesis.expected_winning_metric,
        platform_fit={_platform_id(k): v for k, v in script.platform_fit.items()},
        risks=script.risks,
        visual_structure=script.visual_structure,
        anti_example=script.anti_example,
        plausible_nonsense_example=script.plausible_nonsense_example,
        concrete_scene=script.concrete_scene,
        human_texture_note=script.human_texture_note,
        linkedin_title=script.linkedin_title,
        linkedin_caption=script.linkedin_caption,
        render_backend_candidate=script.render_backend_candidate,
    )
