# version: v3
"""
================================================================================
Quantum Terminal Consumer — Startup Gate & Route Wiring
================================================================================
v3 — consumer_gate() now accepts `skip_sync=False`. data_server's lifespan
     calls it with `skip_sync=True` so the auth phase runs synchronously
     (needed for login routing) while the slow sync_all() is kicked off in
     a background thread after lifespan returns. HTTP routes become
     available immediately; frontend polls /api/sync/status for the SYNCING
     pill. Eliminates the "15-minute loading screen" symptom caused by
     persistent 5xx responses on specific data endpoints.

v2 — Wire /api/version (version_info.py) so the app can report its running
     version and check for updates via /api/version endpoint.
Bridges the consumer-specific modules (data_sync_client)
into the existing data_server.py with MINIMAL changes to the PRO codebase.

Usage in data_server.py lifespan:
    from consumer_startup import consumer_gate, wire_consumer_routes

    # In lifespan, BEFORE provider connect:
    gate_result = consumer_gate()
    if not gate_result["ok"]:
        # Terminal won't render — gate_result has details
        pass

    # After app creation:
    wire_consumer_routes(app)

This module does NOT introduce any calculation triggers.
================================================================================
"""

import logging
from typing import Optional

log = logging.getLogger("mk.consumer_startup")


# ============================================================
# 1. CONSUMER STARTUP GATE (Rule C2)
# ============================================================

def consumer_gate(skip_sync: bool = False) -> dict:
    """
    Run the consumer startup gate (Rule C2).

    Three conditions must be met before terminal renders:
        1. Auth always passes (Quantum Terminal is free)
        2. data_sync_client completes download OR loads from cache
        3. MT5 connection established (handled by existing data_server code)

    This function handles conditions 1 and 2.

    v3: when `skip_sync=True`, only the auth phase runs (fast). Caller is
        responsible for running sync in a background thread so the FastAPI
        lifespan isn't blocked by a slow/unhealthy server. `sync_summary`
        will be returned as {"in_progress": True} in that case — populate it
        from the thread when sync completes.
    Returns dict with gate status:
        {
            "ok": bool,
            "auth_result": AuthResult dict,
            "sync_summary": dict,
            "needs_login": bool,
            "needs_update": bool,
            "offline_mode": bool,
        }
    """
    result = {
        "ok": False,
        "auth_result": None,
        "sync_summary": None,
        "needs_login": False,
        "needs_update": False,
        "offline_mode": False,
    }

    # ── Gate 1: Auth validation ──
    # Removed in Quantum Terminal: Always authenticated
    result["auth_result"] = {"status": "ok", "message": "Quantum Terminal - Free Edition"}
    result["needs_login"] = False

    # ── Gate 2: Data sync ──
    # v3: skip_sync=True → lifespan will run sync_all() in a background
    #   thread instead, so the HTTP server is responsive immediately.
    if skip_sync:
        result["sync_summary"] = {"in_progress": True}
    else:
        try:
            from data_sync_client import get_sync_client
            sync_client = get_sync_client()
            sync_summary = sync_client.sync_all()
            result["sync_summary"] = sync_summary

            # Rule C6: format version mismatch blocks terminal
            if not sync_summary.get("format_version_ok", True):
                log.error("Startup gate: FORMAT VERSION MISMATCH — update required")
                result["needs_update"] = True
                result["ok"] = False
                return result

            if sync_summary.get("offline_mode", False):
                result["offline_mode"] = True

        except ImportError:
            log.warning("data_sync_client not available — skipping data sync (dev mode)")
            result["sync_summary"] = {"note": "dev mode — no sync"}
        except Exception as e:
            log.error(f"Data sync error: {e}")
            result["sync_summary"] = {"error": str(e)}

    result["ok"] = True
    log.info("Consumer startup gate PASSED")
    return result


# ============================================================
# 2. ROUTE WIRING
# ============================================================

