"""Gateway logging configuration with local file and optional GCS sync."""

from __future__ import annotations

import logging
import sys
from pathlib import Path
from typing import Optional

from .logging_sinks import (
    CompositeLogSink,
    FileLogSink,
    GCSLogSink,
    LogSink,
    SinkHandler,
)
from .settings import GatewaySettings

_LOGGER_ROOT = "ember.gateway"
_TELEMETRY_LOGGER = "ember.gateway.eb1.telemetry"
_logger = logging.getLogger(__name__)


def configure_gateway_logging(settings: GatewaySettings) -> Optional[Path]:
    """Configure gateway loggers with local file and optional cloud sinks.

    When cloud_logging is enabled and gcs_bucket is set, logs are written both
    locally and synced to GCS. Uses Application Default Credentials (ADC).

    Args:
        settings: Gateway configuration with logging and cloud_logging sections.

    Returns:
        The resolved local log path when logging is enabled, otherwise None.

    Raises:
        RuntimeError: If the log path cannot be created or opened, or if GCS logging
            is explicitly configured but fails to init.
    """
    log_settings = getattr(settings, "logging", None)
    if log_settings is None or log_settings.enabled is False:
        return None

    level_name = (log_settings.level or "INFO").upper()
    level = getattr(logging, level_name, logging.INFO)

    logger = logging.getLogger(_LOGGER_ROOT)
    logger.setLevel(level)
    logger.propagate = True

    # Ensure telemetry logger is explicitly set to INFO for observability.
    # This must happen before get_telemetry() is first called to avoid
    # caching NullTelemetry due to uninitialized logger level.
    telemetry_logger = logging.getLogger(_TELEMETRY_LOGGER)
    telemetry_logger.setLevel(logging.INFO)

    # Add stdout handler for telemetry so it's captured by systemd/journalctl
    # even when no file path is configured. Check for existing handler to avoid
    # duplicates on reconfiguration.
    if not any(isinstance(h, logging.StreamHandler) for h in telemetry_logger.handlers):
        telemetry_handler = logging.StreamHandler(sys.stdout)
        telemetry_handler.setLevel(logging.INFO)
        telemetry_handler.setFormatter(logging.Formatter("%(message)s"))
        telemetry_logger.addHandler(telemetry_handler)
        telemetry_logger.propagate = False  # Avoid duplicate output

    if not log_settings.path:
        return None

    target_path = Path(log_settings.path).expanduser()

    try:
        target_path.parent.mkdir(parents=True, exist_ok=True)
    except OSError as exc:
        raise RuntimeError(
            f"Failed to create gateway log directory {target_path.parent}"
        ) from exc

    # Remove existing SinkHandlers to avoid duplicates on reconfiguration
    for handler in logger.handlers[:]:
        if isinstance(handler, SinkHandler):
            handler.close()
            logger.removeHandler(handler)

    # Build composite sink: local file + optional GCS
    sinks: list[LogSink] = []

    try:
        sinks.append(FileLogSink(target_path))
    except OSError as exc:
        raise RuntimeError(f"Failed to open gateway log file {target_path}") from exc

    cloud_settings = getattr(settings, "cloud_logging", None)
    if cloud_settings and cloud_settings.enabled and cloud_settings.gcs_bucket:
        try:
            gcs_sink = GCSLogSink(
                bucket=cloud_settings.gcs_bucket,
                prefix=cloud_settings.gcs_prefix,
                batch_size=cloud_settings.batch_size,
                flush_interval_seconds=cloud_settings.sync_interval_seconds,
            )
            sinks.append(gcs_sink)
            _logger.info(
                "GCS log sync enabled: gs://%s/%s",
                cloud_settings.gcs_bucket,
                cloud_settings.gcs_prefix,
            )
        except ImportError as exc:
            # Fail-closed: GCS explicitly configured but package not installed
            raise RuntimeError(
                f"GCS logging configured but google-cloud-storage not installed: {exc}"
            ) from exc
        except Exception as exc:
            # Fail-closed: GCS explicitly configured but initialization failed
            raise RuntimeError(f"GCS logging configured but initialization failed: {exc}") from exc

    composite_sink = CompositeLogSink(sinks)
    handler = SinkHandler(composite_sink)
    handler.setLevel(level)

    logger.addHandler(handler)

    return target_path


__all__ = ["configure_gateway_logging"]
