"""
Demo users initialization — creates the three canonical @kevlarai.com accounts
and links them to the KevlarAI institute in both Supabase and Neo4j.

Idempotent: existing users are reused, stale .edu demo users are removed.
Run via: python3 main.py --mode demo-users
"""
import os
import requests
import time
from typing import Dict, Any
from modules.logger_tool import initialise_logger

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

INSTITUTE_DB = "cc.institutes.6585bf916ae84d72ab54cddf3ba4e648"
INSTITUTE_ID = "6585bf91-6ae8-4d72-ab54-cddf3ba4e648"

DEMO_USERS = [
    {
        "email": "kcar@kevlarai.com",
        "password": "KevlarAI2025!",
        "username": "kcar",
        "full_name": "Kevin Carroll",
        "display_name": "Kevin",
        "user_type": "teacher",
        "role": "school_admin",
    },
    {
        "email": "teacher1@kevlarai.com",
        "password": "Teacher1@KevlarAI!",
        "username": "teacher1.kevlarai",
        "full_name": "Sarah Chen",
        "display_name": "Sarah",
        "user_type": "teacher",
        "role": "teacher",
    },
    {
        "email": "teacher2@kevlarai.com",
        "password": "Teacher2@KevlarAI!",
        "username": "teacher2.kevlarai",
        "full_name": "Marcus Rodriguez",
        "display_name": "Marcus",
        "user_type": "teacher",
        "role": "teacher",
    },
]


def initialize_demo_users() -> Dict[str, Any]:
    """Create/refresh canonical @kevlarai.com demo users."""
    from neo4j import GraphDatabase
    from modules.database.supabase.utils.client import SupabaseServiceRoleClient

    sb_client = SupabaseServiceRoleClient()
    supabase_url = os.environ["SUPABASE_URL"]
    service_key  = os.environ["SERVICE_ROLE_KEY"]
    auth_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=auth_headers, params=params)
        r.raise_for_status()
        return r.json()

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

    def auth_delete(path):
        return requests.delete(f"{supabase_url}/auth/v1/admin{path}", headers=auth_headers)

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

    errors = []

    # ── Step 1: delete stale .edu users ─────────────────────────────────────
    logger.info("Removing stale .edu demo users...")
    try:
        existing = auth_get("/users", params={"per_page": 100}).get("users", [])
        edu_users = [u for u in existing if u.get("email", "").endswith("@kevlarai.edu")]
        for u in edu_users:
            # Try direct delete first
            r = auth_delete(f"/users/{u['id']}")
            if r.status_code not in (200, 204):
                # Profile has dependent rows — clean via SQL
                _purge_profile_rows(supabase_url, service_key, u["id"])
                auth_delete(f"/users/{u['id']}")
            logger.info(f"  Removed: {u['email']}")
    except Exception as e:
        logger.warning(f"  .edu cleanup warning: {e}")

    # ── Step 2: create @kevlarai.com users ───────────────────────────────────
    logger.info("Creating @kevlarai.com demo users...")
    created_users = {}
    for spec in DEMO_USERS:
        email = spec["email"]
        all_users = auth_get("/users", params={"per_page": 100}).get("users", [])
        existing_user = next((u for u in all_users if u.get("email") == email), None)

        if existing_user:
            uid = existing_user["id"]
            logger.info(f"  {email}: already 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"Failed to create {email}: {r.text[:200]}"
            logger.error(f"  {msg}")
            errors.append(msg)
        time.sleep(0.3)

    # ── Step 3: upsert profiles ──────────────────────────────────────────────
    logger.info("Upserting profiles...")
    for spec in DEMO_USERS:
        u = created_users.get(spec["email"])
        if not u:
            continue
        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": INSTITUTE_ID,
            "neo4j_sync_status": "pending",
        }, on_conflict="id")

    # ── Step 4: upsert memberships ───────────────────────────────────────────
    logger.info("Upserting institute memberships...")
    for spec in DEMO_USERS:
        u = created_users.get(spec["email"])
        if not u:
            continue
        sb_upsert("institute_memberships", {
            "profile_id": u["id"],
            "institute_id": INSTITUTE_ID,
            "role": spec["role"],
        }, on_conflict="profile_id,institute_id")

    # ── Step 5: Teacher nodes in Neo4j ───────────────────────────────────────
    logger.info("Creating Neo4j Teacher nodes...")
    try:
        driver = GraphDatabase.driver("bolt://192.168.0.209:7687", auth=("neo4j", "&%N304j&%"))
        new_emails = {spec["email"] for spec in DEMO_USERS}
        with driver.session(database=INSTITUTE_DB) as s:
            # Remove stale Teacher nodes
            stale = s.run("MATCH (t:Teacher) WHERE NOT t.worker_email IN $emails RETURN t.worker_email as e, t.uuid_string as u", emails=list(new_emails)).data()
            for t in stale:
                s.run("MATCH (t:Teacher {uuid_string: $u}) DETACH DELETE t", u=t["u"])
                logger.info(f"  Removed stale Teacher: {t['e']}")
            # Remove duplicate Teacher nodes (same email, different UUID)
            for spec in DEMO_USERS:
                u = created_users.get(spec["email"])
                if not u:
                    continue
                dupes = s.run("MATCH (t:Teacher {worker_email: $e}) WHERE t.uuid_string <> $u RETURN t.uuid_string as uid", e=spec["email"], u=u["id"]).data()
                for d in dupes:
                    s.run("MATCH (t:Teacher {uuid_string: $u}) DETACH DELETE t", u=d["uid"])
                    logger.info(f"  Removed duplicate Teacher UUID {d['uid'][:8]} for {spec['email']}")
            # Upsert Teacher nodes
            for spec in DEMO_USERS:
                u = created_users.get(spec["email"])
                if not u:
                    continue
                s.run("""
                    MERGE (t:Teacher {uuid_string: $uuid})
                    SET t.worker_email = $email,
                        t.worker_name = $name,
                        t.unique_id = $uid,
                        t.user_type = 'teacher',
                        t.worker_type = 'teacher'
                """, uuid=u["id"], email=spec["email"], name=spec["full_name"], uid=u["id"])
                logger.info(f"  Teacher node: {spec['email']} [{u['id'][:8]}]")
        driver.close()
    except Exception as e:
        msg = f"Neo4j Teacher node setup failed: {e}"
        logger.error(msg)
        errors.append(msg)

    return {
        "success": len(errors) == 0,
        "created": list(created_users.keys()),
        "errors": errors,
        "message": "Demo users initialized" if not errors else f"{len(errors)} errors: {errors[0]}",
    }


def _purge_profile_rows(supabase_url: str, service_key: str, profile_id: str) -> None:
    """Delete all rows referencing a profile before deleting the auth user."""
    hdrs = {"apikey": service_key, "Authorization": f"Bearer {service_key}"}
    for table, col in [("files", "uploaded_by"), ("whiteboard_rooms", "user_id"),
                       ("cabinet_memberships", "profile_id"), ("institute_memberships", "profile_id")]:
        requests.delete(f"{supabase_url}/rest/v1/{table}?{col}=eq.{profile_id}", headers=hdrs)
