"""
seed_file_cabinets.py — Create one file cabinet per class with sample document references.

Creates file_cabinets, files, and cabinet_memberships rows via Supabase REST API
using the service role key. Also creates document_artefacts entries for sample files.

Each cabinet is owned by the class's primary teacher and shared with students
in that class via cabinet_memberships.

Tables: file_cabinets, files, cabinet_memberships, document_artefacts

Run inside ccapi container:
    python3 -c "from run.initialization.seed_file_cabinets import seed; seed()"
"""
import os
import time
import uuid
import requests
from typing import Dict, Any, List, Optional

SUPA_URL   = os.environ["SUPABASE_URL"]
SERVICE_KEY = os.environ["SERVICE_ROLE_KEY"]
API_BASE   = os.environ.get("API_BASE_URL", "http://localhost:8000")

# ─── Passwords (standardized from T4) ────────────────────────────────────────

PWD_ADMIN   = "Admin@Cc2025!"
PWD_TEACHER = "Teacher@Cc2025!"
PWD_STUDENT = "Student@Cc2025!"


# ─── Sample file data ────────────────────────────────────────────────────────
# Each cabinet gets 2-3 sample files with realistic paths.

SAMPLE_FILES = {
    # Physics cabinets
    "lesson_plans": [
        {"name": "forces_motion_plan.pdf", "path": "cc.public.snapshots/lesson_plans/forces_motion.pdf", "mime_type": "application/pdf", "size": "245KB"},
        {"name": "electric_circuits_plan.pdf", "path": "cc.public.snapshots/lesson_plans/electric_circuits.pdf", "mime_type": "application/pdf", "size": "312KB"},
    ],
    "worksheets": [
        {"name": "worksheet_fma.pdf", "path": "cc.public.snapshots/worksheets/fma_practice.pdf", "mime_type": "application/pdf", "size": "128KB"},
        {"name": "worksheet_resistance.pdf", "path": "cc.public.snapshots/worksheets/resistance_calc.pdf", "mime_type": "application/pdf", "size": "95KB"},
    ],
    "presentations": [
        {"name": "intro_forces.pptx", "path": "cc.public.snapshots/presentations/forces_intro.pptx", "mime_type": "application/vnd.openxmlformats-officedocument.presentationml.presentation", "size": "2.1MB"},
    ],
    # Maths cabinets
    "lesson_plans": [
        {"name": "quadratic_factorisation_plan.pdf", "path": "cc.public.snapshots/lesson_plans/quadratics.pdf", "mime_type": "application/pdf", "size": "278KB"},
    ],
    "worksheets": [
        {"name": "worksheet_quadratics.pdf", "path": "cc.public.snapshots/worksheets/quadratic_practice.pdf", "mime_type": "application/pdf", "size": "156KB"},
        {"name": "worksheet_tree_diagrams.pdf", "path": "cc.public.snapshots/worksheets/tree_diagrams.pdf", "mime_type": "application/pdf", "size": "134KB"},
    ],
    # CS cabinets
    "lesson_plans": [
        {"name": "intro_python_plan.pdf", "path": "cc.public.snapshots/lesson_plans/intro_python.pdf", "mime_type": "application/pdf", "size": "198KB"},
    ],
    "code_samples": [
        {"name": "hello_world.py", "path": "cc.public.snapshots/code_samples/hello_world.py", "mime_type": "text/x-python", "size": "0.5KB"},
        {"name": "variables.py", "path": "cc.public.snapshots/code_samples/variables.py", "mime_type": "text/x-python", "size": "1.2KB"},
    ],
}


# ─── Helpers ───────────────────────────────────────────────────────────────────

def _sb_headers() -> Dict:
    return {
        "apikey": SERVICE_KEY,
        "Authorization": f"Bearer {SERVICE_KEY}",
        "Content-Type": "application/json",
    }


def _sign_in(email: str, password: str) -> str:
    r = requests.post(
        f"{SUPA_URL}/auth/v1/token?grant_type=password",
        headers={"apikey": SERVICE_KEY, "Content-Type": "application/json"},
        json={"email": email, "password": password},
    )
    r.raise_for_status()
    return r.json()["access_token"]


