"""CLI commands for tenant management."""

from __future__ import annotations

from pathlib import Path

import click

from oclawma.tenant import (
    TenantConfig,
    TenantManager,
    TenantNotFoundError,
    TenantQuotas,
    TenantStatus,
)


@click.group(name="tenant")
def tenant_cli() -> None:
    """Manage tenants and multi-tenant configuration.

    Commands for creating, listing, and managing tenants with
    resource quotas and access controls.
    """
    pass


def get_tenant_manager() -> TenantManager:
    """Get a tenant manager with default config path."""
    data_dir = Path.home() / ".oclawma" / "tenants"
    data_dir.mkdir(parents=True, exist_ok=True)
    return TenantManager(data_dir / "tenants.db")


@tenant_cli.command(name="create")
@click.argument("tenant-id")
@click.option("--name", "-n", required=True, help="Tenant display name")
@click.option("--description", "-d", help="Tenant description")
@click.option("--max-jobs", type=int, default=100, help="Maximum concurrent jobs")
@click.option("--max-workers", type=int, default=10, help="Maximum workers")
@click.option("--storage-limit", type=int, default=1000, help="Storage limit in MB")
@click.option("--status", type=click.Choice(["active", "suspended", "disabled"]), default="active")
@click.option(
    "--feature", "features", multiple=True, help="Enable feature (can be used multiple times)"
)
@click.option(
    "--disable-feature",
    "disabled_features",
    multiple=True,
    help="Disable feature (can be used multiple times)",
)
def create_tenant(
    tenant_id: str,
    name: str,
    description: str | None,
    max_jobs: int,
    max_workers: int,
    storage_limit: int,
    status: str,
    features: tuple[str, ...],
    disabled_features: list[str],
) -> None:
    """Create a new tenant.

    Example:
        oclawma tenant create acme-corp --name "Acme Corporation" --max-jobs 500
    """
    with get_tenant_manager() as manager:
        try:
            # Build quotas
            quotas = TenantQuotas(
                max_jobs=max_jobs,
                max_workers=max_workers,
                storage_limit_mb=storage_limit,
            )

            # Build config with features
            features_dict: dict[str, bool] = {
                "web_chat": True,
                "batch_jobs": True,
                "encryption": True,
                "rate_limiting": True,
                "distributed_locking": False,
                "priority_preemption": True,
            }

            # Apply enabled features
            for feature in features:
                features_dict[feature] = True

            # Apply disabled features
            for feature in disabled_features:
                features_dict[feature] = False

            config = TenantConfig(features=features_dict)

            # Create tenant
            tenant = manager.create(
                tenant_id=tenant_id,
                name=name,
                description=description,
                quotas=quotas,
                config=config,
                status=TenantStatus(status),
            )

            click.echo(f"✓ Created tenant '{tenant.id}' - {tenant.name}")
            click.echo(f"  Status: {tenant.status.value}")
            click.echo(f"  Max Jobs: {tenant.quotas.max_jobs}")
            click.echo(f"  Max Workers: {tenant.quotas.max_workers}")
            click.echo(f"  Storage: {tenant.quotas.storage_limit_mb} MB")

        except Exception as e:
            click.echo(f"✗ Failed to create tenant: {e}", err=True)
            raise click.Abort() from None


@tenant_cli.command(name="list")
@click.option(
    "--status", type=click.Choice(["active", "suspended", "disabled", "all"]), default="all"
)
@click.option("--limit", "-l", type=int, default=50, help="Maximum tenants to display")
def list_tenants(status: str, limit: int) -> None:
    """List all tenants."""
    with get_tenant_manager() as manager:
        if status == "all":
            tenants = manager.list_all(limit=limit)
        else:
            tenants = manager.list_all(status=TenantStatus(status), limit=limit)

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

        click.echo(f"{'ID':<20} {'Name':<30} {'Status':<12} {'Jobs':<8} {'Workers':<8}")
        click.echo("-" * 80)

        for tenant in tenants:
            click.echo(
                f"{tenant.id:<20} {tenant.name:<30} {tenant.status.value:<12} "
                f"{tenant.quotas.max_jobs:<8} {tenant.quotas.max_workers:<8}"
            )


