#!/usr/bin/env python3
"""
GHL OAuth Setup & Management CLI

Usage:
    # Initialize database schema
    python3 GHL/oauth/setup.py --init-db

    # Start OAuth flow (prints URL to open in browser)
    python3 GHL/oauth/setup.py --init-flow

    # Handle callback (after approving in browser)
    python3 GHL/oauth/setup.py --callback --code CODE --state STATE

    # Exchange agency token for all location tokens
    python3 GHL/oauth/setup.py --exchange-all

    # Exchange for a specific location
    python3 GHL/oauth/setup.py --exchange --location-id 7UExU3gWmZqJEKbAeAq4

    # Check token status
    python3 GHL/oauth/setup.py --status

    # Test location access
    python3 GHL/oauth/setup.py --test --location-id 7UExU3gWmZqJEKbAeAq4

    # Full setup (init db + start flow)
    python3 GHL/oauth/setup.py --full-setup

    # Standalone callback server (runs on port 8099)
    python3 GHL/oauth/setup.py --serve
"""

import sys
import json
import argparse
import logging

sys.path.append("/mnt/e/genesis-system/data/genesis-memory")
sys.path.append("/mnt/e/genesis-system")

logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
logger = logging.getLogger(__name__)


def cmd_init_db():
    from GHL.oauth.token_vault import TokenVault
    vault = TokenVault()
    vault.init_schema()
    print("Database schema initialized.")


def cmd_init_flow():
    from GHL.oauth.oauth_flow import OAuthFlowManager
    flow = OAuthFlowManager()
    result = flow.initiate()

    if result.get("error"):
        print(f"ERROR: {result['error']}")
        print("\nTo configure:")
        print("  1. Register at marketplace.gohighlevel.com")
        print("  2. Create a Custom/Private App")
        print("  3. Set env vars: GHL_OAUTH_CLIENT_ID, GHL_OAUTH_CLIENT_SECRET")
        return

    print("\n=== GHL OAuth Flow Initiated ===")
    print(f"\nOpen this URL in your browser:\n")
    print(f"  {result['auth_url']}")
    print(f"\nState token: {result['state']}")
    print(f"\nAfter approving, you'll be redirected to the callback URL.")
    print(f"If the callback server isn't running, copy the 'code' and 'state'")
    print(f"from the redirect URL and run:")
    print(f"\n  python3 GHL/oauth/setup.py --callback --code CODE --state STATE")


def cmd_callback(code: str, state: str):
    from GHL.oauth.oauth_flow import OAuthFlowManager
    flow = OAuthFlowManager()
    result = flow.handle_callback(code, state)

    if result.get("error"):
        print(f"ERROR: {result['error']}")
        if result.get("details"):
            print(f"Details: {result['details']}")
        return

    print("\n=== OAuth Callback Success ===")
    print(f"Token ID: {result['token_id']}")
    print(f"User Type: {result['user_type']}")
    print(f"Company ID: {result['company_id']}")
    print(f"Expires In: {result['expires_in']}s")
    print(f"Scopes: {result['scope_count']}")
    print(f"\nNext: Run --exchange-all to get per-location tokens")


def cmd_exchange_all():
    from GHL.oauth.oauth_flow import OAuthFlowManager
    flow = OAuthFlowManager()
    result = flow.exchange_all_locations()

    if result.get("error"):
        print(f"ERROR: {result['error']}")
        return

    print(f"\n=== Location Token Exchange ===")
    print(f"Total locations: {result['locations_total']}")
    print(f"Successfully exchanged: {result['locations_exchanged']}")
    print()

    for loc_id, info in result.get("results", {}).items():
        status = "OK" if info["success"] else "FAILED"
        print(f"  [{status}] {info['name']} ({loc_id})")
        if info.get("expires_at"):
            print(f"         Expires: {info['expires_at']}")


def cmd_exchange(location_id: str):
    from GHL.oauth.token_vault import TokenVault
    vault = TokenVault()
    token = vault.exchange_location_token(location_id, location_name="")
    if token:
        print(f"Token exchanged for {location_id}")
        print(f"Expires: {token.expires_at.isoformat()}")
    else:
        print(f"FAILED to exchange token for {location_id}")


