"""Self-hosted platform CLI helpers."""

from __future__ import annotations

import shutil
import socket
from pathlib import Path

import click
import yaml

from g_gremlin.autopilot.policy import generate_default_policy


@click.group("platform")
def platform() -> None:
    """Self-hosted Docker platform commands."""


def _render_compose_environment(integrations: set[str]) -> list[str]:
    lines = [
        "      - G_GREMLIN_API_KEY=${G_GREMLIN_API_KEY:-}",
        "      - G_GREMLIN_POLICY_PATH=/policy/autopilot_policy.yaml",
    ]
    if "hubspot" in integrations:
        lines.append("      - G_GREMLIN_HUBSPOT_ACCESS_TOKEN=${G_GREMLIN_HUBSPOT_ACCESS_TOKEN:-}")
    if "salesforce" in integrations:
        lines.append("      - G_GREMLIN_SFDC_ORG_ALIAS=${G_GREMLIN_SFDC_ORG_ALIAS:-}")
    if "dynamics" in integrations:
        lines.append("      - G_GREMLIN_DYNAMICS_PROFILE=${G_GREMLIN_DYNAMICS_PROFILE:-}")
    if "google" in integrations:
        lines.extend(
            [
                "      - G_GREMLIN_GOOGLE_CLIENT_ID=${G_GREMLIN_GOOGLE_CLIENT_ID:-}",
                "      - G_GREMLIN_GOOGLE_CLIENT_SECRET=${G_GREMLIN_GOOGLE_CLIENT_SECRET:-}",
                "      - G_GREMLIN_GOOGLE_REFRESH_TOKEN=${G_GREMLIN_GOOGLE_REFRESH_TOKEN:-}",
            ]
        )
    if "slack" in integrations:
        lines.append("      - G_GREMLIN_SLACK_BOT_TOKEN=${G_GREMLIN_SLACK_BOT_TOKEN:-}")
    return lines


def _render_env_template(integrations: set[str]) -> str:
    lines = [
        "# Core platform variables",
        "G_GREMLIN_API_KEY=",
        "G_GREMLIN_POLICY_PATH=/policy/autopilot_policy.yaml",
        "",
    ]
    if "hubspot" in integrations:
        lines.extend(["# HubSpot", "G_GREMLIN_HUBSPOT_ACCESS_TOKEN=", ""])
    if "salesforce" in integrations:
        lines.extend(["# Salesforce", "G_GREMLIN_SFDC_ORG_ALIAS=", ""])
    if "dynamics" in integrations:
        lines.extend(["# Dynamics", "G_GREMLIN_DYNAMICS_PROFILE=default", ""])
    if "google" in integrations:
        lines.extend(
            [
                "# Google OAuth",
                "G_GREMLIN_GOOGLE_CLIENT_ID=",
                "G_GREMLIN_GOOGLE_CLIENT_SECRET=",
                "G_GREMLIN_GOOGLE_REFRESH_TOKEN=",
                "",
            ]
        )
    if "slack" in integrations:
        lines.extend(["# Slack notifications", "G_GREMLIN_SLACK_BOT_TOKEN=", ""])
    return "\n".join(lines).rstrip() + "\n"


def _render_compose_yaml(integrations: set[str]) -> str:
    env_lines = "\n".join(_render_compose_environment(integrations))
    return (
        "services:\n"
        "  gremlin-platform:\n"
        "    build:\n"
        "      context: .\n"
        "      dockerfile: Dockerfile.platform\n"
        "    ports:\n"
        "      - \"7777:7777\"\n"
        "    volumes:\n"
        "      - ./gremlin-config:/config\n"
        "      - gremlin-data:/data\n"
        "      - ./policy:/policy\n"
        "    environment:\n"
        f"{env_lines}\n"
        "    restart: unless-stopped\n"
        "\n"
        "volumes:\n"
        "  gremlin-data:\n"
    )


def _check_port_available(port: int) -> bool:
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    try:
        sock.bind(("127.0.0.1", port))
        return True
    except OSError:
        return False
    finally:
        sock.close()


