"""Deterministic voiceover finalizer for curated AutoShortsBot ideas."""

from __future__ import annotations

import re
from pathlib import Path
from typing import Any

from autoshorts.script_drafts import _slug

TOP3_CUSTOM_VOICEOVERS = {
    "ai-004": """Stop asking AI to think for you. Ask it to argue with you. Most people use AI like a vending machine: type a question, get a confident answer, move on. That is the weakest use case. Try this instead: paste your idea and ask, what assumptions am I making? What is the weakest part? What would a smart critic disagree with? Now AI is not replacing your thinking. It is putting resistance against lazy thinking. You still decide. You still own the consequence. But you arrive sharper, because the first version had to survive a fight. Comment CRITIC if you want the exact prompt.""",
    "ai-005": """If your brain has 47 tabs open, paste the mess into this four-box prompt. Do not ask AI to motivate you. Ask it to sort the noise. First, dump everything: tasks, worries, random reminders, half-decisions, all of it. Then ask AI: split this into four boxes. Box one: tasks I can actually do. Box two: worries I cannot solve right now. Box three: decisions I need to make. Box four: later, not today. Then ask one final question: what is the next action that takes less than two minutes? That is the whole trick. You are not looking for a perfect life plan. You are looking for one clean handle on the chaos. When the output appears, do only the two-minute action first. If it still feels too big, shrink it again. Momentum beats clarity. Comment RESET if you want me to turn this into a copy-paste template.""",
    "attention-002": """The algorithm does not need you happy. It needs you to stay. That does not mean every app is evil. It means the incentives are not the same as yours. You want focus, sleep, actual progress, maybe a quiet brain for once. The feed wants one more swipe. So stop fighting a machine with vibes. Change the design. First, turn your phone to greyscale when you need deep work. Second, remove your worst app from the home screen. Do not delete it if that feels dramatic. Just make it less automatic. Third, before you open a feed, set a leaving cue: one search, three videos, or five minutes. If there is no exit rule, the app owns the exit. This is not about becoming a monk. It is about making your phone slightly less talented at stealing your day. Which app gets moved off your home screen today?""",
}


def _word_count(text: str) -> int:
    return len(re.findall(r"\b[\w'-]+\b", text))


def _estimate_seconds(word_count: int, words_per_minute: int = 145) -> int:
    return round(word_count / words_per_minute * 60)


def _generic_voiceover(idea: dict[str, Any]) -> str:
    """Fallback finalizer for non-custom ideas."""
    return (
        f"{idea['hook']} "
        f"Here is the useful part. {idea['script_outline']} "
        f"Do not turn this into another idea you save and forget. Try the smallest version today. "
        f"{idea['cta']}"
    )


def _caption_beats(voiceover: str, duration: int) -> list[dict[str, Any]]:
    sentences = [part.strip() for part in re.split(r"(?<=[.!?])\s+", voiceover) if part.strip()]
    if not sentences:
        return []
    step = max(2, round(duration / len(sentences)))
    beats: list[dict[str, Any]] = []
    current = 0
    for sentence in sentences:
        beats.append({"start": current, "text": sentence})
        current += step
    return beats


def _production_notes(idea: dict[str, Any], estimated_seconds: int) -> list[str]:
    notes = [
        "First frame must show the hook as large kinetic caption text.",
        "Use motion or a visual state change in the first 1-2 seconds.",
        "Avoid static AI slideshow visuals; use screen recordings, cards, timer, or before/after cuts.",
    ]
    if estimated_seconds >= 60:
        notes.append("Keep this version above 60 seconds for TikTok Creator Rewards testing.")
    if idea["pillar"] == "ai_life_systems":
        notes.append("Show the human approval/decision moment; do not imply AI has final authority.")
    if idea["pillar"] == "attention_design":
        notes.append("Avoid moral panic; frame as attention design and defaults.")
    return notes


def finalize_voiceover(idea: dict[str, Any]) -> dict[str, Any]:
    """Create a final spoken script and production metadata for one idea."""
    voiceover = TOP3_CUSTOM_VOICEOVERS.get(idea["id"], _generic_voiceover(idea)).strip()
    word_count = _word_count(voiceover)
    estimated_seconds = _estimate_seconds(word_count)
    platform_note = "TikTok Rewards Candidate" if int(idea["duration_seconds"]) >= 60 else "Growth Short"

    return {
        "id": idea["id"],
        "pillar": idea["pillar"],
        "title": idea["title"],
        "target_seconds": int(idea["duration_seconds"]),
        "estimated_seconds": estimated_seconds,
        "platform_note": platform_note,
        "word_count": word_count,
        "voiceover": voiceover,
        "caption_beats": _caption_beats(voiceover, estimated_seconds),
        "visual_concept": idea["visual_concept"],
        "caption": idea["caption"],
        "cta": idea["cta"],
        "production_notes": _production_notes(idea, estimated_seconds),
    }


def format_final_script(final: dict[str, Any]) -> str:
    """Format final voiceover package as Markdown."""
    beats = "\n".join(f"- {beat['start']:02d}s: {beat['text']}" for beat in final["caption_beats"])
    notes = "\n".join(f"- {note}" for note in final["production_notes"])
    return f"""# {final['title']}

- ID: `{final['id']}`
- Pillar: `{final['pillar']}`
- Target duration: {final['target_seconds']}s
- Estimated voiceover duration: {final['estimated_seconds']}s
- Word count: {final['word_count']}
- Platform note: {final['platform_note']}

## Voiceover

{final['voiceover']}

## Caption beats

{beats}

## Visual concept

{final['visual_concept']}

## Caption

{final['caption']}

## CTA

{final['cta']}

## Production notes

{notes}
"""


def write_final_scripts(
    batch: dict[str, Any], output_dir: Path, selected_ids: list[str] | None = None
) -> list[Path]:
    """Write final voiceover scripts for selected ideas."""
    selected = set(selected_ids or [])
    output_dir.mkdir(parents=True, exist_ok=True)
    paths: list[Path] = []
    for idea in batch.get("ideas", []):
        if selected and idea["id"] not in selected:
            continue
        final = finalize_voiceover(idea)
        path = output_dir / f"{final['id']}-{_slug(final['title'])}.md"
        path.write_text(format_final_script(final), encoding="utf-8")
        paths.append(path)
    return paths
