"""JamPulse – 30-Tage Content-Kalender (Auto-Themen + optional Auto-Render)."""

from __future__ import annotations

import json
import random
import threading
from datetime import datetime, timedelta
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
CALENDAR_PATH = ROOT / "data" / "jampulse-calendar.json"

# Mo/Mi/Fr/So Post-Slots
DEFAULT_HOURS = (9, 12, 18, 20)


def _load() -> dict:
    if CALENDAR_PATH.is_file():
        try:
            data = json.loads(CALENDAR_PATH.read_text(encoding="utf-8"))
            if isinstance(data, dict):
                return data
        except (json.JSONDecodeError, OSError):
            pass
    return {"entries": [], "generated_at": ""}


def _save(data: dict) -> None:
    CALENDAR_PATH.parent.mkdir(parents=True, exist_ok=True)
    CALENDAR_PATH.write_text(json.dumps(data, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")


def generate_calendar(*, days: int = 30, posts_per_week: int = 4) -> dict:
    from jam.jampulse_templates import INDUSTRY_TEMPLATES

    templates = list(INDUSTRY_TEMPLATES)
    random.shuffle(templates)
    entries: list[dict] = []
    start = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
    t_idx = 0
    slot_hours = DEFAULT_HOURS[: max(1, min(posts_per_week, len(DEFAULT_HOURS)))]

    for d in range(days):
        day = start + timedelta(days=d)
        # ca. 4 Posts pro Woche ≈ jeden 2. Tag
        if d % max(1, 7 // posts_per_week) != 0 and d > 0:
            continue
        tpl = templates[t_idx % len(templates)]
        t_idx += 1
        hour = slot_hours[len(entries) % len(slot_hours)]
        when = day.replace(hour=hour, minute=0)
        entries.append(
            {
                "id": f"{when.strftime('%Y%m%d-%H%M')}-{tpl['id']}",
                "date": when.isoformat(timespec="seconds"),
                "template_id": tpl["id"],
                "label": tpl["label"],
                "prompt": tpl["prompt"],
                "hashtags": tpl.get("hashtags", ""),
                "duration_sec": 120 if d % 3 == 0 else 60,
                "quality": "4k" if d % 4 == 0 else "1080p",
                "status": "planned",
                "job_id": "",
                "video": "",
            }
        )

    data = {
        "generated_at": datetime.now().isoformat(timespec="seconds"),
        "days": days,
        "entries": entries[:days],
    }
    _save(data)
    return data


def list_entries(*, include_done: bool = True) -> list[dict]:
    data = _load()
    entries = data.get("entries") or []
    if not include_done:
        entries = [e for e in entries if e.get("status") != "done"]
    return entries


def due_entries(*, within_hours: float = 2.0) -> list[dict]:
    now = datetime.now()
    out: list[dict] = []
    for e in list_entries(include_done=False):
        if e.get("status") not in ("planned", "queued"):
            continue
        try:
            when = datetime.fromisoformat(str(e["date"]))
        except (ValueError, TypeError):
            continue
        delta_h = (when - now).total_seconds() / 3600.0
        if -1.0 <= delta_h <= within_hours:
            out.append(e)
    return out


def mark_entry(entry_id: str, **fields) -> dict | None:
    data = _load()
    for e in data.get("entries") or []:
        if e.get("id") == entry_id:
            e.update(fields)
            _save(data)
            return e
    return None


def run_entry(entry_id: str, *, background: bool = True) -> dict:
    data = _load()
    entry = next((e for e in data.get("entries") or [] if e.get("id") == entry_id), None)
    if not entry:
        return {"ok": False, "error": "Eintrag nicht gefunden"}

    from jam.jampulse_license import can_generate

    ok, msg, _ = can_generate(consume=True)
    if not ok:
        return {"ok": False, "error": msg}

    mark_entry(entry_id, status="running")

    def _work() -> None:
        try:
            from jam.ia1minute import run_ia1minute

            quality = str(entry.get("quality") or "1080p")
            result = run_ia1minute(
                entry["prompt"],
                hd=True,
                commercial=True,
                target_sec=int(entry.get("duration_sec") or 60),
                resolution="4k" if quality.lower() == "4k" else "1080p",
            )
            if result.get("ok"):
                mark_entry(
                    entry_id,
                    status="done",
                    video=result.get("video"),
                    job_id=result.get("work_dir"),
                )
                video = Path(result.get("video") or "")
                cap = f"{entry['prompt']}\n\n{entry.get('hashtags', '')}"
                if video.is_file():
                    from jam.social_publish import publish_video

                    publish_video(
                        video,
                        caption=cap,
                        title=entry.get("label", "JamPulse"),
                        platforms=("tiktok", "youtube", "instagram"),
                    )
            else:
                mark_entry(entry_id, status="error", error=result.get("error") or "Fehler")
        except Exception as ex:
            mark_entry(entry_id, status="error", error=str(ex)[:200])

    if background:
        threading.Thread(target=_work, daemon=True).start()
        return {"ok": True, "message": "Kalender-Job gestartet", "entryId": entry_id}
    _work()
    return {"ok": True, "entryId": entry_id}


def run_due(*, limit: int = 1) -> list[dict]:
    results = []
    for e in due_entries()[:limit]:
        results.append(run_entry(e["id"]))
    return results
