"""BlackAnt SDK Command Line Interface.

This module provides a CLI for the BlackAnt SDK, allowing users to
interact with the BlackAnt platform directly from the terminal.

Usage:
    blackant login --user USER --password PASS --url URL
    blackant build --name SERVICE_NAME --path PATH [--push]
    blackant list
    blackant status SERVICE_NAME
    blackant delete SERVICE_NAME
"""

import os
import sys
import click
from typing import Optional


def get_client(user: Optional[str] = None, password: Optional[str] = None,
               base_url: Optional[str] = None, login_url: Optional[str] = None):
    """Create and authenticate a BlackAnt client.

    Args:
        user: Username (or from BLACKANT_USER env var)
        password: Password (or from BLACKANT_PASSWORD env var)
        base_url: Base URL (or from BLACKANT_URL env var)
        login_url: Login URL (or from BLACKANT_LOGIN_URL env var)

    Returns:
        Authenticated BlackAntClient instance

    Raises:
        click.ClickException: If authentication fails or credentials missing
    """
    from blackant import BlackAntClient

    user = user or os.getenv("BLACKANT_USER")
    password = password or os.getenv("BLACKANT_PASSWORD")
    base_url = base_url or os.getenv("BLACKANT_URL", "https://dev.blackant.app")
    login_url = login_url or os.getenv("BLACKANT_LOGIN_URL", f"{base_url}/api/auth/login")

    if not user or not password:
        raise click.ClickException(
            "Missing credentials. Provide --user and --password, "
            "or set BLACKANT_USER and BLACKANT_PASSWORD environment variables."
        )

    try:
        client = BlackAntClient(
            user=user,
            password=password,
            base_url=base_url,
            login_url=login_url
        )
        if not client.authenticate():
            raise click.ClickException("Authentication failed. Check your credentials.")
        return client
    except Exception as e:
        raise click.ClickException(f"Failed to connect: {e}")


@click.group()
@click.version_option(version="1.0.4", prog_name="blackant")
def main():
    """BlackAnt SDK - Command Line Interface

    Interact with the BlackAnt platform from your terminal.

    \b
    Environment variables:
      BLACKANT_USER       - Username for authentication
      BLACKANT_PASSWORD   - Password for authentication
      BLACKANT_URL        - Base URL (default: https://dev.blackant.app)

    \b
    Examples:
      blackant login --user admin --password xxx
      blackant build --name my-calc --path ./src/calculation/impl --push
      blackant list
      blackant status my-calc
    """
    pass


@main.command()
@click.option("--user", "-u", help="BlackAnt username")
@click.option("--password", "-p", help="BlackAnt password")
@click.option("--url", help="BlackAnt base URL")
def login(user: Optional[str], password: Optional[str], url: Optional[str]):
    """Test connection and authenticate with BlackAnt.

    Verifies that the provided credentials are valid and the
    BlackAnt platform is reachable.
    """
    client = get_client(user=user, password=password, base_url=url)

    if client.test_connection():
        click.secho("Successfully connected to BlackAnt!", fg="green")
        click.echo(f"  User: {user or os.getenv('BLACKANT_USER')}")
        click.echo(f"  URL: {url or os.getenv('BLACKANT_URL', 'https://dev.blackant.app')}")
    else:
        raise click.ClickException("Connection test failed.")


@main.command()
@click.option("--name", "-n", required=True, help="Service name")
@click.option("--path", "-p", required=True, help="Path to implementation directory")
@click.option("--dockerfile", "-d", default="Dockerfile", help="Dockerfile name (default: Dockerfile)")
@click.option("--tag", "-t", default="latest", help="Image tag (default: latest)")
@click.option("--push/--no-push", default=True, help="Push to registry after build (default: yes)")
@click.option("--register/--no-register", default=False, help="Register service after push (default: no)")
@click.option("--user", "-u", help="BlackAnt username")
@click.option("--password", help="BlackAnt password")
@click.option("--url", help="BlackAnt base URL")
def build(name: str, path: str, dockerfile: str, tag: str, push: bool,
          register: bool, user: Optional[str], password: Optional[str],
          url: Optional[str]):
    """Build a Docker image and optionally push to registry.

    \b
    Examples:
      blackant build --name my-calc --path ./src/calculation/impl
      blackant build --name my-calc --path ./impl --tag v1.0.0 --push
      blackant build --name my-calc --path ./impl --no-push
    """
    client = get_client(user=user, password=password, base_url=url)

    click.echo(f"Building service '{name}' from {path}...")
    click.echo(f"  Dockerfile: {dockerfile}")
    click.echo(f"  Tag: {tag}")
    click.echo(f"  Push: {'yes' if push else 'no'}")

    try:
        result = client.build_service(
            service_name=name,
            impl_path=path,
            dockerfile_path=dockerfile,
            tag=tag,
            push=push,
            register_service=register
        )

        if result.get("build_success"):
            click.secho("Build successful!", fg="green")
            click.echo(f"  Image: {result.get('full_image', 'N/A')}")
            click.echo(f"  Image ID: {result.get('image_id', 'N/A')[:12]}...")
            size_mb = result.get('size', 0) / 1024 / 1024
            click.echo(f"  Size: {size_mb:.2f} MB")

            if push and result.get("pushed"):
                click.secho("Push successful!", fg="green")
            elif push:
                click.secho("Push failed!", fg="red")
        else:
            raise click.ClickException("Build failed. Check logs for details.")

    except Exception as e:
        raise click.ClickException(f"Build error: {e}")


