"""FastAPI web console server."""

from pathlib import Path
from typing import TYPE_CHECKING

from paracord.core.project_registry import list_projects
from paracord.console.scanner import get_port_status, PortStatus
from paracord.console.tunnel import generate_tunnel_config, get_tunnel_instructions
from paracord.auth.config import ProjectInfo

if TYPE_CHECKING:
    from fastapi import FastAPI
    from fastapi.responses import HTMLResponse


def check_console_deps() -> tuple[bool, str | None]:
    """Check if console dependencies are available.

    Returns:
        Tuple of (available, error_message)
    """
    try:
        import fastapi  # noqa: F401
        import jinja2  # noqa: F401

        return True, None
    except ImportError as e:
        missing = str(e).split("'")[1] if "'" in str(e) else "fastapi or jinja2"
        return False, f"Missing dependency: {missing}. Install with: pip install paracord[console]"


def create_app() -> "FastAPI":
    """Create and configure the FastAPI application.

    Returns:
        Configured FastAPI app

    Raises:
        ImportError: If console dependencies are not installed
    """
    available, error = check_console_deps()
    if not available:
        raise ImportError(error)

    from fastapi import FastAPI, Request
    from fastapi.responses import HTMLResponse
    from fastapi.templating import Jinja2Templates

    app = FastAPI(
        title="Paracord Console",
        description="Local project management console",
    )

    # Set up templates
    templates_dir = Path(__file__).parent / "templates"
    templates = Jinja2Templates(directory=str(templates_dir))

    @app.get("/", response_class=HTMLResponse)
    async def console_home(request: Request):
        """Main console page showing all projects."""
        projects = list_projects()
        project_data = []

        for path, project in projects.items():
            port = project.get("port", 8000)
            status = get_port_status(port)

            project_data.append({
                "path": path,
                "name": project.get("name", Path(path).name),
                "port": port,
                "status": status,
                "cloudflare": project.get("cloudflare", {}),
                "template_source": project.get("template_source", ""),
                "registered_at": project.get("registered_at", ""),
            })

        return templates.TemplateResponse(
            "console.html",
            {
                "request": request,
                "projects": project_data,
                "project_count": len(project_data),
            },
        )

    @app.get("/api/projects")
    async def api_projects():
        """API endpoint for project list with status."""
        projects = list_projects()
        result = []

        for path, project in projects.items():
            port = project.get("port", 8000)
            status = get_port_status(port)

            result.append({
                "path": path,
                "name": project.get("name", Path(path).name),
                "port": port,
                "is_running": status.is_listening,
                "process_name": status.process_name,
                "pid": status.pid,
                "cloudflare": project.get("cloudflare", {}),
            })

        return {"projects": result}

    @app.get("/api/projects/{path:path}/status")
    async def api_project_status(path: str):
        """Get status for a specific project."""
        projects = list_projects()
        project = projects.get(f"/{path}")

        if not project:
            return {"error": "Project not found"}, 404

        port = project.get("port", 8000)
        status = get_port_status(port)

        return {
            "path": f"/{path}",
            "port": port,
            "is_running": status.is_listening,
            "process_name": status.process_name,
            "pid": status.pid,
        }

    @app.get("/partials/project-card/{path:path}", response_class=HTMLResponse)
    async def partial_project_card(request: Request, path: str):
        """HTMX partial for refreshing a project card."""
        projects = list_projects()
        full_path = f"/{path}"
        project = projects.get(full_path)

        if not project:
            return HTMLResponse("<div>Project not found</div>", status_code=404)

        port = project.get("port", 8000)
        status = get_port_status(port)

        return templates.TemplateResponse(
            "partials/project_card.html",
            {
                "request": request,
                "project": {
                    "path": full_path,
                    "name": project.get("name", Path(full_path).name),
                    "port": port,
                    "status": status,
                    "cloudflare": project.get("cloudflare", {}),
                },
            },
        )

    @app.get("/api/tunnel/config")
    async def api_tunnel_config(domain: str = "example.com", tunnel: str = "paracord"):
        """Generate cloudflared tunnel configuration."""
        projects = list_projects()
        config = generate_tunnel_config(projects, tunnel_name=tunnel, domain=domain)

        return {
            "config": config,
            "instructions": get_tunnel_instructions(tunnel),
        }

    @app.get("/tunnel", response_class=HTMLResponse)
    async def tunnel_page(request: Request):
        """Tunnel configuration page."""
        projects = list_projects()
        config = generate_tunnel_config(projects)
        instructions = get_tunnel_instructions()

        return templates.TemplateResponse(
            "tunnel.html",
            {
                "request": request,
                "config": config,
                "instructions": instructions,
                "projects": projects,
            },
        )

    return app


def run_server(host: str = "127.0.0.1", port: int = 7272, open_browser: bool = True):
    """Run the console server.

    Args:
        host: Host to bind to
        port: Port to listen on
        open_browser: Whether to open browser automatically
    """
    available, error = check_console_deps()
    if not available:
        raise ImportError(error)

    import uvicorn
    import webbrowser
    import threading

    app = create_app()

    if open_browser:
        def open_browser_delayed():
            import time

            time.sleep(0.5)
            webbrowser.open(f"http://{host}:{port}")

        threading.Thread(target=open_browser_delayed, daemon=True).start()

    uvicorn.run(app, host=host, port=port, log_level="info")
