"""
Seed Test Environment — idempotent full-environment setup for CC development.

Creates:
  - kcar@kevlarai.com       → platform super-admin (admin_profiles)
  - KevlarAI school         → already exists; adds 3 student users
  - Greenfield Academy      → new second school with full staff + students

Run inside ccapi container:
    python3 main.py --mode seed-test

Or directly:
    cd ~/api && python3 -c "
    from run.initialization.seed_test_environment import seed_test_environment
    import json; print(json.dumps(seed_test_environment(), indent=2))
    "
"""
import os
import time
import requests
import uuid
from typing import Dict, Any, Optional, List
from modules.logger_tool import initialise_logger

logger = initialise_logger(__name__, os.getenv("LOG_LEVEL"), os.getenv("LOG_PATH"), "default", True)

# ─── Existing KevlarAI school ────────────────────────────────────────────────
KEVLARAI_INSTITUTE_ID   = "6585bf91-6ae8-4d72-ab54-cddf3ba4e648"
KEVLARAI_INSTITUTE_DB   = "cc.institutes.6585bf916ae84d72ab54cddf3ba4e648"

# ─── Second test school ──────────────────────────────────────────────────────
GREENFIELD_INSTITUTE_ID = "a1b2c3d4-e5f6-7890-abcd-ef1234567890"  # deterministic UUID
GREENFIELD_URN          = "TEST-GFA-001"
GREENFIELD_NAME         = "Greenfield Academy"

# ─── User definitions ────────────────────────────────────────────────────────
# Format: email, password, username, full_name, display_name, user_type, role, institute_id
TEST_USERS: List[Dict] = [
    # ── KevlarAI students ────────────────────────────────────────────────────
    {
        "email": "student1@kevlarai.com",
        "password": "Student1@KevlarAI!",
        "username": "student1.kevlarai",
        "full_name": "Alice Nguyen",
        "display_name": "Alice",
        "user_type": "student",
        "role": "student",
        "institute_id": KEVLARAI_INSTITUTE_ID,
        "institute_db": KEVLARAI_INSTITUTE_DB,
        "metadata": {"year_group": "Year 10"},
    },
    {
        "email": "student2@kevlarai.com",
        "password": "Student2@KevlarAI!",
        "username": "student2.kevlarai",
        "full_name": "Ben Okafor",
        "display_name": "Ben",
        "user_type": "student",
        "role": "student",
        "institute_id": KEVLARAI_INSTITUTE_ID,
        "institute_db": KEVLARAI_INSTITUTE_DB,
        "metadata": {"year_group": "Year 10"},
    },
    {
        "email": "student3@kevlarai.com",
        "password": "Student3@KevlarAI!",
        "username": "student3.kevlarai",
        "full_name": "Chloe Park",
        "display_name": "Chloe",
        "user_type": "student",
        "role": "student",
        "institute_id": KEVLARAI_INSTITUTE_ID,
        "institute_db": KEVLARAI_INSTITUTE_DB,
        "metadata": {"year_group": "Year 11"},
    },
    # ── Greenfield Academy admin ─────────────────────────────────────────────
    {
        "email": "head@greenfieldacademy.test",
        "password": "Admin@Greenfield1!",
        "username": "head.greenfield",
        "full_name": "Dr James Whitmore",
        "display_name": "Dr Whitmore",
        "user_type": "teacher",
        "role": "school_admin",
        "institute_id": GREENFIELD_INSTITUTE_ID,
        "institute_db": None,  # populated after school provisioning
        "metadata": {},
    },
    # ── Greenfield teachers ──────────────────────────────────────────────────
    {
        "email": "physics@greenfieldacademy.test",
        "password": "Teacher1@Greenfield1!",
        "username": "physics.greenfield",
        "full_name": "Priya Sharma",
        "display_name": "Priya",
        "user_type": "teacher",
        "role": "teacher",
        "institute_id": GREENFIELD_INSTITUTE_ID,
        "institute_db": None,
        "metadata": {"subject": "Physics"},
    },
    {
        "email": "english@greenfieldacademy.test",
        "password": "Teacher2@Greenfield1!",
        "username": "english.greenfield",
        "full_name": "Tom Bradley",
        "display_name": "Tom",
        "user_type": "teacher",
        "role": "teacher",
        "institute_id": GREENFIELD_INSTITUTE_ID,
        "institute_db": None,
        "metadata": {"subject": "English"},
    },
    # ── Greenfield students ──────────────────────────────────────────────────
    {
        "email": "alice@greenfieldacademy.test",
        "password": "Student1@Greenfield1!",
        "username": "alice.greenfield",
        "full_name": "Alice Thornton",
        "display_name": "Alice T",
        "user_type": "student",
        "role": "student",
        "institute_id": GREENFIELD_INSTITUTE_ID,
        "institute_db": None,
        "metadata": {"year_group": "Year 9"},
    },
    {
        "email": "bob@greenfieldacademy.test",
        "password": "Student2@Greenfield1!",
        "username": "bob.greenfield",
        "full_name": "Bob Ivanov",
        "display_name": "Bob",
        "user_type": "student",
        "role": "student",
        "institute_id": GREENFIELD_INSTITUTE_ID,
        "institute_db": None,
        "metadata": {"year_group": "Year 9"},
    },
    {
        "email": "carol@greenfieldacademy.test",
        "password": "Student3@Greenfield1!",
        "username": "carol.greenfield",
        "full_name": "Carol Mensah",
        "display_name": "Carol",
        "user_type": "student",
        "role": "student",
        "institute_id": GREENFIELD_INSTITUTE_ID,
        "institute_db": None,
        "metadata": {"year_group": "Year 10"},
    },
]