@main.command("list")
@click.option("--namespace", "-ns", help="Filter by namespace")
@click.option("--user", "-u", help="BlackAnt username")
@click.option("--password", "-p", help="BlackAnt password")
@click.option("--url", help="BlackAnt base URL")
def list_services(namespace: Optional[str], user: Optional[str],
                  password: Optional[str], url: Optional[str]):
    """List all registered services.

    \b
    Examples:
      blackant list
      blackant list --namespace production
    """
    client = get_client(user=user, password=password, base_url=url)

    try:
        services = client.list_services(namespace=namespace)

        if not services:
            click.echo("No services found.")
            return

        click.echo(f"Found {len(services)} service(s):\n")

        for svc in services:
            name = svc.get("name", "Unknown")
            status = svc.get("status", "Unknown")
            svc_type = svc.get("type", "Unknown")

            # Color based on status
            if status.lower() in ("running", "active"):
                status_color = "green"
            elif status.lower() in ("stopped", "inactive"):
                status_color = "yellow"
            else:
                status_color = "white"

            click.echo(f"  {name}")
            click.echo(f"    Status: ", nl=False)
            click.secho(status, fg=status_color)
            click.echo(f"    Type: {svc_type}")
            click.echo()

    except Exception as e:
        raise click.ClickException(f"Failed to list services: {e}")


@main.command()
@click.argument("name")
@click.option("--user", "-u", help="BlackAnt username")
@click.option("--password", "-p", help="BlackAnt password")
@click.option("--url", help="BlackAnt base URL")
def status(name: str, user: Optional[str], password: Optional[str],
           url: Optional[str]):
    """Get status of a specific service.

    \b
    Examples:
      blackant status my-calc
      blackant status my-service --user admin --password xxx
    """
    client = get_client(user=user, password=password, base_url=url)

    try:
        svc_status = client.get_service_status(service_name=name)

        click.echo(f"Service: {name}\n")

        for key, value in svc_status.items():
            click.echo(f"  {key}: {value}")

    except Exception as e:
        raise click.ClickException(f"Failed to get status: {e}")


@main.command()
@click.argument("name")
@click.option("--yes", "-y", is_flag=True, help="Skip confirmation")
@click.option("--user", "-u", help="BlackAnt username")
@click.option("--password", "-p", help="BlackAnt password")
@click.option("--url", help="BlackAnt base URL")
def delete(name: str, yes: bool, user: Optional[str], password: Optional[str],
           url: Optional[str]):
    """Delete a service.

    \b
    Examples:
      blackant delete my-calc
      blackant delete my-calc --yes
    """
    if not yes:
        click.confirm(f"Are you sure you want to delete '{name}'?", abort=True)

    client = get_client(user=user, password=password, base_url=url)

    try:
        if client.delete_service(service_name=name):
            click.secho(f"Service '{name}' deleted successfully!", fg="green")
        else:
            raise click.ClickException(f"Failed to delete service '{name}'.")

    except Exception as e:
        raise click.ClickException(f"Delete error: {e}")


@main.command()
@click.argument("name")
@click.option("--user", "-u", help="BlackAnt username")
@click.option("--password", "-p", help="BlackAnt password")
@click.option("--url", help="BlackAnt base URL")
def info(name: str, user: Optional[str], password: Optional[str],
         url: Optional[str]):
    """Get detailed information about a service.

    \b
    Examples:
      blackant info my-calc
    """
    client = get_client(user=user, password=password, base_url=url)

    try:
        service = client.get_service(service_name=name)

        click.echo(f"Service: {name}\n")

        for key, value in service.items():
            if isinstance(value, dict):
                click.echo(f"  {key}:")
                for k, v in value.items():
                    click.echo(f"    {k}: {v}")
            else:
                click.echo(f"  {key}: {value}")

    except Exception as e:
        raise click.ClickException(f"Failed to get service info: {e}")


if __name__ == "__main__":
    main()
