import json
import logging
from datetime import date, datetime, timedelta, timezone

from app.config import CATEGORIES, OUTPUT_DIR
from app.content.gemini_client import generate_unique_fact
from app.dedup.store import connect, insert_fact, update_status
from app.orchestrator.scheduling import TR_UTC_OFFSET_HOURS, compute_publish_at
from app.render.video_builder import render_video
from app.youtube.quota import can_upload_more
from app.youtube.uploader import upload_video

logger = logging.getLogger(__name__)


def run_daily_pipeline(target_date: date | None = None, categories: list[str] | None = None) -> dict:
    if target_date is None:
        target_date = (datetime.now(timezone.utc) + timedelta(hours=TR_UTC_OFFSET_HOURS)).date()

    out_dir = OUTPUT_DIR / target_date.isoformat()
    out_dir.mkdir(parents=True, exist_ok=True)
    logger.info("Target publish date: %s", target_date.isoformat())

    manifest_path = out_dir / "manifest.json"
    manifest: dict = json.loads(manifest_path.read_text(encoding="utf-8")) if manifest_path.exists() else {}

    slugs_to_process = categories if categories is not None else list(CATEGORIES.keys())
    conn = connect()

    try:
        for category_slug in slugs_to_process:
            category = CATEGORIES[category_slug]
            entry: dict = {"status": "pending"}
            manifest[category_slug] = entry

            try:
                if not can_upload_more(conn):
                    entry["status"] = "skipped_quota"
                    logger.warning("Daily upload quota reached, skipping %s", category_slug)
                    continue

                content = generate_unique_fact(conn, category_slug, category["display_name"])
                if content is None:
                    entry["status"] = "generation_failed"
                    logger.error("Generation failed for %s", category_slug)
                    continue

                fact_id = insert_fact(
                    conn, category_slug, content.fact, content.title, content.description, content.hashtags
                )
                entry["fact_id"] = fact_id
                entry["title"] = content.title

                video_path = out_dir / f"{category_slug}.mp4"
                render_video(category_slug, content.fact, video_path)
                update_status(conn, fact_id, "rendered")
                entry["status"] = "rendered"

                publish_at = compute_publish_at(category["hour"], target_date)
                video_id = upload_video(
                    video_path=video_path,
                    title=content.title,
                    description=content.description,
                    hashtags=content.hashtags,
                    publish_at_iso=publish_at,
                )
                update_status(conn, fact_id, "uploaded", published_at=publish_at, youtube_video_id=video_id)
                entry["status"] = "uploaded"
                entry["youtube_video_id"] = video_id
                entry["publish_at"] = publish_at
                logger.info("%s -> uploaded (%s), scheduled %s", category_slug, video_id, publish_at)

            except Exception as exc:
                logger.exception("Category %s failed", category_slug)
                entry["status"] = "error"
                entry["error"] = str(exc)
            finally:
                conn.commit()

    finally:
        conn.close()

    manifest_path.write_text(json.dumps(manifest, ensure_ascii=False, indent=2), encoding="utf-8")
    logger.info("Daily run complete. Manifest: %s", manifest_path)
    return manifest
