"""Doctor command registration."""

from __future__ import annotations

import json
from typing import Any

import click

from g_gremlin import __version__
from g_gremlin import cli as cli_mod
from g_gremlin.cli import _should_emit_json, cli


def _mark_warning(entry: dict[str, Any], message: str, *, detail: Exception | str | None = None) -> None:
    entry["status"] = "warn"
    entry["warning"] = message
    if detail is not None:
        entry["error"] = str(detail)


@cli.command("doctor")
@click.option(
    "--format",
    "output_format",
    type=click.Choice(["text", "json"], case_sensitive=False),
    default="text",
    show_default=True,
    help="Output format (text|json).",
)
@click.option("--json", "json_flag", is_flag=True, help="Shortcut for --format json.")
@click.option(
    "--live",
    is_flag=True,
    help="Run deeper connector checks where supported; use connector-specific doctor commands for full diagnostics.",
)
@click.option("--sfdc", "check_sfdc", is_flag=True, help="Include Salesforce doctor checks.")
@click.option("--hubspot", "check_hubspot", is_flag=True, help="Include HubSpot doctor checks.")
@click.option("--dynamics", "check_dynamics", is_flag=True, help="Include Dynamics doctor checks.")
def doctor(
    output_format: str,
    json_flag: bool,
    live: bool,
    check_sfdc: bool,
    check_hubspot: bool,
    check_dynamics: bool,
) -> None:
    """
    Top-level health check: auth status, connector availability, and config.

    \b
    Quick check:      g-gremlin doctor --format json
    Live checks:      g-gremlin doctor --live --format json
    Connector-only:   g-gremlin doctor --sfdc --format json
    Deep connector:   g-gremlin sfdc doctor --json
                      g-gremlin hubspot doctor --json
                      g-gremlin dynamics doctor --json
    """
    emit_json = _should_emit_json(output_format, json_flag, False)
    result: dict[str, Any] = {
        "overall_status": "ok",
        "status": "ok",
        "version": __version__,
        "connectors": {},
    }

    status_order = {"ok": 0, "warn": 1, "error": 2}

    def merge_status(next_status: str) -> None:
        current = str(result.get("overall_status") or "ok")
        if status_order.get(next_status, 0) > status_order.get(current, 0):
            result["overall_status"] = next_status
            result["status"] = next_status

    connector_checks: list[tuple[str, bool]] = [
        ("sfdc", check_sfdc),
        ("hubspot", check_hubspot),
        ("dynamics", check_dynamics),
    ]
    any_explicit = any(flag for _, flag in connector_checks)

    for name, flag in connector_checks:
        if any_explicit and not flag:
            continue

        active_check = bool(live or flag)
        entry: dict[str, Any] = {"available": False, "status": "ok"}

        try:
            if name == "sfdc":
                try:
                    helpers = cli_mod._get_sfdc_helpers()
                except Exception as exc:
                    _mark_warning(entry, "Salesforce support unavailable.", detail=exc)
                    result["connectors"][name] = entry
                    if active_check:
                        merge_status("warn")
                    continue

                try:
                    entry["sf_version"] = helpers.get_cli_version()
                    entry["available"] = True
                except Exception as exc:
                    _mark_warning(entry, "Salesforce CLI is not available.", detail=exc)
                    result["connectors"][name] = entry
                    if active_check:
                        merge_status("warn")
                    continue

                if active_check:
                    alias = helpers.get_configured_org()
                    entry["configured_org"] = alias
                    if alias:
                        try:
                            entry["identity"] = helpers.get_org_identity(org_alias=alias)
                        except Exception as exc:
                            entry["identity_error"] = str(exc)
                            entry["status"] = "warn"
                            entry["warning"] = "Configured Salesforce org could not be verified."
                    else:
                        entry["status"] = "warn"
                        entry["warning"] = "No configured Salesforce org alias."

            elif name == "hubspot":
                try:
                    hubspot_mod = cli_mod._get_hubspot_helpers()
                except Exception as exc:
                    _mark_warning(entry, "HubSpot support unavailable.", detail=exc)
                    result["connectors"][name] = entry
                    if active_check:
                        merge_status("warn")
                    continue
                entry["available"] = True
                try:
                    cfg = hubspot_mod.HubSpotConfig.load(profile=cli_mod._get_hubspot_profile())
                    entry["configured"] = True
                    entry["profile"] = cfg.profile
                    entry["verified"] = bool(getattr(cfg, "verified", False))
                    if active_check and not entry["verified"]:
                        entry["status"] = "warn"
                        entry["warning"] = "HubSpot profile is present but not verified."
                except Exception as exc:
                    entry["configured"] = False
                    entry["config_error"] = str(exc)
                    if active_check:
                        entry["status"] = "warn"
                        entry["warning"] = "No verified HubSpot profile configured."

            elif name == "dynamics":
                try:
                    dynamics_mod = cli_mod._get_dynamics_helpers()
                except Exception as exc:
                    _mark_warning(entry, "Dynamics support unavailable.", detail=exc)
                    result["connectors"][name] = entry
                    if active_check:
                        merge_status("warn")
                    continue

                try:
                    pac_path = cli_mod._get_dynamics_pac_path()
                except Exception as exc:
                    pac_path = None
                    entry["pac_path_error"] = str(exc)
                entry["available"] = bool(pac_path)
                entry["pac_path"] = pac_path
                try:
                    cfg = dynamics_mod.DynamicsConfig.load(profile=cli_mod._get_dynamics_profile())
                    entry["profile"] = cfg.profile
                    entry["configured"] = bool(cfg.verified or cfg.pac_profile_index is not None or cfg.org_url)
                    entry["verified"] = bool(cfg.verified)
                except Exception as exc:
                    entry["configured"] = False
                    entry["config_error"] = str(exc)
                    entry["profile"] = cli_mod._get_dynamics_profile() or "default"
                    entry["verified"] = False
                if active_check and not pac_path:
                    entry["status"] = "warn"
                    entry["warning"] = "Power Platform CLI (pac) not found."
                elif active_check and not entry.get("configured"):
                    entry["status"] = "warn"
                    entry["warning"] = "No verified Dynamics profile configured."

        except Exception as exc:
            entry["error"] = str(exc)
            entry["status"] = "error"

        if active_check and entry["status"] != "ok":
            merge_status(str(entry["status"]))

        result["connectors"][name] = entry

    result["hint"] = "For deep connector diagnostics run: g-gremlin <connector> doctor --json"

    if emit_json:
        click.echo(json.dumps(result, indent=2, default=str))
        return

    click.echo("g-gremlin doctor")
    click.echo(f"  Status: {result['overall_status']}")
    for connector_name, connector_info in result["connectors"].items():
        connector_status = str(
            connector_info.get("status") or ("ok" if connector_info.get("available") else "warn")
        )
        click.echo(f"  {connector_name:<12} {connector_status}")
        warning = connector_info.get("warning") or connector_info.get("config_error")
        if warning:
            click.echo(f"    {warning}")
    click.echo(f"\n  {result['hint']}")
