"""RBS REGAL — Module Video Tutorials.

Super Admin can attach a YouTube / Vimeo / direct MP4 URL to each module path.
When the user opens the Floating AI on that page, the assistant shows a
"▶ Watch 2-min video" button — but ONLY if the user has the `video_tutorials`
feature flag enabled in their per-user feature overrides.

This makes the Floating AI a true onboarding trainer: text tips + interactive
nav + video walkthrough — all gated by Super Admin.

Endpoints:
  • GET  /api/module-tutorials           — list all tutorials (admin)
  • PUT  /api/module-tutorials/{path}    — upsert tutorial for a module path
  • DELETE /api/module-tutorials/{path}  — remove tutorial
  • GET  /api/module-tutorials/me?path=X — fetch tutorial for THIS user on
        page X. Returns {} if disabled for the user.
"""
from __future__ import annotations

import csv
import io
from datetime import datetime, timezone
from typing import Optional, List
from fastapi import APIRouter, HTTPException, Depends, Request, UploadFile, File
from pydantic import BaseModel, Field

from auth import get_current_user, require_admin

router = APIRouter(prefix="/api/module-tutorials", tags=["module-tutorials"])


def _now_iso() -> str:
    return datetime.now(timezone.utc).isoformat()


class TutorialIn(BaseModel):
    module_path: str                                # e.g. "/pos"
    title: Optional[str] = ""
    video_url: str                                  # YouTube / Vimeo / MP4
    description: Optional[str] = ""
    duration_seconds: Optional[int] = 120
    language: Optional[str] = "hi"                  # hi | en | hi-en
    is_active: bool = True


def _normalise_path(p: str) -> str:
    if not p:
        return "/"
    p = p.strip()
    if not p.startswith("/"):
        p = "/" + p
    return p.rstrip("/") or "/"


def _ser(doc: dict) -> dict:
    out = {k: v for k, v in doc.items() if k != "_id"}
    out["id"] = str(doc.get("_id", ""))
    return out


@router.get("")
async def list_tutorials(request: Request, user=Depends(get_current_user)):
    """List all configured tutorials. Visible to all users (so AI bubble can
    surface video buttons), but only admins can mutate via PUT/DELETE."""
    db = request.app.state.db
    docs = await db.module_tutorials.find({}).sort("module_path", 1).to_list(500)
    return [_ser(d) for d in docs]


@router.put("/{module_path:path}")
async def upsert_tutorial(module_path: str, payload: TutorialIn, request: Request, user=Depends(require_admin)):
    """Create or update a tutorial. Caller passes the path in the URL OR in body."""
    db = request.app.state.db
    path = _normalise_path(payload.module_path or module_path)
    if not payload.video_url.strip():
        raise HTTPException(422, "video_url is required")
    doc = {
        "module_path": path,
        "title": payload.title.strip()[:140] if payload.title else "",
        "video_url": payload.video_url.strip(),
        "description": payload.description.strip()[:500] if payload.description else "",
        "duration_seconds": int(payload.duration_seconds or 120),
        "language": payload.language or "hi",
        "is_active": bool(payload.is_active),
        "updated_at": _now_iso(),
        "updated_by": user.get("email", ""),
    }
    await db.module_tutorials.update_one(
        {"module_path": path},
        {"$set": doc, "$setOnInsert": {"created_at": _now_iso()}},
        upsert=True,
    )
    return {"ok": True, **doc}


@router.delete("/{module_path:path}")
async def delete_tutorial(module_path: str, request: Request, user=Depends(require_admin)):
    db = request.app.state.db
    path = _normalise_path(module_path)
    r = await db.module_tutorials.delete_one({"module_path": path})
    if r.deleted_count == 0:
        raise HTTPException(404, "Tutorial not found")
    return {"ok": True}


@router.get("/me")
async def my_tutorial(request: Request, path: str = "/", user=Depends(get_current_user)):
    """Resolve the tutorial for the current user on a given page.

    Returns `{enabled: false}` if the user has the `video_tutorials` feature
    OFF in their per-user overrides — the AI will hide the video button.
    """
    db = request.app.state.db
    # Check per-user feature override
    override = await db.user_feature_overrides.find_one({"user_email": user.get("email", "")})
    enabled = True                                  # default: ON for all
    if override:
        feats = (override or {}).get("features") or {}
        if "video_tutorials" in feats:
            enabled = bool(feats["video_tutorials"])
    if not enabled:
        return {"enabled": False}

    # Find best-match tutorial — exact first, then longest prefix
    norm = _normalise_path(path)
    exact = await db.module_tutorials.find_one({"module_path": norm, "is_active": True})
    if exact:
        return {"enabled": True, **_ser(exact)}
    # Prefix match
    all_active = await db.module_tutorials.find({"is_active": True}).to_list(200)
    best = None
    for t in all_active:
        if norm.startswith(t["module_path"]) and (best is None or len(t["module_path"]) > len(best["module_path"])):
            best = t
    if best:
        return {"enabled": True, **_ser(best)}
    return {"enabled": True, "video_url": "", "module_path": norm}


# ---------------------------------------------------------------------------
# Bulk CSV Import — admin uploads one file with all 21 module tutorials
# ---------------------------------------------------------------------------
@router.post("/bulk-import")
async def bulk_import_tutorials(request: Request, file: UploadFile = File(...), user=Depends(require_admin)):
    """Upload a CSV with columns: module_path, video_url, title, description,
    duration_seconds, language, is_active.

    Headers are case-insensitive; only `module_path` and `video_url` are required.
    Returns: inserted, updated, skipped, errors[]
    """
    raw = await file.read()
    try:
        text = raw.decode("utf-8-sig")
    except UnicodeDecodeError:
        text = raw.decode("latin-1", errors="ignore")
    rows = list(csv.DictReader(io.StringIO(text)))
    if not rows:
        raise HTTPException(400, "CSV is empty")

    db = request.app.state.db
    inserted, updated, skipped, errors = 0, 0, 0, []
    for idx, row in enumerate(rows, start=2):
        # Normalise header keys (lowercase strip)
        norm = {(k or "").strip().lower(): (v or "").strip() for k, v in row.items()}
        mp = _normalise_path(norm.get("module_path") or norm.get("path") or "")
        url = norm.get("video_url") or norm.get("url") or ""
        if not mp or not url:
            errors.append({"row": idx, "reason": "module_path & video_url required"})
            skipped += 1
            continue
        doc = {
            "module_path": mp,
            "video_url": url,
            "title": norm.get("title", "")[:140],
            "description": norm.get("description", "")[:500],
            "duration_seconds": int(norm.get("duration_seconds") or norm.get("duration") or 120),
            "language": (norm.get("language") or "hi")[:10],
            "is_active": (norm.get("is_active", "true").lower() not in ("false", "0", "no", "off")),
            "updated_at": _now_iso(),
            "updated_by": user.get("email", ""),
        }
        existing = await db.module_tutorials.find_one({"module_path": mp})
        if existing:
            await db.module_tutorials.update_one({"_id": existing["_id"]}, {"$set": doc})
            updated += 1
        else:
            doc["created_at"] = _now_iso()
            await db.module_tutorials.insert_one(doc)
            inserted += 1
    return {"ok": True, "inserted": inserted, "updated": updated, "skipped": skipped, "errors": errors[:20], "total_rows": len(rows)}