@platform.command("init")
@click.option(
    "--output-dir",
    default=Path("./my-platform"),
    type=click.Path(file_okay=False, path_type=Path),
    show_default=True,
    help="Directory to scaffold for self-hosted deployment.",
)
@click.option(
    "--integrations",
    multiple=True,
    type=click.Choice(["hubspot", "salesforce", "dynamics", "google", "slack"], case_sensitive=False),
    help="Integrations to pre-wire in generated .env template.",
)
def platform_init(output_dir: Path, integrations: tuple[str, ...]) -> None:
    """Generate a deployment scaffold for the self-hosted platform."""
    normalized_integrations = {item.lower() for item in integrations}

    output_dir.mkdir(parents=True, exist_ok=True)
    gremlin_config_dir = output_dir / "gremlin-config"
    policy_dir = output_dir / "policy"
    gremlin_config_dir.mkdir(parents=True, exist_ok=True)
    policy_dir.mkdir(parents=True, exist_ok=True)

    compose_path = output_dir / "docker-compose.yaml"
    env_template_path = output_dir / ".env.template"
    gremlin_readme_path = gremlin_config_dir / "README.md"
    policy_path = policy_dir / "autopilot_policy.yaml"
    readme_path = output_dir / "README.md"

    compose_path.write_text(_render_compose_yaml(normalized_integrations), encoding="utf-8")
    env_template_path.write_text(_render_env_template(normalized_integrations), encoding="utf-8")

    gremlin_readme_path.write_text(
        "\n".join(
            [
                "# gremlin-config",
                "",
                "Populate this folder with license credentials before first boot:",
                "- `license.jwt` + `refresh_token` (online license flow), or",
                "- `license.json` (offline signed license flow).",
                "",
                "Optional:",
                "- `autopilot/api_key` to persist a pre-generated API key.",
            ]
        )
        + "\n",
        encoding="utf-8",
    )

    policy = generate_default_policy("local")
    policy_path.write_text(
        yaml.safe_dump(policy.model_dump(by_alias=True, exclude_none=True), sort_keys=False),
        encoding="utf-8",
    )

    readme_path.write_text(
        "\n".join(
            [
                "# g-gremlin Platform Scaffold",
                "",
                "## Quick Start",
                "1. Copy Docker assets into this folder (`Dockerfile.platform`, `docker/platform/*`).",
                "2. Add license files under `gremlin-config/`.",
                "3. Review and edit `policy/autopilot_policy.yaml`.",
                "4. Copy `.env.template` to `.env` and fill integration credentials.",
                "5. Start with `docker compose up -d`.",
            ]
        )
        + "\n",
        encoding="utf-8",
    )

    click.echo(f"Scaffold generated in: {output_dir.resolve()}")
    click.echo(f"- {compose_path.name}")
    click.echo(f"- {env_template_path.name}")
    click.echo(f"- {gremlin_readme_path.relative_to(output_dir)}")
    click.echo(f"- {policy_path.relative_to(output_dir)}")
    click.echo(f"- {readme_path.name}")


@platform.command("doctor")
@click.option(
    "--dir",
    "base_dir",
    default=Path("."),
    type=click.Path(file_okay=False, path_type=Path),
    show_default=True,
    help="Platform deployment directory to validate.",
)
def platform_doctor(base_dir: Path) -> None:
    """Validate local deployment readiness for the self-hosted platform."""
    base = base_dir.resolve()

    docker_ok = shutil.which("docker") is not None
    compose_ok = (base / "docker-compose.yaml").exists() or (base / "docker-compose.platform.yaml").exists()
    policy_ok = (base / "policy" / "autopilot_policy.yaml").exists()
    license_ok = (base / "gremlin-config" / "license.jwt").exists() or (base / "gremlin-config" / "license.json").exists()
    port_ok = _check_port_available(7777)

    checks = [
        ("docker_cli", docker_ok, "Docker CLI available in PATH."),
        ("compose_file", compose_ok, "Compose file found."),
        ("policy_file", policy_ok, "Policy file found at policy/autopilot_policy.yaml."),
        ("license_file", license_ok, "License file found in gremlin-config/."),
        ("port_7777", port_ok, "Port 7777 is available."),
    ]

    has_errors = False
    for name, passed, detail in checks:
        status = "OK" if passed else "FAIL"
        click.echo(f"[{status}] {name}: {detail}")
        if not passed:
            has_errors = True

    if has_errors:
        raise click.ClickException("Platform doctor found blocking issues.")