def _get_profile_id(email: str) -> Optional[str]:
    """Look up a profile's UUID by email via Supabase service role."""
    r = requests.get(
        f"{SUPA_URL}/rest/v1/profiles",
        headers=_sb_headers(),
        params={"email": f"eq.{email}", "select": "id", "limit": "1"},
    )
    data = r.json() if r.ok else []
    return data[0]["id"] if data else None


def _get_class_info(admin_token: str, class_code: str) -> Optional[Dict]:
    """Get class info including teacher and students."""
    r = requests.get(
        f"{API_BASE}/database/timetable/classes",
        headers={"Authorization": f"Bearer {admin_token}"},
        params={"class_code": class_code},
    )
    if not r.ok:
        return None
    data = r.json()
    if isinstance(data, list) and data:
        return data[0]
    if isinstance(data, dict):
        return data
    return None


def _get_class_students(admin_token: str, class_id: str) -> List[str]:
    """Get student profile IDs enrolled in a class."""
    r = requests.get(
        f"{API_BASE}/database/timetable/classes/{class_id}/students",
        headers={"Authorization": f"Bearer {admin_token}"},
    )
    if r.ok:
        data = r.json()
        if isinstance(data, list):
            return [s.get("student_id") or s.get("id") for s in data if s.get("student_id") or s.get("id")]
    return []


# ─── Main seed ─────────────────────────────────────────────────────────────────

