"""Coordinator-side diagnostics helpers for CLI preflight checks."""

from __future__ import annotations

import os
import sqlite3
from dataclasses import dataclass
from pathlib import Path
from typing import Literal
from urllib.parse import urlparse

from hive_compute.config import get_settings
from hive_compute.coordinator.manager_auth import WEBAUTHN_AVAILABLE

DiagnosticStatus = Literal["ok", "warn", "fail"]


@dataclass(frozen=True)
class DoctorCheck:
    name: str
    status: DiagnosticStatus
    summary: str
    detail: str | None = None


def run_coordinator_doctor() -> list[DoctorCheck]:
    settings = get_settings()
    checks = [
        _check_client_api_key(settings.client_api_key),
        _check_database_path(settings.database_path),
        _check_manager_origins(settings.get_manager_origins()),
        _check_manager_rp_id(settings.get_manager_origins(), settings.get_manager_rp_id()),
        _check_worker_enrollment_mode(settings.public_worker_enrollment_enabled),
        _check_app_download(settings),
        _check_local_audio_jobs(settings.allow_local_audio_jobs),
        _check_passkeys(),
        _check_bootstrap(settings.database_path, settings.admin_bootstrap_secret),
    ]
    return checks


def _check_client_api_key(client_api_key: str) -> DoctorCheck:
    if client_api_key:
        return DoctorCheck("secrets", "ok", "HIVE_CLIENT_API_KEY is configured")
    return DoctorCheck(
        "secrets",
        "fail",
        "HIVE_CLIENT_API_KEY is missing",
        "Set HIVE_CLIENT_API_KEY before starting the coordinator.",
    )


def _check_database_path(database_path: str) -> DoctorCheck:
    path = Path(database_path).expanduser()
    parent = path.parent
    if not parent.exists():
        return DoctorCheck(
            "database",
            "warn",
            f"Database directory does not exist yet: {parent}",
            "Startup will create it if the runtime user can write there (for example after the Fly volume mounts).",
        )

    if not os.access(parent, os.W_OK):
        return DoctorCheck(
            "database",
            "fail",
            f"Database directory is not writable: {parent}",
            "Grant write access or point HIVE_DATABASE_PATH at a writable directory.",
        )

    if path.exists() and not os.access(path, os.W_OK):
        return DoctorCheck(
            "database",
            "fail",
            f"Database file is not writable: {path}",
            "Grant write access or restore the database from a writable volume.",
        )

    return DoctorCheck("database", "ok", f"Database path is writable: {path}")


def _check_manager_origins(origins: list[str]) -> DoctorCheck:
    if not origins:
        return DoctorCheck(
            "manager-origin",
            "fail",
            "No manager origins are configured",
            "Set HIVE_MANAGER_ORIGIN to the exact public origin for the hosted manager.",
        )

    for origin in origins:
        parsed = urlparse(origin)
        if parsed.scheme not in {"http", "https"} or not parsed.hostname:
            return DoctorCheck(
                "manager-origin",
                "fail",
                f"Invalid manager origin: {origin}",
                "Origins must be full http(s) URLs such as https://hivecompute.fly.dev.",
            )
        if parsed.scheme != "https" and parsed.hostname not in {"localhost", "127.0.0.1"}:
            return DoctorCheck(
                "manager-origin",
                "fail",
                f"Manager origin must use HTTPS in non-local environments: {origin}",
                "Passkeys require a secure origin outside localhost.",
            )

    return DoctorCheck("manager-origin", "ok", f"Configured {len(origins)} manager origin(s)")


def _check_manager_rp_id(origins: list[str], rp_id: str) -> DoctorCheck:
    if not rp_id:
        return DoctorCheck(
            "manager-rp-id",
            "fail",
            "Manager RP ID could not be derived",
            "Set HIVE_MANAGER_RP_ID explicitly if HIVE_MANAGER_ORIGIN does not contain a hostname.",
        )

    for origin in origins:
        hostname = urlparse(origin).hostname
        if not hostname:
            continue
        if hostname != rp_id and not hostname.endswith(f".{rp_id}"):
            return DoctorCheck(
                "manager-rp-id",
                "fail",
                f"Manager RP ID does not match the configured origin host: {rp_id}",
                f"The RP ID must equal the host or a parent domain of {hostname}.",
            )

    return DoctorCheck("manager-rp-id", "ok", f"Manager RP ID is compatible with configured origins: {rp_id}")


