"""Command-line interface for Azure discovery."""

from __future__ import annotations

import asyncio
import json
import sys
from pathlib import Path
from typing import List, Optional

import typer

from .orchestrator import run_discovery
from .adt_types import (
    AzureDiscoveryRequest,
    AzureEnvironment,
    DiscoveryFilter,
    VisualizationOptions,
)
from .utils.logging import get_logger

cli = typer.Typer(help="Azure tenant discovery and visualization CLI")


def _parse_tags(tag_args: Optional[List[str]]) -> Optional[dict]:
    if not tag_args:
        return None
    tags = {}
    for tag_arg in tag_args:
        if "=" not in tag_arg:
            raise typer.BadParameter("Tags must use key=value syntax")
        key, value = tag_arg.split("=", 1)
        tags[key.strip()] = value.strip()
    return tags


@cli.command("discover")
def discover_command(
    tenant_id: str = typer.Option(..., help="Azure AD tenant identifier"),
    environment: AzureEnvironment = typer.Option(
        AzureEnvironment.AZURE_PUBLIC, help="Azure cloud environment"
    ),
    subscription: Optional[List[str]] = typer.Option(
        None, "--subscription", "-s", help="Explicit subscription identifier"
    ),
    include_type: Optional[List[str]] = typer.Option(
        None, "--include-type", help="Resource type to include (repeatable)"
    ),
    exclude_type: Optional[List[str]] = typer.Option(
        None, "--exclude-type", help="Resource type to exclude (repeatable)"
    ),
    resource_group: Optional[List[str]] = typer.Option(
        None, "--resource-group", help="Resource group filter (repeatable)"
    ),
    required_tag: Optional[List[str]] = typer.Option(
        None, "--required-tag", help="Required tag key=value (repeatable)"
    ),
    prefer_cli: bool = typer.Option(
        False, "--prefer-cli", help="Prefer Azure CLI credential in chain"
    ),
    visualization_output_dir: Path = typer.Option(
        Path("artifacts/graphs"),
        "--visualization-output-dir",
        help="Directory for HTML output",
    ),
    visualization_file: Optional[str] = typer.Option(
        None, "--visualization-file", help="Optional HTML file name"
    ),
    output: Optional[Path] = typer.Option(
        None, "--output", "-o", help="Write JSON output to file instead of stdout"
    ),
    quiet: bool = typer.Option(
        False, "--quiet", "-q", help="Suppress all logs except errors"
    ),
    format: str = typer.Option(
        "json", "--format", "-f", help="Output format: json, json-compact"
    ),
) -> None:
    """Discover Azure resources and emit JSON output.

    By default, JSON is written to stdout and logs go to stderr.
    Use --output to write JSON to a file.
    Use --quiet to suppress all logs except errors.
    """

    # Initialize logger with quiet mode
    get_logger(quiet=quiet)

    tag_filters = _parse_tags(required_tag)
    discovery_filter = DiscoveryFilter(
        include_types=include_type,
        exclude_types=exclude_type,
        required_tags=tag_filters,
        resource_groups=resource_group,
    )
    visualization_options = VisualizationOptions(
        output_dir=visualization_output_dir,
        file_name=visualization_file,
    )
    request = AzureDiscoveryRequest(
        tenant_id=tenant_id,
        environment=environment,
        subscriptions=subscription,
        filter=discovery_filter,
        prefer_cli_credentials=prefer_cli,
        visualization=visualization_options,
    )
    response = asyncio.run(run_discovery(request))

    # Format output based on format option
    if format == "json-compact":
        json_output = json.dumps(response.model_dump(), default=str)
    else:  # json
        json_output = json.dumps(response.model_dump(), indent=2, default=str)

    # Write output to file or stdout
    if output:
        output.parent.mkdir(parents=True, exist_ok=True)
        output.write_text(json_output)
        # Log to stderr that output was written
        typer.echo(f"Discovery results written to {output}", err=True)
    else:
        # Write JSON to stdout (clean output for piping)
        sys.stdout.write(json_output + "\n")


def main() -> None:
    cli()


if __name__ == "__main__":
    main()
