#!/usr/bin/env python3
from __future__ import annotations

import argparse
import json
import sys
from pathlib import Path
from typing import Any

ROOT = Path(__file__).resolve().parents[1]
BACKEND = ROOT / "backend"
sys.path.insert(0, str(BACKEND))

from sqlmodel import Session, select  # noqa: E402
from app.db.session import init_db  # noqa: E402
from app.models.core import ContentScript, Idea, Theme, VideoAsset, now_utc  # noqa: E402


def load_json(path: Path) -> dict[str, Any] | None:
    try:
        return json.loads(path.read_text(encoding="utf-8"))
    except Exception:
        return None


def text_from(value: Any) -> str | None:
    if value is None:
        return None
    if isinstance(value, str):
        return value.strip() or None
    if isinstance(value, list):
        return "\n".join(str(x) for x in value if x).strip() or None
    if isinstance(value, dict):
        for key in ["text", "script", "voiceover", "narration", "content"]:
            if key in value:
                return text_from(value[key])
    return str(value).strip() or None


def package_id_for(path: Path, source_dir: Path) -> str:
    try:
        return path.relative_to(source_dir).parts[0]
    except Exception:
        return path.parent.name


def infer_family(data: dict[str, Any], package_id: str) -> str:
    for key in ["family", "topic", "theme", "content_family", "series"]:
        value = data.get(key)
        if isinstance(value, str) and value.strip():
            return value.strip().replace("_", " ").title()
    if "everyday-red-flags" in package_id:
        return "Everyday Red Flags"
    return (package_id.split("-")[0] or "Imported Content").replace("_", " ").title()


def extract_script(data: dict[str, Any]) -> str | None:
    for key in ["script", "voiceover_script", "narration", "transcript", "full_script"]:
        found = text_from(data.get(key))
        if found:
            return found
    scenes = data.get("scenes") or data.get("timeline")
    if isinstance(scenes, list):
        lines = []
        for scene in scenes:
            if isinstance(scene, dict):
                lines.append(text_from(scene.get("voiceover") or scene.get("text") or scene.get("subtitle")) or "")
        joined = "\n".join(line for line in lines if line).strip()
        if joined:
            return joined
    return None


def extract_title(data: dict[str, Any], package_id: str) -> str:
    for key in ["title", "working_title", "youtube_title", "short_title"]:
        value = text_from(data.get(key))
        if value:
            return value
    yt = data.get("youtube") or data.get("youtube_metadata") or data.get("youtube_upload")
    if isinstance(yt, dict):
        value = text_from(yt.get("title"))
        if value:
            return value
    return package_id.replace("-", " ").title()


def extract_youtube(data: dict[str, Any]) -> tuple[str | None, str | None]:
    for container_key in ["youtube", "youtube_metadata", "youtube_upload", "posting_pack"]:
        container = data.get(container_key)
        if isinstance(container, dict):
            title = text_from(container.get("title") or container.get("youtube_title"))
            desc = text_from(container.get("description") or container.get("youtube_description"))
            if title or desc:
                return title, desc
    return text_from(data.get("youtube_title")), text_from(data.get("youtube_description"))


def extract_caption(data: dict[str, Any]) -> str | None:
    for key in ["tiktok_caption", "caption", "platform_caption"]:
        value = text_from(data.get(key))
        if value:
            return value
    tt = data.get("tiktok") or data.get("tiktok_metadata")
    if isinstance(tt, dict):
        return text_from(tt.get("caption"))
    return None


def extract_hook(script: str | None, data: dict[str, Any]) -> str | None:
    for key in ["hook", "opening", "first_line"]:
        value = text_from(data.get(key))
        if value:
            return value
    if script:
        return script.split("\n", 1)[0][:180]
    return None


def scan(source_dir: Path):
    for path in sorted(source_dir.rglob("review_package*.json")):
        data = load_json(path)
        if not data:
            continue
        package_id = package_id_for(path, source_dir)
        script = extract_script(data)
        title = extract_title(data, package_id)
        yt_title, yt_desc = extract_youtube(data)
        yield {
            "package_id": package_id,
            "family": infer_family(data, package_id),
            "title": title,
            "hook": extract_hook(script, data),
            "script_text": script,
            "platform_caption": extract_caption(data),
            "youtube_title": yt_title or title,
            "youtube_description": yt_desc,
            "status": "produced" if any(path.parent.glob("*.mp4")) else "scripted",
            "source_path": str(path),
        }


def upsert(session: Session, item: dict[str, Any]) -> tuple[bool, str]:
    family = session.exec(select(Theme).where(Theme.title == item["family"])).first()
    if not family:
        family = Theme(title=item["family"], description="Imported content family", promise="Help viewers avoid common scam traps.", priority=10)
        session.add(family)
        session.commit()
        session.refresh(family)
    video = session.exec(select(VideoAsset).where(VideoAsset.package_id == item["package_id"])).first()
    existing = session.exec(select(ContentScript).where(ContentScript.package_id == item["package_id"], ContentScript.title == item["title"])).first()
    created = False
    if not existing:
        existing = ContentScript(title=item["title"], package_id=item["package_id"])
        created = True
    existing.family_id = family.id
    existing.video_asset_id = video.id if video else None
    existing.hook = item.get("hook")
    existing.script_text = item.get("script_text")
    existing.platform_caption = item.get("platform_caption")
    existing.youtube_title = item.get("youtube_title")
    existing.youtube_description = item.get("youtube_description")
    existing.status = "produced" if video else item.get("status") or "scripted"
    existing.source_path = item.get("source_path")
    existing.updated_at = now_utc()
    session.add(existing)
    if not session.exec(select(Idea).where(Idea.topic_id == family.id, Idea.title == item["title"])).first():
        session.add(Idea(topic_id=family.id, title=item["title"], notes=item.get("hook"), priority=5, status="produced" if video else "idea"))
    session.commit()
    return created, family.title


def main() -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument("--source-dir", required=True)
    parser.add_argument("--api-base", default=None, help="Accepted for CLI compatibility; importer writes to local DB.")
    parser.add_argument("--dry-run", action="store_true")
    parser.add_argument("--import", dest="do_import", action="store_true")
    args = parser.parse_args()
    source = Path(args.source_dir).expanduser()
    items = list(scan(source)) if source.exists() else []
    print(json.dumps({"source_dir": str(source), "found_scripts": len(items), "families": sorted({i['family'] for i in items})}, ensure_ascii=False, indent=2))
    if args.dry_run or not args.do_import:
        for item in items[:30]:
            print(json.dumps({k: item.get(k) for k in ["family", "title", "package_id", "status", "source_path"]}, ensure_ascii=False))
        return 0
    engine = init_db()
    created = 0
    updated = 0
    families = set()
    with Session(engine) as session:
        for item in items:
            was_created, family = upsert(session, item)
            created += 1 if was_created else 0
            updated += 0 if was_created else 1
            families.add(family)
    print(json.dumps({"imported": len(items), "created": created, "updated": updated, "families": sorted(families)}, ensure_ascii=False, indent=2))
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