@tenant_cli.command(name="show")
@click.argument("tenant-id")
def show_tenant(tenant_id: str) -> None:
    """Show detailed information about a tenant."""
    with get_tenant_manager() as manager:
        try:
            tenant = manager.get(tenant_id)
            usage = manager.get_usage(tenant_id)
            quota_status = manager.get_quota_status(tenant_id)

            click.echo(f"Tenant: {tenant.name} ({tenant.id})")
            click.echo(f"Description: {tenant.description or 'N/A'}")
            click.echo(f"Status: {tenant.status.value}")
            click.echo(f"Created: {tenant.created_at.isoformat()}")
            click.echo(f"Updated: {tenant.updated_at.isoformat()}")
            click.echo()

            click.echo("Quotas:")
            click.echo(f"  Max Jobs: {tenant.quotas.max_jobs}")
            click.echo(f"  Max Workers: {tenant.quotas.max_workers}")
            click.echo(f"  Storage Limit: {tenant.quotas.storage_limit_mb} MB")
            click.echo(f"  Max Requests/Min: {tenant.quotas.max_requests_per_minute}")
            click.echo(f"  Max Sessions: {tenant.quotas.max_concurrent_sessions}")
            click.echo()

            click.echo("Usage:")
            click.echo(f"  Jobs: {usage.job_count}")
            click.echo(f"  Workers: {usage.worker_count}")
            click.echo(f"  Storage: {usage.storage_mb} MB")
            click.echo(f"  Sessions: {usage.session_count}")
            click.echo(f"  Requests: {usage.request_count}")
            click.echo()

            click.echo("Quota Status:")
            for quota_name, status in quota_status.items():
                pct = status["percent"]
                indicator = "✓" if pct < 75 else "⚠" if pct < 90 else "✗"
                click.echo(
                    f"  {indicator} {quota_name}: {status['used']}/{status['limit']} " f"({pct}%)"
                )
            click.echo()

            click.echo("Features:")
            for feature, enabled in tenant.config.features.items():
                status = "✓ enabled" if enabled else "✗ disabled"
                click.echo(f"  {feature}: {status}")

            if tenant.config.allowed_origins:
                click.echo()
                click.echo("Allowed Origins:")
                for origin in tenant.config.allowed_origins:
                    click.echo(f"  - {origin}")

            if tenant.config.api_keys:
                click.echo()
                click.echo(f"API Keys: {len(tenant.config.api_keys)} configured")

        except TenantNotFoundError:
            click.echo(f"✗ Tenant '{tenant_id}' not found", err=True)
            raise click.Abort() from None


@tenant_cli.command(name="update")
@click.argument("tenant-id")
@click.option("--name", "-n", help="New tenant name")
@click.option("--description", "-d", help="New description")
@click.option("--max-jobs", type=int, help="Maximum concurrent jobs")
@click.option("--max-workers", type=int, help="Maximum workers")
@click.option("--storage-limit", type=int, help="Storage limit in MB")
def update_tenant(
    tenant_id: str,
    name: str | None,
    description: str | None,
    max_jobs: int | None,
    max_workers: int | None,
    storage_limit: int | None,
) -> None:
    """Update an existing tenant."""
    with get_tenant_manager() as manager:
        try:
            tenant = manager.get(tenant_id)

            if name:
                tenant.name = name
            if description:
                tenant.description = description
            if max_jobs is not None:
                tenant.quotas.max_jobs = max_jobs
            if max_workers is not None:
                tenant.quotas.max_workers = max_workers
            if storage_limit is not None:
                tenant.quotas.storage_limit_mb = storage_limit

            manager.update(tenant)
            click.echo(f"✓ Updated tenant '{tenant_id}'")

        except TenantNotFoundError:
            click.echo(f"✗ Tenant '{tenant_id}' not found", err=True)
            raise click.Abort() from None


@tenant_cli.command(name="delete")
@click.argument("tenant-id")
@click.confirmation_option(prompt="Are you sure you want to delete this tenant?")
def delete_tenant(tenant_id: str) -> None:
    """Delete a tenant."""
    with get_tenant_manager() as manager:
        try:
            if manager.delete(tenant_id):
                click.echo(f"✓ Deleted tenant '{tenant_id}'")
            else:
                click.echo(f"✗ Tenant '{tenant_id}' not found", err=True)
                raise click.Abort() from None
        except Exception as e:
            click.echo(f"✗ Failed to delete tenant: {e}", err=True)
            raise click.Abort() from None


@tenant_cli.command(name="suspend")
@click.argument("tenant-id")
def suspend_tenant(tenant_id: str) -> None:
    """Suspend a tenant (disable access but keep data)."""
    with get_tenant_manager() as manager:
        try:
            manager.suspend(tenant_id)
            click.echo(f"✓ Suspended tenant '{tenant_id}'")
        except TenantNotFoundError:
            click.echo(f"✗ Tenant '{tenant_id}' not found", err=True)
            raise click.Abort() from None


@tenant_cli.command(name="activate")
@click.argument("tenant-id")
def activate_tenant(tenant_id: str) -> None:
    """Activate a suspended tenant."""
    with get_tenant_manager() as manager:
        try:
            manager.activate(tenant_id)
            click.echo(f"✓ Activated tenant '{tenant_id}'")
        except TenantNotFoundError:
            click.echo(f"✗ Tenant '{tenant_id}' not found", err=True)
            raise click.Abort() from None


