"""Azure Authentication Preflight — Pre-execution validation for Azure FinOps."""

import json
import os
import shutil
import subprocess
import time
from dataclasses import dataclass, field
from typing import Optional


@dataclass
class PreflightCheck:
    name: str
    status: str  # PASS, FAIL
    message: str
    elapsed_ms: float = 0.0


@dataclass
class PreflightResult:
    checks: list[PreflightCheck] = field(default_factory=list)
    subscription_id: Optional[str] = None
    tenant_id: Optional[str] = None

    @property
    def passed(self) -> bool:
        return all(c.status == "PASS" for c in self.checks)

    @property
    def summary(self) -> str:
        passed = sum(1 for c in self.checks if c.status == "PASS")
        return f"{passed}/{len(self.checks)} checks passed"


def _run_az(args: list[str], timeout: int = 30) -> tuple[int, str, str]:
    try:
        result = subprocess.run(["az"] + args, capture_output=True, text=True, timeout=timeout)
        return result.returncode, result.stdout, result.stderr
    except FileNotFoundError:
        return -1, "", "az CLI not found"
    except subprocess.TimeoutExpired:
        return -2, "", f"Timeout after {timeout}s"


def check_az_installed() -> PreflightCheck:
    start = time.monotonic()
    found = shutil.which("az") is not None
    elapsed = (time.monotonic() - start) * 1000
    return PreflightCheck(
        name="az_cli_installed",
        status="PASS" if found else "FAIL",
        message=(
            "Azure CLI found on PATH" if found else "Azure CLI not found — install: https://aka.ms/installazurecli"
        ),
        elapsed_ms=elapsed,
    )


def check_az_logged_in() -> PreflightCheck:
    start = time.monotonic()
    rc, stdout, stderr = _run_az(["account", "show", "--output", "json"])
    elapsed = (time.monotonic() - start) * 1000
    if rc == 0:
        try:
            data = json.loads(stdout)
            user = data.get("user", {}).get("name", "unknown")
            return PreflightCheck("az_logged_in", "PASS", f"Logged in as {user}", elapsed)
        except json.JSONDecodeError:
            return PreflightCheck("az_logged_in", "FAIL", "az account show returned invalid JSON", elapsed)
    return PreflightCheck("az_logged_in", "FAIL", f"Not logged in: {stderr.strip()}", elapsed)


def check_subscription_accessible(subscription_id: Optional[str] = None) -> PreflightCheck:
    sub_id = subscription_id or os.environ.get("AZURE_SUBSCRIPTION_ID", "")
    if not sub_id:
        return PreflightCheck(
            "subscription_accessible",
            "FAIL",
            "No subscription ID provided (set AZURE_SUBSCRIPTION_ID)",
            0,
        )
    start = time.monotonic()
    rc, stdout, stderr = _run_az(["account", "show", "--subscription", sub_id, "--output", "json"])
    elapsed = (time.monotonic() - start) * 1000
    if rc == 0:
        try:
            data = json.loads(stdout)
            name = data.get("name", "unknown")
            return PreflightCheck(
                "subscription_accessible",
                "PASS",
                f"Subscription '{name}' ({sub_id[:8]}...) accessible",
                elapsed,
            )
        except json.JSONDecodeError:
            pass
    return PreflightCheck(
        "subscription_accessible",
        "FAIL",
        f"Cannot access subscription {sub_id[:8]}...: {stderr.strip()}",
        elapsed,
    )


def check_cost_management_api(subscription_id: Optional[str] = None) -> PreflightCheck:
    sub_id = subscription_id or os.environ.get("AZURE_SUBSCRIPTION_ID", "")
    if not sub_id:
        return PreflightCheck("cost_management_api", "FAIL", "No subscription ID for API check", 0)
    start = time.monotonic()
    rc, stdout, stderr = _run_az(
        [
            "consumption",
            "usage",
            "list",
            "--subscription",
            sub_id,
            "--top",
            "1",
            "--output",
            "json",
        ],
        timeout=60,
    )
    elapsed = (time.monotonic() - start) * 1000
    if rc == 0:
        return PreflightCheck("cost_management_api", "PASS", "Cost Management API reachable", elapsed)
    return PreflightCheck(
        "cost_management_api",
        "FAIL",
        f"Cost Management API unreachable: {stderr.strip()}",
        elapsed,
    )


def run_preflight(subscription_id: Optional[str] = None) -> PreflightResult:
    result = PreflightResult(subscription_id=subscription_id)
    c1 = check_az_installed()
    result.checks.append(c1)
    if c1.status == "FAIL":
        return result
    c2 = check_az_logged_in()
    result.checks.append(c2)
    if c2.status == "PASS":
        _, stdout, _ = _run_az(["account", "show", "--output", "json"])
        try:
            result.tenant_id = json.loads(stdout).get("tenantId")
        except (json.JSONDecodeError, AttributeError):
            pass
    if c2.status == "FAIL":
        return result
    result.checks.append(check_subscription_accessible(subscription_id))
    result.checks.append(check_cost_management_api(subscription_id))
    return result
