"""Hand off a finished video to MinIO storage via gnommoeditor (prod) or gnommoweb (local).

Works for any gnommo project type: parent videos and shorts alike.

Usage:
  gnommo handoff -p video1
  gnommo handoff -p short_pixelated_universe
  gnommo handoff -p video1 --file /path/to/render.mp4

Reads project.json for the 'output_video' field (path relative to the
project directory). Override with --file.

On success (production):
  - Uploads the video to MinIO via POST /api/assets/upload on gnommoeditor
  - Updates .gnommo_sync.prod.json with asset URL

On success (local):
  - Uploads via POST /api/projects/:handle/handoff on gnommoweb
  - Updates .gnommo_sync.json with new video_version

Configuration (from .env or environment):
  GNOMMOEDITOR_URL   Base URL for production (e.g. https://editor.glitch.university)
  GNOMMOWEB_URL      Base URL for local dev (e.g. http://localhost:3001)
  GNOMMOWEB_API_KEY  Bearer token (CONTENT_API_KEY from gnommoweb)
"""

import json
import os
import sys
from datetime import datetime, timezone
from pathlib import Path

try:
    import requests
except ImportError:
    print(
        "Error: 'requests' package is required. Run: pip install requests",
        file=sys.stderr,
    )
    sys.exit(1)

SYNC_FILE_LOCAL = ".gnommo_sync.json"
SYNC_FILE_PROD = ".gnommo_sync.prod.json"


def _sync_file(prod: bool) -> str:
    return SYNC_FILE_PROD if prod else SYNC_FILE_LOCAL


def _load_env_file():
    env_path = Path(__file__).parent.parent / ".env"
    if not env_path.exists():
        return
    with open(env_path) as f:
        for line in f:
            line = line.strip()
            if not line or line.startswith("#") or "=" not in line:
                continue
            key, _, value = line.partition("=")
            key = key.strip()
            value = value.strip().strip('"').strip("'")
            if key not in os.environ:
                os.environ[key] = value


def _read_sync(project_path: Path, prod: bool = False) -> dict:
    sync_file = project_path / _sync_file(prod)
    if sync_file.exists():
        with open(sync_file) as f:
            return json.load(f)
    return {}


def _write_sync(project_path: Path, data: dict, prod: bool = False):
    with open(project_path / _sync_file(prod), "w") as f:
        json.dump(data, f, indent=2)


def cmd_handoff(
    project_path: Path,
    verbose: bool = False,
    file_override: str | None = None,
    prod: bool = False,
    res: str = "full",
) -> int:
    _load_env_file()

    if prod:
        api_url = os.environ.get("GNOMMOEDITOR_URL", "").rstrip("/")
        if not api_url:
            print("Error: GNOMMOEDITOR_URL is not set.", file=sys.stderr)
            return 1
    else:
        api_url = os.environ.get("GNOMMOWEB_URL", "").rstrip("/")
        api_key = os.environ.get("GNOMMOWEB_API_KEY", "")
        if not api_url:
            print("Error: GNOMMOWEB_URL is not set.", file=sys.stderr)
            return 1
        if not api_key:
            print("Error: GNOMMOWEB_API_KEY is not set.", file=sys.stderr)
            return 1

    if verbose:
        target = "production (gnommoeditor)" if prod else "local"
        print(f"  → {target}: {api_url}")

    project_file = project_path / "project.json"
    if not project_file.exists():
        print(f"Error: {project_file} not found", file=sys.stderr)
        return 1

    with open(project_file) as f:
        project = json.load(f)

    project_id = project.get("id")
    if not project_id:
        print("Error: project.json must have an 'id' field.", file=sys.stderr)
        return 1

    # ── Resolve video file ─────────────────────────────────────────────────────
    if file_override:
        video_path = Path(file_override)
    else:
        output_filename = (
            project.get("output") or Path(project.get("output_video", "")).name
        )
        if not output_filename:
            print(
                "Error: no 'output' field in project.json and no --file provided.",
                file=sys.stderr,
            )
            return 1
        if res != "full":
            video_path = project_path / "out" / res / output_filename
        else:
            video_path = project_path / "out" / output_filename

    if not video_path.exists():
        print(f"Error: video file not found: {video_path}", file=sys.stderr)
        return 1

    file_size_mb = video_path.stat().st_size / (1024 * 1024)
    if verbose:
        print(f"Handing off {project_id} → {api_url}")
        print(f"  File: {video_path} ({file_size_mb:.1f} MB)")

    # ── Upload ─────────────────────────────────────────────────────────────────
    try:
        if prod:
            # gnommoeditor: POST /api/assets/upload — field name is 'file', no auth
            with open(video_path, "rb") as vf:
                r = requests.post(
                    f"{api_url}/api/assets/upload",
                    files={"file": (video_path.name, vf, _mime_type(video_path))},
                    timeout=None,
                )
        else:
            # gnommoweb: POST /api/projects/:id/handoff
            with open(video_path, "rb") as vf:
                r = requests.post(
                    f"{api_url}/api/projects/{project_id}/handoff",
                    files={"video": (video_path.name, vf, _mime_type(video_path))},
                    headers={"Authorization": f"Bearer {api_key}"},
                    timeout=None,
                )
    except requests.exceptions.ConnectionError:
        print(f"✗ Could not connect to {api_url}")
        return 1

    if not r.ok:
        try:
            body = r.json()
        except Exception:
            body = r.text[:500]
        print(f"✗ Server returned {r.status_code}: {body}")
        return 1

    result = r.json()

    # ── Write sync state ───────────────────────────────────────────────────────
    now_iso = datetime.now(tz=timezone.utc).isoformat(timespec="seconds")
    existing_sync = _read_sync(project_path, prod)

    if prod:
        # gnommoeditor response: { asset: { id, url, minio_object_key, ... } }
        asset = result.get("asset", {})
        asset_url = asset.get("url", "")
        _write_sync(
            project_path,
            {**existing_sync, "last_handoff_at": now_iso, "asset_url": asset_url},
            prod,
        )
        print(f"✓ {project_id} → uploaded [asset #{asset.get('id')}]")
        if asset_url:
            print(f"  {asset_url}")
    else:
        # gnommoweb response: { video_version, video_url, asset: { updated_at } }
        video_version = result.get("video_version", "?")
        video_url = result.get("video_url", "")
        _write_sync(
            project_path,
            {
                **existing_sync,
                "last_handoff_at": now_iso,
                "video_version": video_version,
                "server_updated_at": result.get("asset", {}).get(
                    "updated_at", existing_sync.get("server_updated_at")
                ),
            },
            prod,
        )
        print(f"✓ {project_id} → v{video_version} [processed]")
        if video_url:
            print(f"  {video_url}")

    return 0


def _mime_type(path: Path) -> str:
    ext = path.suffix.lower()
    return {
        ".mp4": "video/mp4",
        ".mov": "video/quicktime",
        ".webm": "video/webm",
        ".mkv": "video/x-matroska",
    }.get(ext, "application/octet-stream")