def seed() -> Dict[str, Any]:
    print("=" * 60)
    print("File cabinets seed — both schools")
    print("=" * 60)
    results: Dict[str, Any] = {}
    errors: List[str] = []

    # ── Sign in as both school admins ───────────────────────────────────────
    print("\n[1] Signing in as school admins...")
    admin_tokens = {}
    for school, email, pwd in [
        ("KevlarAI", "admin@kevlarai.test", PWD_ADMIN),
        ("Greenfield", "admin@greenfieldacademy.test", PWD_ADMIN),
    ]:
        try:
            token = _sign_in(email, pwd)
            admin_tokens[school] = token
            print(f"  ✓ {school} admin signed in")
        except Exception as e:
            print(f"  ✗ {school} admin login failed: {e}")
            errors.append(f"{school}_admin_login: {e}")

    if not admin_tokens:
        return {"success": False, "error": "No admin tokens obtained"}

    # ── Resolve class codes per school ──────────────────────────────────────
    print("\n[2] Resolving classes per school...")

    # KevlarAI classes
    kevlarai_classes = [
        ("10K/Ph1", "physics@kevlarai.test"),
        ("11K/Ph1", "physics@kevlarai.test"),
        ("10K/Ma1", "maths@kevlarai.test"),
        ("11K/Ma1", "maths@kevlarai.test"),
        ("10K/CS1", "physics@kevlarai.test"),
        ("11K/CS1", "maths@kevlarai.test"),
        ("9K/Ph1",  "physics@kevlarai.test"),
        ("9K/Ma1",  "maths@kevlarai.test"),
    ]

    # Greenfield classes (subset — just a few for cabinet seeding)
    greenfield_classes = [
        ("9P/Ph1",  "physics@greenfieldacademy.test"),
        ("10P/Ph2", "physics@greenfieldacademy.test"),
        ("9M/Ma1",  "maths@greenfieldacademy.test"),
        ("10M/Ma1", "maths@greenfieldacademy.test"),
        ("9En/1",   "teacher1@greenfieldacademy.test"),
        ("10Hs/1",  "teacher2@greenfieldacademy.test"),
    ]

    # ── Seed KevlarAI cabinets ──────────────────────────────────────────────
    print("\n[3] Seeding KevlarAI file cabinets...")
    results["kevlarai"] = {"cabinets": 0, "files": 0, "memberships": 0}

    for class_code, teacher_email in kevlarai_classes:
        try:
            # Get class info
            class_info = _get_class_info(admin_tokens["KevlarAI"], class_code)
            if not class_info:
                print(f"  ✗ class not found: {class_code}")
                errors.append(f"class_not_found: {class_code}")
                continue

            class_id = class_info.get("id") or class_info
            teacher_pid = _get_profile_id(teacher_email)
            if not teacher_pid:
                print(f"  ✗ teacher profile not found: {teacher_email}")
                errors.append(f"teacher_profile_not_found: {teacher_email}")
                continue

            # Get students in this class
            student_ids = _get_class_students(admin_tokens["KevlarAI"], str(class_id))

            # Determine file category based on subject
            subject = (class_info.get("subject") or "").lower()
            if "physics" in subject:
                file_category = "lesson_plans"
            elif "math" in subject:
                file_category = "worksheets"
            elif "cs" in subject or "computer" in subject:
                file_category = "code_samples"
            else:
                file_category = "lesson_plans"

            files_list = SAMPLE_FILES.get(file_category, SAMPLE_FILES["lesson_plans"])

            # Create cabinet
            cabinet_id = str(uuid.uuid4())
            cabinet_name = f"{class_code} — {class_info.get('name', class_code)}"

            r = requests.post(
                f"{SUPA_URL}/rest/v1/file_cabinets",
                headers={**_sb_headers(), "Prefer": "return=representation"},
                json={"id": cabinet_id, "user_id": teacher_pid, "name": cabinet_name},
                params={"on_conflict": "id"},
            )
            if r.status_code in (200, 201):
                print(f"  ✓ Cabinet: {cabinet_name}")
                results["kevlarai"]["cabinets"] += 1
            else:
                print(f"  ✗ Cabinet create failed ({class_code}): {r.text[:100]}")
                errors.append(f"cabinet_create: {class_code}")
                continue

            # Create files in cabinet
            for fi in files_list:
                file_id = str(uuid.uuid4())
                r = requests.post(
                    f"{SUPA_URL}/rest/v1/files",
                    headers={**_sb_headers(), "Prefer": "return=representation"},
                    json={
                        "id": file_id,
                        "cabinet_id": cabinet_id,
                        "name": fi["name"],
                        "path": fi["path"],
                        "bucket": "file-cabinets",
                        "mime_type": fi.get("mime_type"),
                        "size": fi.get("size"),
                        "metadata": {},
                    },
                    params={"on_conflict": "id"},
                )
                if r.status_code in (200, 201):
                    results["kevlarai"]["files"] += 1

                    # Create document_artefact for this file
                    artefact_id = str(uuid.uuid4())
                    requests.post(
                        f"{SUPA_URL}/rest/v1/document_artefacts",
                        headers={**_sb_headers(), "Prefer": "return=representation"},
                        json={
                            "id": artefact_id,
                            "file_id": file_id,
                            "type": fi.get("mime_type", "application/octet-stream").split("/")[-1],
                            "rel_path": fi["path"],
                            "status": "processed",
                            "extra": {"seeded": True, "source": "seed_file_cabinets"},
                        },
                        params={"on_conflict": "id"},
                    )

                time.sleep(0.05)

            # Create cabinet memberships for students
            for sid in student_ids:
                r = requests.post(
                    f"{SUPA_URL}/rest/v1/cabinet_memberships",
                    headers={**_sb_headers(), "Prefer": "return=minimal"},
                    json={
                        "cabinet_id": cabinet_id,
                        "profile_id": sid,
                        "role": "viewer",
                    },
                    params={"on_conflict": "cabinet_id,profile_id"},
                )
                if r.status_code in (200, 201, 409):
                    results["kevlarai"]["memberships"] += 1

            time.sleep(0.1)

        except Exception as e:
            err = f"cabinet seed {class_code}: {e}"
            print(f"  ✗ {err}")
            errors.append(err)

    # ── Seed Greenfield cabinets ────────────────────────────────────────────
    print("\n[4] Seeding Greenfield file cabinets...")
    results["greenfield"] = {"cabinets": 0, "files": 0, "memberships": 0}

    for class_code, teacher_email in greenfield_classes:
        try:
            class_info = _get_class_info(admin_tokens["Greenfield"], class_code)
            if not class_info:
                print(f"  ✗ class not found: {class_code}")
                errors.append(f"class_not_found: {class_code}")
                continue

            class_id = class_info.get("id") or class_info
            teacher_pid = _get_profile_id(teacher_email)
            if not teacher_pid:
                print(f"  ✗ teacher profile not found: {teacher_email}")
                errors.append(f"teacher_profile_not_found: {teacher_email}")
                continue

            student_ids = _get_class_students(admin_tokens["Greenfield"], str(class_id))

            subject = (class_info.get("subject") or "").lower()
            if "physics" in subject:
                file_category = "lesson_plans"
            elif "math" in subject:
                file_category = "worksheets"
            elif "english" in subject:
                file_category = "presentations"
            elif "history" in subject:
                file_category = "lesson_plans"
            else:
                file_category = "lesson_plans"

            files_list = SAMPLE_FILES.get(file_category, SAMPLE_FILES["lesson_plans"])

            cabinet_id = str(uuid.uuid4())
            cabinet_name = f"{class_code} — {class_info.get('name', class_code)}"

            r = requests.post(
                f"{SUPA_URL}/rest/v1/file_cabinets",
                headers={**_sb_headers(), "Prefer": "return=representation"},
                json={"id": cabinet_id, "user_id": teacher_pid, "name": cabinet_name},
                params={"on_conflict": "id"},
            )
            if r.status_code in (200, 201):
                print(f"  ✓ Cabinet: {cabinet_name}")
                results["greenfield"]["cabinets"] += 1
            else:
                print(f"  ✗ Cabinet create failed ({class_code}): {r.text[:100]}")
                errors.append(f"cabinet_create: {class_code}")
                continue

            for fi in files_list:
                file_id = str(uuid.uuid4())
                r = requests.post(
                    f"{SUPA_URL}/rest/v1/files",
                    headers={**_sb_headers(), "Prefer": "return=representation"},
                    json={
                        "id": file_id,
                        "cabinet_id": cabinet_id,
                        "name": fi["name"],
                        "path": fi["path"],
                        "bucket": "file-cabinets",
                        "mime_type": fi.get("mime_type"),
                        "size": fi.get("size"),
                        "metadata": {},
                    },
                    params={"on_conflict": "id"},
                )
                if r.status_code in (200, 201):
                    results["greenfield"]["files"] += 1

                    artefact_id = str(uuid.uuid4())
                    requests.post(
                        f"{SUPA_URL}/rest/v1/document_artefacts",
                        headers={**_sb_headers(), "Prefer": "return=representation"},
                        json={
                            "id": artefact_id,
                            "file_id": file_id,
                            "type": fi.get("mime_type", "application/octet-stream").split("/")[-1],
                            "rel_path": fi["path"],
                            "status": "processed",
                            "extra": {"seeded": True, "source": "seed_file_cabinets"},
                        },
                        params={"on_conflict": "id"},
                    )

                time.sleep(0.05)

            for sid in student_ids:
                r = requests.post(
                    f"{SUPA_URL}/rest/v1/cabinet_memberships",
                    headers={**_sb_headers(), "Prefer": "return=minimal"},
                    json={
                        "cabinet_id": cabinet_id,
                        "profile_id": sid,
                        "role": "viewer",
                    },
                    params={"on_conflict": "cabinet_id,profile_id"},
                )
                if r.status_code in (200, 201, 409):
                    results["greenfield"]["memberships"] += 1

            time.sleep(0.1)

        except Exception as e:
            err = f"cabinet seed {class_code}: {e}"
            print(f"  ✗ {err}")
            errors.append(err)

    # ── Summary ─────────────────────────────────────────────────────────────
    print("\n" + "=" * 60)
    results["success"] = len(errors) == 0
    results["errors"] = errors
    total_cabinets = results["kevlarai"]["cabinets"] + results["greenfield"]["cabinets"]
    total_files = results["kevlarai"]["files"] + results["greenfield"]["files"]
    total_memberships = results["kevlarai"]["memberships"] + results["greenfield"]["memberships"]
    print(f"COMPLETE — {total_cabinets} cabinets, {total_files} files, {total_memberships} memberships")
    if errors:
        print(f"Errors ({len(errors)}):")
        for e in errors:
            print(f"  ✗ {e}")
    print("=" * 60)
    return results


if __name__ == "__main__":
    import json
    print(json.dumps(seed(), indent=2, default=str))