@tenant_cli.command(name="api-key")
@click.argument("tenant-id")
@click.option("--add", "add_key", help="Add a new API key")
@click.option("--remove", "remove_key", help="Remove an API key")
@click.option("--list", "list_keys", is_flag=True, help="List API keys")
def manage_api_keys(
    tenant_id: str,
    add_key: str | None,
    remove_key: str | None,
    list_keys: bool,
) -> None:
    """Manage API keys for a tenant."""
    with get_tenant_manager() as manager:
        try:
            tenant = manager.get(tenant_id)

            if list_keys:
                if tenant.config.api_keys:
                    click.echo(f"API keys for '{tenant_id}':")
                    for key in tenant.config.api_keys:
                        masked = key[:8] + "..." + key[-4:] if len(key) > 12 else key
                        click.echo(f"  - {masked}")
                else:
                    click.echo(f"No API keys configured for '{tenant_id}'")
                return

            if add_key:
                if add_key not in tenant.config.api_keys:
                    tenant.config.api_keys.append(add_key)
                    manager.update(tenant)
                    click.echo(f"✓ Added API key to tenant '{tenant_id}'")
                else:
                    click.echo("API key already exists")

            if remove_key:
                if remove_key in tenant.config.api_keys:
                    tenant.config.api_keys.remove(remove_key)
                    manager.update(tenant)
                    click.echo(f"✓ Removed API key from tenant '{tenant_id}'")
                else:
                    click.echo("API key not found")

        except TenantNotFoundError:
            click.echo(f"✗ Tenant '{tenant_id}' not found", err=True)
            raise click.Abort() from None


@tenant_cli.command(name="feature")
@click.argument("tenant-id")
@click.argument("feature-name")
@click.argument("action", type=click.Choice(["enable", "disable"]))
def manage_feature(tenant_id: str, feature_name: str, action: str) -> None:
    """Enable or disable a feature for a tenant."""
    with get_tenant_manager() as manager:
        try:
            tenant = manager.get(tenant_id)

            tenant.config.features[feature_name] = action == "enable"
            manager.update(tenant)

            status = "enabled" if action == "enable" else "disabled"
            click.echo(f"✓ {status.capitalize()} feature '{feature_name}' for tenant '{tenant_id}'")

        except TenantNotFoundError:
            click.echo(f"✗ Tenant '{tenant_id}' not found", err=True)
            raise click.Abort() from None


@tenant_cli.command(name="origin")
@click.argument("tenant-id")
@click.option("--add", "add_origin", help="Add an allowed origin")
@click.option("--remove", "remove_origin", help="Remove an allowed origin")
@click.option("--list", "list_origins", is_flag=True, help="List allowed origins")
def manage_origins(
    tenant_id: str,
    add_origin: str | None,
    remove_origin: str | None,
    list_origins: bool,
) -> None:
    """Manage allowed CORS origins for a tenant."""
    with get_tenant_manager() as manager:
        try:
            tenant = manager.get(tenant_id)

            if list_origins:
                if tenant.config.allowed_origins:
                    click.echo(f"Allowed origins for '{tenant_id}':")
                    for origin in tenant.config.allowed_origins:
                        click.echo(f"  - {origin}")
                else:
                    click.echo(f"No allowed origins configured for '{tenant_id}'")
                return

            if add_origin:
                if add_origin not in tenant.config.allowed_origins:
                    tenant.config.allowed_origins.append(add_origin)
                    manager.update(tenant)
                    click.echo(f"✓ Added origin '{add_origin}' to tenant '{tenant_id}'")
                else:
                    click.echo("Origin already exists")

            if remove_origin:
                if remove_origin in tenant.config.allowed_origins:
                    tenant.config.allowed_origins.remove(remove_origin)
                    manager.update(tenant)
                    click.echo(f"✓ Removed origin '{remove_origin}' from tenant '{tenant_id}'")
                else:
                    click.echo("Origin not found")

        except TenantNotFoundError:
            click.echo(f"✗ Tenant '{tenant_id}' not found", err=True)
            raise click.Abort() from None


@tenant_cli.command(name="usage")
@click.argument("tenant-id")
def show_usage(tenant_id: str) -> None:
    """Show current resource usage for a tenant."""
    with get_tenant_manager() as manager:
        try:
            manager.get_usage(tenant_id)
            quota_status = manager.get_quota_status(tenant_id)

            click.echo(f"Resource Usage for '{tenant_id}':")
            click.echo()

            for quota_name, status in quota_status.items():
                pct = status["percent"]
                bar_length = 30
                filled = int(bar_length * pct / 100)
                bar = "█" * filled + "░" * (bar_length - filled)

                click.echo(f"{quota_name}:")
                click.echo(f"  [{bar}] {pct}%")
                click.echo(
                    f"  {status['used']} / {status['limit']} used ({status['remaining']} remaining)"
                )
                click.echo()

        except TenantNotFoundError:
            click.echo(f"✗ Tenant '{tenant_id}' not found", err=True)
            raise click.Abort() from None
