"""Main CLI interface using Click."""

import asyncio
import json
import logging
from pathlib import Path
from typing import Optional

import click

from ..core import UnifiedLogger
from ..formatters import JSONFormatter, PlainFormatter
from ..handlers import (
    ConsoleBackend,
    ElasticsearchBackend,
    FileBackend,
    FluentdBackend,
    JaegerBackend,
    KafkaBackend,
)


@click.group()
@click.option('--config', '-c', type=click.Path(exists=True), help='Configuration file path')
@click.option('--verbose', '-v', is_flag=True, help='Enable verbose output')
@click.pass_context
def cli(ctx: click.Context, config: str | None, verbose: bool) -> None:
    """Unified Logger CLI - Interface to backend logging systems."""
    ctx.ensure_object(dict)
    ctx.obj['config_file'] = config
    ctx.obj['verbose'] = verbose

    if verbose:
        logging.basicConfig(level=logging.DEBUG)


@cli.command()
@click.option('--message', '-m', required=True, help='Log message to send')
@click.option('--level', '-l', default='INFO',
              type=click.Choice(['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']),
              help='Log level')
@click.option('--backend', '-b', multiple=True,
              type=click.Choice(['console', 'file', 'elasticsearch', 'fluentd', 'kafka', 'jaeger']),
              help='Backend(s) to use (can be specified multiple times)')
@click.option('--format-type', '-f', default='json',
              type=click.Choice(['json', 'plain']),
              help='Log format type')
@click.option('--extra', '-e', multiple=True,
              help='Extra fields in key=value format')
@click.pass_context
def send(
    ctx: click.Context,
    message: str,
    level: str,
    backend: tuple[str, ...],
    format_type: str,
    extra: tuple[str, ...]
) -> None:
    """Send a log message to configured backends."""

    async def _send_log() -> None:
        # Parse extra fields
        extra_dict = {}
        for item in extra:
            if '=' in item:
                key, value = item.split('=', 1)
                extra_dict[key] = value
            else:
                click.echo(f"Warning: Ignoring malformed extra field: {item}", err=True)

        # Create logger
        logger = UnifiedLogger(
            name="cli_logger",
            level=getattr(logging, level),
            format_type=format_type
        )

        # Add specified backends or default ones
        backends_to_use = list(backend) if backend else ['console']

        for backend_name in backends_to_use:
            backend_instance = _create_backend(backend_name, format_type, ctx.obj.get('config_file'))
            if backend_instance:
                logger.add_backend(backend_instance)

        # Connect and send log
        async with logger:
            log_method = getattr(logger, level.lower())
            await log_method(message, extra=extra_dict if extra_dict else None)
            await logger.flush()

        if ctx.obj['verbose']:
            click.echo(f"Successfully sent {level} log to {len(backends_to_use)} backend(s)")

    asyncio.run(_send_log())


@cli.command()
@click.option('--backend', '-b', multiple=True,
              type=click.Choice(['console', 'file', 'elasticsearch', 'fluentd', 'kafka', 'jaeger']),
              help='Backend(s) to test (can be specified multiple times)')
@click.pass_context
def test(ctx: click.Context, backend: tuple[str, ...]) -> None:
    """Test connectivity to backends."""

    async def _test_backends() -> None:
        backends_to_test = list(backend) if backend else [
            'console', 'file', 'elasticsearch', 'fluentd', 'kafka', 'jaeger'
        ]

        click.echo("Testing backend connectivity...")

        for backend_name in backends_to_test:
            backend_instance = _create_backend(backend_name, 'json', ctx.obj.get('config_file'))
            if not backend_instance:
                click.echo(f"❌ {backend_name}: Failed to create backend")
                continue

            try:
                await backend_instance.connect()
                is_healthy = await backend_instance.health_check()
                await backend_instance.disconnect()

                status = "✅" if is_healthy else "⚠️"
                click.echo(f"{status} {backend_name}: {'Healthy' if is_healthy else 'Connected but unhealthy'}")

            except Exception as e:
                click.echo(f"❌ {backend_name}: {str(e)}")

    asyncio.run(_test_backends())


