"""
djb init CLI - Initialize djb development environment.

Provides commands for setting up system dependencies, Python packages, and frontend tooling.
"""

from __future__ import annotations

import subprocess
import sys
from pathlib import Path

import click

from djb.cli.logging import get_logger

logger = get_logger(__name__)


def _run(
    cmd: list[str],
    cwd: Path | None = None,
    label: str | None = None,
    done_msg: str | None = None,
    halt_on_fail: bool = True,
) -> int:
    """Run a shell command with optional error handling."""
    if label:
        logger.next(label)
    logger.debug(f"Executing: {' '.join(cmd)}")
    result = subprocess.run(cmd, cwd=cwd, capture_output=True)
    if result.returncode != 0 and halt_on_fail:
        logger.error(f"{label or 'Command'} failed with exit code {result.returncode}")
        if result.stderr:
            logger.debug(result.stderr.decode())
        raise click.ClickException(f"{label or 'Command'} failed")
    if done_msg:
        logger.done(done_msg)
    return result.returncode


@click.command("init")
@click.option(
    "--skip-brew",
    is_flag=True,
    help="Skip installing system dependencies via Homebrew",
)
@click.option(
    "--skip-python",
    is_flag=True,
    help="Skip installing Python dependencies",
)
@click.option(
    "--skip-frontend",
    is_flag=True,
    help="Skip installing frontend dependencies",
)
@click.option(
    "--skip-secrets",
    is_flag=True,
    help="Skip secrets initialization",
)
@click.option(
    "--project-root",
    type=click.Path(exists=True, file_okay=False, path_type=Path),
    default=None,
    help="Project root directory (default: current directory)",
)
def init(
    skip_brew: bool,
    skip_python: bool,
    skip_frontend: bool,
    skip_secrets: bool,
    project_root: Path | None,
):
    """Initialize djb development environment.

    Sets up everything needed for local development:

    \b
    • System dependencies (Homebrew): age, PostgreSQL, GDAL, Bun
    • Python dependencies: uv sync
    • Frontend dependencies: bun install in frontend/
    • Secrets management: Age-encrypted configuration

    This command is idempotent - safe to run multiple times.
    Already-installed dependencies are skipped automatically.

    \b
    Examples:
      djb init                    # Full setup
      djb init --skip-brew        # Skip Homebrew (already installed)
      djb init --skip-secrets     # Skip secrets (configure later)
    """
    if project_root is None:
        project_root = Path.cwd()

    logger.info("Initializing djb development environment")
    logger.note()

    # Check if we're on macOS
    is_macos = sys.platform == "darwin"

    # Install system dependencies via Homebrew
    if not skip_brew and is_macos:
        logger.next("Installing system dependencies via Homebrew")

        # Check if brew is installed
        brew_check = subprocess.run(["which", "brew"], capture_output=True)
        if brew_check.returncode != 0:
            logger.error("Homebrew not found. Please install from https://brew.sh/")
            raise click.ClickException(
                "Homebrew is required for automatic dependency installation"
            )

        # Install age (for secrets encryption)
        result = subprocess.run(["brew", "list", "age"], capture_output=True)
        if result.returncode != 0:
            _run(["brew", "install", "age"], label="Installing age", done_msg="age installed")
        else:
            logger.done("age already installed")

        # Install PostgreSQL (for database)
        result = subprocess.run(["brew", "list", "postgresql@17"], capture_output=True)
        if result.returncode != 0:
            _run(
                ["brew", "install", "postgresql@17"],
                label="Installing PostgreSQL",
                done_msg="postgresql@17 installed",
            )
        else:
            logger.done("postgresql@17 already installed")

        # Install GDAL (for GeoDjango)
        result = subprocess.run(["brew", "list", "gdal"], capture_output=True)
        if result.returncode != 0:
            _run(["brew", "install", "gdal"], label="Installing GDAL", done_msg="gdal installed")
        else:
            logger.done("gdal already installed")

        # Install Bun (JavaScript runtime)
        result = subprocess.run(["which", "bun"], capture_output=True)
        if result.returncode != 0:
            _run(
                ["brew", "install", "oven-sh/bun/bun"],
                label="Installing Bun",
                done_msg="bun installed",
            )
        else:
            logger.done("bun already installed")

        logger.note()
        logger.done("System dependencies ready")
    elif not skip_brew and not is_macos:
        logger.skip("Homebrew installation (not on macOS)")
        logger.info("Please install dependencies manually:")
        logger.info("  - age: https://age-encryption.org/")
        logger.info("  - PostgreSQL 17: https://www.postgresql.org/")
        logger.info("  - GDAL: https://gdal.org/")
        logger.info("  - Bun: https://bun.sh/")
    else:
        logger.skip("System dependency installation")

    # Install Python dependencies
    if not skip_python:
        logger.note()
        _run(
            ["uv", "sync"],
            cwd=project_root,
            label="Installing Python dependencies",
            done_msg="Python dependencies installed",
        )
    else:
        logger.note()
        logger.skip("Python dependency installation")

    # Install frontend dependencies
    if not skip_frontend:
        frontend_dir = project_root / "frontend"
        if frontend_dir.exists():
            logger.note()
            _run(
                ["bun", "install"],
                cwd=frontend_dir,
                label="Installing frontend dependencies",
                done_msg="Frontend dependencies installed",
            )
        else:
            logger.note()
            logger.skip(f"Frontend directory not found at {frontend_dir}")
    else:
        logger.note()
        logger.skip("Frontend dependency installation")

    # Initialize secrets
    if not skip_secrets:
        logger.note()
        logger.next("Initializing secrets management")

        # Check if secrets already initialized
        key_path = Path.home() / ".age" / "keys.txt"
        secrets_dir = project_root / "secrets"

        if key_path.exists() and (secrets_dir / "dev.yaml").exists():
            logger.done("Secrets already initialized")
            logger.info("  (Use 'djb secrets init --force' to re-initialize)")
        else:
            _run(
                ["djb", "secrets", "init"],
                cwd=project_root,
                label="Initializing secrets",
                done_msg="Secrets initialized",
            )
            logger.note()
            logger.info("Remember to edit your secrets:")
            logger.info("  djb secrets edit dev")
            logger.info("  djb secrets edit production")
    else:
        logger.note()
        logger.skip("Secrets initialization")

    # Final success message
    logger.note()
    logger.done("djb initialization complete!")
    logger.note()
    logger.info("Next steps:")
    logger.info("  1. Configure your Django project to use djb")
    logger.info("  2. Edit secrets: djb secrets edit dev")
    logger.info("  3. Set up your database and run migrations")
    logger.info("  4. Deploy: djb deploy heroku --app your-app")