def _check_local_audio_jobs(allow_local_audio_jobs: bool) -> DoctorCheck:
    if not allow_local_audio_jobs:
        return DoctorCheck("local-audio", "ok", "Local audio job submission is disabled")
    return DoctorCheck(
        "local-audio",
        "warn",
        "Local audio job submission is enabled",
        "Disable HIVE_ALLOW_LOCAL_AUDIO_JOBS in hosted or partner-facing environments. "
        "When enabled, the first-party client key can submit absolute filesystem paths for normalization.",
    )


def _check_worker_enrollment_mode(public_worker_enrollment_enabled: bool) -> DoctorCheck:
    if not public_worker_enrollment_enabled:
        return DoctorCheck(
            "worker-enrollment",
            "ok",
            "Worker enrollment requires manager-issued tokens",
        )
    return DoctorCheck(
        "worker-enrollment",
        "warn",
        "Public worker enrollment is enabled",
        "Anyone who can reach the public download or install flow can register a new worker. "
        "Existing workers still need their current worker token or a manager-issued enrollment "
        "token to rotate credentials.",
    )


def _check_app_download(settings) -> DoctorCheck:
    try:
        app_download_source = settings.get_app_download_source(validate=True)
    except ValueError as exc:
        return DoctorCheck(
            "app-download",
            "fail",
            str(exc),
            "Point HIVE_APP_DOWNLOAD_URL at a public HTTPS .dmg/.zip or "
            "HIVE_APP_DOWNLOAD_FILE at a local .dmg/.zip file.",
        )

    if app_download_source:
        kind, value = app_download_source
        if kind == "file":
            return DoctorCheck("app-download", "ok", f"Public app download served locally from {value}")
        return DoctorCheck("app-download", "ok", f"Public app download redirects to {value}")

    if settings.should_require_app_download_url():
        return DoctorCheck(
            "app-download",
            "fail",
            "HIVE_APP_DOWNLOAD_URL / HIVE_APP_DOWNLOAD_FILE is missing for a hosted manager origin",
            "Set one download source before advertising the public /download path.",
        )

    return DoctorCheck(
        "app-download",
        "warn",
        "HIVE_APP_DOWNLOAD_URL is unset",
        "This is acceptable for localhost-only development, but hosted deployments should configure it.",
    )


def _check_passkeys() -> DoctorCheck:
    if WEBAUTHN_AVAILABLE:
        return DoctorCheck("passkeys", "ok", "webauthn package is installed")
    return DoctorCheck(
        "passkeys",
        "fail",
        "webauthn package is missing",
        "Install the coordinator dependencies again so the passkey libraries are available.",
    )


def _check_bootstrap(database_path: str, bootstrap_secret: str) -> DoctorCheck:
    admin_count = _count_admin_users(database_path)
    if bootstrap_secret and admin_count > 0:
        return DoctorCheck(
            "bootstrap",
            "warn",
            "HIVE_ADMIN_BOOTSTRAP_SECRET is still configured after manager enrollment",
            "Unset the bootstrap secret after the first manager passkey is enrolled.",
        )
    if bootstrap_secret:
        return DoctorCheck("bootstrap", "ok", "HIVE_ADMIN_BOOTSTRAP_SECRET is configured")
    if admin_count > 0:
        return DoctorCheck(
            "bootstrap",
            "ok",
            f"Bootstrap secret is unset, but {admin_count} admin user(s) already exist",
        )
    return DoctorCheck(
        "bootstrap",
        "warn",
        "HIVE_ADMIN_BOOTSTRAP_SECRET is missing",
        "First-time manager bootstrap will fail until you set it.",
    )


def _count_admin_users(database_path: str) -> int:
    path = Path(database_path).expanduser()
    if not path.exists():
        return 0

    try:
        with sqlite3.connect(path) as db:
            row = db.execute(
                """
                SELECT COUNT(*) FROM sqlite_master
                WHERE type = 'table' AND name = 'admin_users'
                """
            ).fetchone()
            if not row or row[0] == 0:
                return 0
            count_row = db.execute("SELECT COUNT(*) FROM admin_users").fetchone()
            return int(count_row[0]) if count_row else 0
    except sqlite3.DatabaseError:
        return 0