def cmd_status():
    from GHL.oauth.token_vault import TokenVault
    vault = TokenVault()
    status = vault.status()

    print(f"\n=== GHL OAuth Token Status ===")
    print(f"Total active tokens: {status['total']}")
    print()

    for t in status["tokens"]:
        type_badge = "AGENCY" if t["type"] == "agency" else "LOCATION"
        status_badge = "VALID" if t["status"] == "valid" else "EXPIRED"
        name = t.get("location_name") or "(agency)"
        print(f"  [{type_badge}] [{status_badge}] {name}")
        if t.get("location_id"):
            print(f"           ID: {t['location_id']}")
        print(f"           Expires: {t['expires_at']}")
        if t.get("last_used"):
            print(f"           Last used: {t['last_used']}")
        print()


def cmd_test(location_id: str):
    from GHL.oauth.ghl_client import GHLClient
    client = GHLClient()
    result = client.test_location_access(location_id)

    print(f"\n=== Access Test: {location_id} ===")
    all_pass = result.get("all_pass", False)
    print(f"Overall: {'ALL PASS' if all_pass else 'SOME FAILED'}")
    print()

    for name, test in result.get("tests", {}).items():
        status = "OK" if test["ok"] else "FAIL"
        print(f"  [{status}] {name}: HTTP {test.get('status_code')}")


def cmd_serve():
    """Run a minimal callback server on port 8099."""
    try:
        from fastapi import FastAPI, Request
        from fastapi.responses import HTMLResponse
        import uvicorn
    except ImportError:
        print("FastAPI/uvicorn not installed. Install with: pip install fastapi uvicorn")
        return

    app = FastAPI(title="GHL OAuth Callback Server")

    @app.get("/api/ghl/oauth/callback")
    async def oauth_callback(code: str, state: str):
        from GHL.oauth.oauth_flow import OAuthFlowManager
        flow = OAuthFlowManager()
        result = flow.handle_callback(code, state)

        if result.get("error"):
            return HTMLResponse(f"<h1>Error</h1><pre>{json.dumps(result, indent=2)}</pre>", status_code=400)

        return HTMLResponse(f"""
            <h1>GHL OAuth Success!</h1>
            <pre>{json.dumps(result, indent=2)}</pre>
            <p>Now run: <code>python3 GHL/oauth/setup.py --exchange-all</code></p>
        """)

    @app.get("/api/ghl/oauth/status")
    async def token_status():
        from GHL.oauth.token_vault import TokenVault
        vault = TokenVault()
        return vault.status()

    print("Starting GHL OAuth callback server on port 8099...")
    print("Callback URL: http://localhost:8099/api/ghl/oauth/callback")
    uvicorn.run(app, host="0.0.0.0", port=8099)


def cmd_full_setup():
    print("=== GHL OAuth Full Setup ===\n")
    print("Step 1: Initialize database...")
    cmd_init_db()
    print("\nStep 2: Start OAuth flow...")
    cmd_init_flow()


def main():
    parser = argparse.ArgumentParser(description="GHL OAuth Setup & Management")
    parser.add_argument("--init-db", action="store_true", help="Initialize database schema")
    parser.add_argument("--init-flow", action="store_true", help="Start OAuth flow")
    parser.add_argument("--callback", action="store_true", help="Handle OAuth callback")
    parser.add_argument("--code", help="Authorization code from callback")
    parser.add_argument("--state", help="State token from callback")
    parser.add_argument("--exchange-all", action="store_true", help="Exchange for all location tokens")
    parser.add_argument("--exchange", action="store_true", help="Exchange for a specific location")
    parser.add_argument("--location-id", help="Location ID for exchange/test")
    parser.add_argument("--status", action="store_true", help="Show token status")
    parser.add_argument("--test", action="store_true", help="Test location access")
    parser.add_argument("--full-setup", action="store_true", help="Full setup (init + flow)")
    parser.add_argument("--serve", action="store_true", help="Run callback server")

    args = parser.parse_args()

    if args.init_db:
        cmd_init_db()
    elif args.init_flow:
        cmd_init_flow()
    elif args.callback:
        if not args.code or not args.state:
            print("ERROR: --callback requires --code and --state")
            return
        cmd_callback(args.code, args.state)
    elif args.exchange_all:
        cmd_exchange_all()
    elif args.exchange:
        if not args.location_id:
            print("ERROR: --exchange requires --location-id")
            return
        cmd_exchange(args.location_id)
    elif args.status:
        cmd_status()
    elif args.test:
        if not args.location_id:
            print("ERROR: --test requires --location-id")
            return
        cmd_test(args.location_id)
    elif args.full_setup:
        cmd_full_setup()
    elif args.serve:
        cmd_serve()
    else:
        parser.print_help()


if __name__ == "__main__":
    main()