@cli.command()
@click.option('--output', '-o', type=click.Path(), help='Output file path (default: stdout)')
def config_template(output: str | None) -> None:
    """Generate a configuration file template."""
    template = {
        "logger": {
            "name": "unified_logger",
            "level": "INFO",
            "format_type": "json",
            "enable_standard_logging": True,
            "max_workers": 4,
            "batch_size": 100,
            "batch_timeout": 5.0,
            "backends": ["console", "file"]
        },
        "backends": {
            "console": {
                "enabled": True,
                "timeout": 1.0,
                "retry_attempts": 0,
                "retry_delay": 0.1,
                "stream": "stdout",
                "use_colors": True
            },
            "file": {
                "enabled": True,
                "timeout": 5.0,
                "retry_attempts": 3,
                "retry_delay": 0.5,
                "file_path": "app.log",
                "max_bytes": 10485760,
                "backup_count": 5,
                "encoding": "utf-8",
                "create_dirs": True
            },
            "elasticsearch": {
                "enabled": False,
                "timeout": 10.0,
                "retry_attempts": 3,
                "retry_delay": 1.0,
                "host": "localhost",
                "port": 9200,
                "index_prefix": "logs",
                "username": None,
                "password": None,
                "use_ssl": False,
                "verify_certs": True,
                "batch_size": 100
            },
            "fluentd": {
                "enabled": False,
                "timeout": 5.0,
                "retry_attempts": 3,
                "retry_delay": 1.0,
                "host": "localhost",
                "port": 24224,
                "tag": "app.logs",
                "buffer_size": 1048576
            },
            "kafka": {
                "enabled": False,
                "timeout": 10.0,
                "retry_attempts": 3,
                "retry_delay": 1.0,
                "bootstrap_servers": "localhost:9092",
                "topic": "logs",
                "batch_size": 100,
                "compression_type": "gzip",
                "acks": "1"
            },
            "jaeger": {
                "enabled": False,
                "timeout": 5.0,
                "retry_attempts": 3,
                "retry_delay": 1.0,
                "collector_endpoint": "http://localhost:14268/api/traces",
                "service_name": "unified-logger",
                "batch_size": 100
            }
        }
    }

    config_json = json.dumps(template, indent=2)

    if output:
        Path(output).write_text(config_json)
        click.echo(f"Configuration template written to: {output}")
    else:
        click.echo(config_json)


def _create_backend(backend_name: str, format_type: str, config_file: Optional[str]):
    """Create a backend instance with configuration from file or defaults.
    
    Args:
        backend_name: Name of the backend to create
        format_type: Format type for the formatter (json or plain)
        config_file: Optional path to configuration file
        
    Returns:
        Backend instance or None if backend not found
    """
    
    # Load configuration from file if provided
    backend_config_dict = None
    if config_file:
        try:
            from ..config import load_config, get_backend_config
            full_config = load_config(config_file)
            backend_config_dict = get_backend_config(full_config, backend_name)
        except Exception as e:
            # If config loading fails, warn but continue with defaults
            click.echo(f"Warning: Failed to load config for {backend_name}: {e}", err=True)
    
    # Create appropriate formatter
    if format_type == 'json':
        formatter = JSONFormatter()
    else:
        formatter = PlainFormatter()
    
    # Create backend with config from file or defaults
    if backend_name == 'console':
        from ..handlers.console import ConsoleBackendConfig
        config = ConsoleBackendConfig.from_config(backend_config_dict) if backend_config_dict else ConsoleBackendConfig()
        return ConsoleBackend(
            config=config, 
            formatter=formatter
        )
    elif backend_name == 'file':
        from ..handlers.file import FileBackendConfig
        config = FileBackendConfig.from_config(backend_config_dict) if backend_config_dict else FileBackendConfig()
        return FileBackend(
            config=config,
            formatter=formatter
        )
    elif backend_name == 'elasticsearch':
        from ..handlers.elasticsearch import ElasticsearchBackendConfig
        config = ElasticsearchBackendConfig.from_config(backend_config_dict) if backend_config_dict else ElasticsearchBackendConfig()
        return ElasticsearchBackend(
            config=config,
            formatter=formatter
        )
    elif backend_name == 'fluentd':
        from ..handlers.fluentd import FluentdBackendConfig
        config = FluentdBackendConfig.from_config(backend_config_dict) if backend_config_dict else FluentdBackendConfig()
        return FluentdBackend(
            config=config,
            formatter=formatter
        )
    elif backend_name == 'kafka':
        from ..handlers.kafka import KafkaBackendConfig
        config = KafkaBackendConfig.from_config(backend_config_dict) if backend_config_dict else KafkaBackendConfig()
        return KafkaBackend(
            config=config,
            formatter=formatter
        )
    elif backend_name == 'jaeger':
        from ..handlers.jaeger import JaegerBackendConfig
        config = JaegerBackendConfig.from_config(backend_config_dict) if backend_config_dict else JaegerBackendConfig()
        return JaegerBackend(
            config=config,
            formatter=formatter
        )
    
    return None


if __name__ == '__main__':
    cli()