def seed_test_environment() -> Dict[str, Any]:
    from modules.database.supabase.utils.client import SupabaseServiceRoleClient
    from modules.database.services.provisioning_service import ProvisioningService

    sb_client = SupabaseServiceRoleClient()
    supabase_url = os.environ["SUPABASE_URL"]
    service_key  = os.environ["SERVICE_ROLE_KEY"]

    headers = {
        "apikey": service_key,
        "Authorization": f"Bearer {service_key}",
        "Content-Type": "application/json",
    }

    def auth_get(path, params=None):
        r = requests.get(f"{supabase_url}/auth/v1/admin{path}", headers=headers, params=params)
        r.raise_for_status()
        return r.json()

    def auth_post(path, data):
        r = requests.post(f"{supabase_url}/auth/v1/admin{path}", headers=headers, json=data)
        return r

    def sb_upsert(table, data, on_conflict):
        h = {**headers, "Prefer": "resolution=merge-duplicates,return=representation"}
        r = requests.post(
            f"{supabase_url}/rest/v1/{table}",
            headers=h,
            json=data,
            params={"on_conflict": on_conflict},
        )
        return r

    def sb_select(table, eq_col, eq_val):
        r = requests.get(
            f"{supabase_url}/rest/v1/{table}",
            headers=headers,
            params={"select": "*", eq_col: f"eq.{eq_val}"},
        )
        r.raise_for_status()
        return r.json()

    errors: List[str] = []
    results: Dict[str, Any] = {"steps": {}}

    # ── Step 1: Ensure kcar is a platform super-admin ─────────────────────────
    logger.info("Step 1: Platform super-admin setup...")
    try:
        kcar_id = "d9e1d1a9-04c4-4611-bb05-57babf4a9a28"  # known from profiles
        r = sb_upsert("admin_profiles", {
            "id":             kcar_id,
            "email":          "kcar@kevlarai.com",
            "display_name":   "Kevin Carroll",
            "admin_role":     "super_admin",
            "is_super_admin": True,
            "metadata":       {"seeded": True},
        }, on_conflict="id")
        if r.status_code in (200, 201):
            logger.info("  kcar → admin_profiles super_admin ✓")
            results["steps"]["super_admin"] = "ok"
        else:
            raise Exception(f"Upsert failed: {r.text[:200]}")
    except Exception as e:
        msg = f"super_admin setup: {e}"
        logger.error(f"  {msg}")
        errors.append(msg)
        results["steps"]["super_admin"] = "error"

    # ── Step 2: Provision Greenfield Academy ──────────────────────────────────
    logger.info("Step 2: Greenfield Academy school provisioning...")
    greenfield_db = None
    try:
        # Check if already exists
        existing = sb_select("institutes", "id", GREENFIELD_INSTITUTE_ID)
        if not existing:
            # Determine neo4j_uuid_string (same sanitization as provisioning_service)
            neo4j_uuid = GREENFIELD_INSTITUTE_ID.replace("-", "")
            r = sb_upsert("institutes", {
                "id":              GREENFIELD_INSTITUTE_ID,
                "name":            GREENFIELD_NAME,
                "urn":             GREENFIELD_URN,
                "status":          "active",
                "address":         {"line1": "1 Academy Road", "city": "Testville", "postcode": "TE1 1ST"},
                "website":         "https://greenfieldacademy.test",
                "metadata":        {"headteacher": "Dr James Whitmore", "seeded": True},
                "neo4j_uuid_string": neo4j_uuid,
            }, on_conflict="id")
            if r.status_code not in (200, 201):
                raise Exception(f"Institute upsert: {r.text[:200]}")
            logger.info(f"  Greenfield Academy created [{GREENFIELD_INSTITUTE_ID[:8]}]")

            # Provision Neo4j DB
            provisioner = ProvisioningService()
            prov_result = provisioner.ensure_school(GREENFIELD_INSTITUTE_ID)
            greenfield_db = prov_result.get("db_name")
            logger.info(f"  Neo4j DB provisioned: {greenfield_db}")
        else:
            neo4j_uuid = existing[0].get("neo4j_uuid_string") or GREENFIELD_INSTITUTE_ID.replace("-", "")
            greenfield_db = f"cc.institutes.{neo4j_uuid}"
            logger.info(f"  Greenfield Academy already exists → {greenfield_db}")

        results["steps"]["greenfield_school"] = greenfield_db
    except Exception as e:
        msg = f"greenfield_school: {e}"
        logger.error(f"  {msg}")
        errors.append(msg)
        results["steps"]["greenfield_school"] = "error"
        greenfield_db = f"cc.institutes.{GREENFIELD_INSTITUTE_ID.replace('-', '')}"

    # Update institute_db for Greenfield users
    for u in TEST_USERS:
        if u["institute_id"] == GREENFIELD_INSTITUTE_ID:
            u["institute_db"] = greenfield_db

    # ── Step 3: Create / verify all test users ────────────────────────────────
    logger.info("Step 3: Creating test users...")
    created_users: Dict[str, Dict] = {}
    try:
        all_users = auth_get("/users", params={"per_page": 200}).get("users", [])
        existing_by_email = {u["email"]: u for u in all_users}
    except Exception as e:
        msg = f"auth/users list: {e}"
        logger.error(msg)
        errors.append(msg)
        existing_by_email = {}

    for spec in TEST_USERS:
        email = spec["email"]
        if email in existing_by_email:
            uid = existing_by_email[email]["id"]
            logger.info(f"  {email}: exists [{uid[:8]}]")
            created_users[email] = {"id": uid, **spec}
            continue

        r = auth_post("/users", {
            "email":         email,
            "password":      spec["password"],
            "email_confirm": True,
            "user_metadata": {
                "username":     spec["username"],
                "full_name":    spec["full_name"],
                "display_name": spec["display_name"],
                "user_type":    spec["user_type"],
            },
        })
        if r.status_code in (200, 201):
            uid = r.json()["id"]
            logger.info(f"  {email}: created [{uid[:8]}]")
            created_users[email] = {"id": uid, **spec}
        else:
            msg = f"create {email}: {r.text[:200]}"
            logger.error(f"  {msg}")
            errors.append(msg)
        time.sleep(0.25)

    results["steps"]["users_created"] = list(created_users.keys())

    # ── Step 4: Upsert profiles + memberships ─────────────────────────────────
    logger.info("Step 4: Upserting profiles and memberships...")
    for spec in TEST_USERS:
        u = created_users.get(spec["email"])
        if not u:
            continue
        try:
            sb_upsert("profiles", {
                "id":           u["id"],
                "email":        spec["email"],
                "user_type":    spec["user_type"],
                "username":     spec["username"],
                "full_name":    spec["full_name"],
                "display_name": spec["display_name"],
                "school_id":    spec["institute_id"],
                "neo4j_sync_status": "pending",
            }, on_conflict="id")

            sb_upsert("institute_memberships", {
                "profile_id":   u["id"],
                "institute_id": spec["institute_id"],
                "role":         spec["role"],
                "metadata":     spec.get("metadata", {}),
            }, on_conflict="profile_id,institute_id")
        except Exception as e:
            msg = f"profile/membership {spec['email']}: {e}"
            logger.error(f"  {msg}")
            errors.append(msg)

    results["steps"]["profiles_memberships"] = "ok"

    # ── Step 5: Neo4j Teacher/Student nodes for all users ────────────────────
    logger.info("Step 5: Creating Neo4j worker nodes...")
    try:
        from neo4j import GraphDatabase
        driver = GraphDatabase.driver("bolt://192.168.0.209:7687", auth=("neo4j", "&%N304j&%"))

        # Group users by institute DB
        by_db: Dict[str, List[Dict]] = {}
        for spec in TEST_USERS:
            u = created_users.get(spec["email"])
            if not u or not spec.get("institute_db"):
                continue
            by_db.setdefault(spec["institute_db"], []).append({**spec, "uid": u["id"]})

        for db, users in by_db.items():
            with driver.session(database=db) as s:
                for u in users:
                    label = "Teacher" if u["user_type"] == "teacher" else "Student"
                    s.run(
                        f"MERGE (n:{label} {{uuid_string: $uid}}) "
                        "SET n.worker_email = $email, "
                        "    n.worker_name  = $name, "
                        "    n.unique_id    = $uid, "
                        "    n.user_type    = $user_type, "
                        "    n.worker_type  = $user_type",
                        uid=u["uid"], email=u["email"],
                        name=u["full_name"], user_type=u["user_type"],
                    )
                    logger.info(f"  [{db[:30]}] {label}: {u['email']}")

        driver.close()
        results["steps"]["neo4j_nodes"] = "ok"
    except Exception as e:
        msg = f"neo4j_nodes: {e}"
        logger.error(f"  {msg}")
        errors.append(msg)
        results["steps"]["neo4j_nodes"] = "error"

    # ── Summary ───────────────────────────────────────────────────────────────
    results["success"] = len(errors) == 0
    results["errors"]  = errors
    results["message"] = (
        f"Seed complete — {len(created_users)} users across 2 schools"
        if not errors
        else f"{len(errors)} error(s): {errors[0]}"
    )

    # Print credential sheet
    logger.info("\n" + "=" * 60)
    logger.info("TEST CREDENTIAL SHEET")
    logger.info("=" * 60)
    logger.info(f"{'ROLE':<20} {'EMAIL':<40} {'PASSWORD'}")
    logger.info("-" * 90)
    logger.info(f"{'[PLATFORM ADMIN]':<20} {'kcar@kevlarai.com':<40} KevlarAI2025!")
    logger.info("-" * 90)
    logger.info(f"[KevlarAI School]")
    for spec in TEST_USERS:
        if spec["institute_id"] == KEVLARAI_INSTITUTE_ID:
            logger.info(f"  {spec['role']:<18} {spec['email']:<40} {spec['password']}")
    logger.info("-" * 90)
    logger.info(f"[Greenfield Academy]")
    for spec in TEST_USERS:
        if spec["institute_id"] == GREENFIELD_INSTITUTE_ID:
            logger.info(f"  {spec['role']:<18} {spec['email']:<40} {spec['password']}")
    logger.info("=" * 60)

    return results