def wire_consumer_routes(app):
    """
    Wire consumer-specific FastAPI routes into the existing app.
    Call this AFTER app = FastAPI() in data_server.py.

    Adds:
        /api/auth/*       — login, register, logout, status, refresh
        /api/sync/*       — sync status, cone/options data, staleness, refresh
        /api/consumer/*   — consumer-specific status endpoints
    """
    routes_added = []

    # Auth routes
    # Removed in Quantum Terminal

    # Data sync routes
    try:
        from data_sync_client import create_data_sync_routes
        app.include_router(create_data_sync_routes())
        routes_added.append("data_sync")
        log.info("Consumer data sync routes wired: /api/sync/*")
    except ImportError:
        log.warning("data_sync_client not available — sync routes not wired")
    except Exception as e:
        log.error(f"Failed to wire data sync routes: {e}")

    # v2: version/update-check route
    try:
        from version_info import create_version_router, CURRENT_VERSION
        app.include_router(create_version_router())
        routes_added.append("version")
        log.info(f"Consumer version route wired: /api/version (running v{CURRENT_VERSION})")
    except ImportError:
        log.warning("version_info not available — /api/version not wired")
    except Exception as e:
        log.error(f"Failed to wire version route: {e}")

    # Consumer status endpoint
    from fastapi import APIRouter
    consumer_router = APIRouter(tags=["consumer"])

    @consumer_router.get("/api/consumer/status")
    async def consumer_status():
        """Consumer terminal status — used by frontend to decide what to show."""
        status = {
            "is_consumer": True,
            "routes_available": routes_added,
        }

        # Auth status
        status["authenticated"] = True
        status["user_email"] = "free@quantumterminal"
        status["subscription_status"] = "active"

        # Sync status
        try:
            from data_sync_client import get_sync_client
            sc = get_sync_client()
            status["synced_tickers"] = sc.synced_tickers
            status["offline_mode"] = sc.is_offline
            status["format_version_ok"] = sc.format_version_ok
            status["sync_in_progress"] = sc.is_syncing   # drives the top-bar pill
            status["last_synced_at"] = sc.last_synced_at

            staleness = sc.get_overall_staleness()
            status["analysis_date"] = staleness.display_date
            status["staleness_level"] = staleness.level.value
        except Exception:
            status["synced_tickers"] = []
            status["offline_mode"] = True
            status["sync_in_progress"] = False

        return status

    @consumer_router.post("/api/consumer/restart")
    async def consumer_restart():
        """
        Restart the terminal backend process. Spawns a fresh instance and
        exits the current one after a brief delay so the HTTP response can
        flush before the process exits.

        Rule C1 compliance: this restarts the display server only — no
        calculation modules are involved.
        """
        import sys, os, subprocess, threading
        import time as _time

        def _do_restart():
            _time.sleep(1.0)
            try:
                creationflags = 0
                if os.name == "nt":
                    creationflags = getattr(subprocess, "DETACHED_PROCESS", 0) | \
                                    getattr(subprocess, "CREATE_NEW_PROCESS_GROUP", 0)
                subprocess.Popen(
                    [sys.executable] + sys.argv,
                    close_fds=True,
                    creationflags=creationflags,
                )
            except Exception as e:
                log.error(f"Restart spawn failed: {e}")
            os._exit(0)

        threading.Thread(target=_do_restart, daemon=True).start()
        log.warning("Consumer restart requested via /api/consumer/restart")
        return {"status": "restarting", "delay_ms": 1000}

    app.include_router(consumer_router)
    log.info("Consumer status route wired: /api/consumer/status")

    return routes_added


# ============================================================
# 3. BLOCKED ENDPOINTS (Rule C1)
# ============================================================

# These endpoint prefixes must NEVER exist in the consumer terminal.
# consumer_verify.py test script checks for them.
BLOCKED_ENDPOINT_PREFIXES = [
    "/api/calculate",
    "/api/calibrate",
    "/api/calibration/run",
    "/api/run-backtest",
    "/api/wf/run",
    "/api/flow/calibrate",
    "/api/anchor/calibrate",
    "/api/dev/clear-cache",   # calc target clears calculation data
]
