"""Fluentd backend for logging to Fluentd."""

import asyncio
import json
from dataclasses import dataclass
from typing import Any

from ..core.backend import BackendConfig, LoggingBackend, LogRecord
from ..formatters import JSONFormatter, LogFormatter

try:
    from fluent import sender
    FLUENTD_AVAILABLE = True
except ImportError:
    FLUENTD_AVAILABLE = False
    sender = None


@dataclass
class FluentdBackendConfig(BackendConfig):
    """Configuration for Fluentd backend."""

    enabled: bool = True
    timeout: float = 5.0
    retry_attempts: int = 3
    retry_delay: float = 1.0
    host: str = "localhost"
    port: int = 24224
    tag: str = "unified_logger"
    buffer_size: int = 1024 * 1024  # 1MB


class FluentdBackend(LoggingBackend):
    """Backend that sends logs to Fluentd via fluent-logger."""

    def __init__(
        self,
        name: str = "fluentd",
        config: FluentdBackendConfig | None = None,
        formatter: LogFormatter | None = None,
        **kwargs: Any
    ) -> None:
        """Initialize Fluentd backend.
        
        Args:
            name: Backend name
            config: Backend configuration
            formatter: Log formatter to use (defaults to JSON)
            **kwargs: Additional configuration
        """
        self.config = config or FluentdBackendConfig()
        super().__init__(name, self.config, **kwargs)

        self.formatter = formatter or JSONFormatter()
        self._sender = None

    async def connect(self) -> bool:
        """Connect to Fluentd."""
        if not FLUENTD_AVAILABLE:
            return False

        try:
            # Initialize fluent sender
            self._sender = sender.FluentSender(
                tag=self.config.tag,
                host=self.config.host,
                port=self.config.port,
                timeout=3.0,
                verbose=False
            )

            # Test connection by sending a dummy message
            test_record = {'test': True, 'timestamp': int(asyncio.get_event_loop().time())}
            success = await asyncio.get_event_loop().run_in_executor(
                None, self._sender.emit, 'connection_test', test_record
            )

            if success:
                self._connected = True
                return True
            else:
                return False

        except Exception as e:
            print(f"Failed to connect to Fluentd: {e}")
            return False

    async def disconnect(self) -> bool:
        """Disconnect from Fluentd."""
        try:
            if hasattr(self, '_sender') and self._sender:
                # Close the fluent sender
                await asyncio.get_event_loop().run_in_executor(
                    None, self._sender.close
                )
                self._sender = None
            self._connected = False
            return True
        except Exception as e:
            print(f"Failed to disconnect from Fluentd: {e}")
            return False

    async def send_log(self, record: LogRecord) -> bool:
        """Send a single log record to Fluentd."""
        if not self._connected or not hasattr(self, '_sender') or not self._sender:
            return False

        try:
            # Format the log record
            import logging
            level_name = logging.getLevelName(record.level).lower()
            
            if isinstance(self.formatter, JSONFormatter):
                formatted_data = self.formatter.format(record)
                data = json.loads(formatted_data) if isinstance(formatted_data, str) else formatted_data
            else:
                # For plain text formatter, create a structured message
                timestamp_val = int(record.timestamp.timestamp())
                data = {
                    'level': level_name,
                    'message': self.formatter.format(record),
                    'logger': record.logger_name,
                    'timestamp': timestamp_val,
                    **record.extra
                }

            # Send to Fluentd using the sender
            result = await asyncio.get_event_loop().run_in_executor(
                None, self._sender.emit, f"{self.config.tag}.{level_name}", data
            )

            return result if isinstance(result, bool) else False

        except Exception as e:
            print(f"Failed to send log to Fluentd: {e}")
            return False

    async def send_logs_batch(self, records: list[LogRecord]) -> list[bool]:
        """Send multiple log records as a batch to Fluentd.
        
        Args:
            records: List of log records to send
            
        Returns:
            List of success/failure status for each record
        """
        # Fluentd typically doesn't have a native batch API,
        # so we send records individually but in parallel
        tasks = [self.send_log(record) for record in records]
        results = await asyncio.gather(*tasks, return_exceptions=True)

        # Convert exceptions to False
        return [
            result if isinstance(result, bool) else False
            for result in results
        ]

    async def health_check(self) -> bool:
        """Check if the Fluentd connection is healthy."""
        if not self._connected or not hasattr(self, '_sender') or not self._sender:
            return False

        try:
            # Send a test message to verify connectivity
            test_record = {
                'health_check': True,
                'timestamp': int(asyncio.get_event_loop().time())
            }

            result = await asyncio.get_event_loop().run_in_executor(
                None, self._sender.emit, f"{self.config.tag}.health_check", test_record
            )

            return result if isinstance(result, bool) else False

        except Exception as e:
            print(f"Health check failed: {e}")
            return False
