"""CLI for proxagent — check and set up Supabase tables."""

import os
from importlib.resources import files

import click
import httpx
from supabase import create_client


REQUIRED_TABLES = ["_proxagent_agents", "_proxagent_skills", "_proxagent_memories", "_proxagent_runs", "_proxagent_logs"]

MANAGEMENT_API = "https://api.supabase.com"


def _get_pat() -> str:
    """Get Personal Access Token from env or prompt."""
    pat = os.environ.get("SUPABASE_ACCESS_TOKEN")
    if pat:
        click.echo(f"Using access token from env.\n")
        return pat

    return click.prompt(
        "Supabase Personal Access Token (Account > Access Tokens)",
        hide_input=True,
    )


def _api_get(pat: str, path: str):
    """GET request to Supabase Management API."""
    resp = httpx.get(
        f"{MANAGEMENT_API}{path}",
        headers={"Authorization": f"Bearer {pat}"},
        timeout=15,
    )
    if resp.status_code == 401:
        raise click.ClickException("Invalid access token. Check your PAT.")
    if resp.status_code != 200:
        raise click.ClickException(f"API error ({resp.status_code}): {resp.text[:200]}")
    return resp.json()


def _list_projects(pat: str) -> list[dict]:
    """Fetch all Supabase projects."""
    return _api_get(pat, "/v1/projects")


def _get_api_keys(pat: str, project_id: str) -> dict:
    """Fetch API keys for a project. Returns dict with 'anon' and 'service_role'."""
    keys = _api_get(pat, f"/v1/projects/{project_id}/api-keys")
    result = {}
    for k in keys:
        if k.get("name") == "anon":
            result["anon"] = k["api_key"]
        elif k.get("name") == "service_role":
            result["service_role"] = k["api_key"]
    return result


def _run_sql(pat: str, project_id: str, sql: str):
    """Execute SQL via Supabase Management API."""
    resp = httpx.post(
        f"{MANAGEMENT_API}/v1/projects/{project_id}/database/query",
        headers={"Authorization": f"Bearer {pat}"},
        json={"query": sql},
        timeout=30,
    )
    if resp.status_code in (200, 201):
        return True
    raise click.ClickException(f"SQL execution failed ({resp.status_code}): {resp.text[:300]}")


def _select_project(pat: str) -> dict:
    """List projects and let user pick one with arrow keys. Returns {id, name, url}."""
    from simple_term_menu import TerminalMenu

    click.echo("Fetching your projects...\n")
    projects = _list_projects(pat)

    if not projects:
        raise click.ClickException("No projects found for this account.")

    if len(projects) == 1:
        p = projects[0]
        click.echo(f"Only one project: {p.get('name', 'unnamed')}\n")
        project_id = p["id"]
        return {"id": project_id, "name": p.get("name", ""), "url": f"https://{project_id}.supabase.co"}

    labels = [
        f"{p.get('name', 'unnamed')} ({p.get('id', '')}) [{p.get('region', '')}]"
        for p in projects
    ]

    click.echo("Select a project:\n")
    menu = TerminalMenu(labels)
    index = menu.show()

    if index is None:
        raise click.Abort()

    project = projects[index]
    project_id = project["id"]
    return {"id": project_id, "name": project.get("name", ""), "url": f"https://{project_id}.supabase.co"}


def _connect_supabase(url: str, service_role_key: str):
    """Create Supabase client and verify it works."""
    sb = create_client(url, service_role_key)
    try:
        sb.table("_proxagent_agents").select("*").limit(1).execute()
    except Exception as e:
        err = str(e)
        if "401" in err or "Invalid API key" in err:
            raise click.ClickException("Service role key rejected by PostgREST.")
    return sb


def _table_exists(sb, table_name: str) -> bool:
    """Try to query a table. Returns True if it exists, False on missing."""
    try:
        sb.table(table_name).select("*").limit(1).execute()
        return True
    except Exception as e:
        err = str(e)
        if "401" in err or "Invalid API key" in err:
            raise click.ClickException("Invalid API key.")
        if any(s in err.lower() for s in ["404", "relation", "does not exist", "not found", "could not find", "pgrst205"]):
            return False
        raise click.ClickException(f"Unexpected error checking {table_name}: {err}")


def _check_tables(sb) -> list[str]:
    """Return list of missing table names."""
    missing = []
    for table in REQUIRED_TABLES:
        exists = _table_exists(sb, table)
        status = click.style("OK", fg="green") if exists else click.style("MISSING", fg="red")
        click.echo(f"  {table}: {status}")
        if not exists:
            missing.append(table)
    return missing


def _get_schema_sql() -> str:
    return files("proxagent").joinpath("schema.sql").read_text()


@click.group()
def cli():
    """proxagent — manage Supabase tables for Claude Agent SDK agents."""
    pass


@cli.command()
def check():
    """Check if required proxagent tables exist and create them if missing."""
    pat = _get_pat()

    # Pick a project
    project = _select_project(pat)
    project_id = project["id"]
    click.echo(f"Project: {click.style(project['name'], bold=True)} ({project_id})\n")

    # Get service_role key automatically
    click.echo("Fetching API keys...")
    keys = _get_api_keys(pat, project_id)
    service_role_key = keys.get("service_role")
    if not service_role_key:
        raise click.ClickException("Could not find service_role key for this project.")
    click.echo(click.style("Got service_role key.\n", fg="green"))

    # Connect via PostgREST
    click.echo("Connecting to PostgREST...")
    sb = _connect_supabase(project["url"], service_role_key)
    click.echo(click.style("Connected.\n", fg="green"))

    # Check/create loop
    while True:
        click.echo("Checking for proxagent tables...\n")
        missing = _check_tables(sb)
        click.echo()

        if not missing:
            click.echo(click.style("All tables present. You're good to go.", fg="green"))
            return

        click.echo(click.style(f"{len(missing)} table(s) missing.\n", fg="red"))

        from simple_term_menu import TerminalMenu
        actions = ["Create tables now", "Show SQL only", "Recheck"]
        menu = TerminalMenu(actions, title="What do you want to do?")
        choice = menu.show()
        if choice is None:
            raise click.Abort()

        if choice == 0:  # Create
            import time
            schema_sql = _get_schema_sql()
            click.echo("\nCreating tables...")
            _run_sql(pat, project_id, schema_sql)
            click.echo(click.style("Tables created.", fg="green"))
            click.echo("Waiting for PostgREST to refresh schema...")
            time.sleep(3)
            # Reconnect so the client picks up the new schema
            sb = _connect_supabase(project["url"], service_role_key)
            click.echo()

        elif choice == 1:  # Show SQL
            click.echo("\n-- proxagent: required tables")
            click.echo("-- safe to run multiple times (IF NOT EXISTS)\n")
            click.echo(_get_schema_sql())
            click.prompt("\nPress Enter to recheck", default="", show_default=False)

