"""Structured logging for Tru-Guard operations."""

import logging
import time
from typing import Any


class TruGuardLogger:
    """Structured logging for Tru-Guard operations."""

    def __init__(self, name: str = "trusys", level: int = logging.INFO) -> None:
        """Initialize the logger.

        Args:
            name: Logger name
            level: Logging level
        """
        self.logger = logging.getLogger(name)
        self.logger.setLevel(level)
        self._enabled = True

        # Add handler if none exists
        if not self.logger.handlers:
            handler = logging.StreamHandler()
            handler.setLevel(level)
            formatter = logging.Formatter(
                "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
            )
            handler.setFormatter(formatter)
            self.logger.addHandler(handler)

    def enable(self) -> None:
        """Enable logging."""
        self._enabled = True

    def disable(self) -> None:
        """Disable logging."""
        self._enabled = False

    def _log(self, level: int, message: str, **kwargs: Any) -> None:
        """Internal logging method with extra context."""
        if not self._enabled:
            return
        extra = {"extra_data": kwargs} if kwargs else {}
        self.logger.log(level, message, extra=extra)

    def set_level(self, level: int) -> None:
        """Set logging level (e.g. logging.INFO or logging.DEBUG). Debug only when debug_print is enabled."""
        self.logger.setLevel(level)
        for handler in self.logger.handlers:
            handler.setLevel(level)

    def scan_started(
        self,
        scan_type: str,
        scanner_count: int,
        execution_mode: str | None = None,
    ) -> None:
        """Log scan started event (DEBUG level; only shown when debug_print is enabled)."""
        self._log(
            logging.DEBUG,
            f"Scan started: type={scan_type}, scanners={scanner_count}, mode={execution_mode}",
            scan_type=scan_type,
            scanner_count=scanner_count,
            execution_mode=execution_mode,
        )

    def scanner_started(self, scanner_name: str, scan_type: str) -> None:
        """Log scanner started event."""
        self._log(
            logging.DEBUG,
            f"Scanner started: {scanner_name} ({scan_type})",
            scanner=scanner_name,
            scan_type=scan_type,
        )

    def scanner_completed(
        self,
        scanner_name: str,
        passed: bool,
        execution_time_ms: float,
        violations_count: int,
    ) -> None:
        """Log scanner completed event (DEBUG level; only shown when debug_print is enabled)."""
        status = "PASSED" if passed else "FAILED"
        self._log(
            logging.DEBUG,
            f"Scanner completed: {scanner_name} - {status} ({execution_time_ms:.2f}ms, {violations_count} violations)",
            scanner=scanner_name,
            passed=passed,
            execution_time_ms=execution_time_ms,
            violations=violations_count,
        )

    def scanner_error(self, scanner_name: str, error: Exception) -> None:
        """Log scanner error event."""
        self._log(
            logging.ERROR,
            f"Scanner error: {scanner_name} - {error}",
            scanner=scanner_name,
            error=str(error),
            error_type=type(error).__name__,
        )

    def scanner_timeout(self, scanner_name: str, timeout: float) -> None:
        """Log scanner timeout event."""
        self._log(
            logging.WARNING,
            f"Scanner timeout: {scanner_name} exceeded {timeout}s",
            scanner=scanner_name,
            timeout=timeout,
        )

    def action_taken(
        self,
        action_type: str,
        scanner_name: str,
        content_modified: bool = False,
    ) -> None:
        """Log action taken event (INFO level; e.g. after a validator fails and filter/fix is applied)."""
        self._log(
            logging.INFO,
            f"Action taken: {action_type} by {scanner_name} (modified={content_modified})",
            action=action_type,
            scanner=scanner_name,
            content_modified=content_modified,
        )

    def action_conflict(self, conflicts: list[str], resolved_to: str) -> None:
        """Log action conflict resolution."""
        self._log(
            logging.WARNING,
            f"Action conflict resolved: {conflicts} -> {resolved_to}",
            conflicts=conflicts,
            resolved_to=resolved_to,
        )

    def scan_completed(
        self,
        passed: bool,
        total_time_ms: float,
        scanners_run: int,
        violations_total: int,
    ) -> None:
        """Log scan completed event (DEBUG level; only shown when debug_print is enabled)."""
        status = "PASSED" if passed else "FAILED"
        self._log(
            logging.DEBUG,
            f"Scan completed: {status} ({total_time_ms:.2f}ms, {scanners_run} scanners, {violations_total} violations)",
            passed=passed,
            total_time_ms=total_time_ms,
            scanners_run=scanners_run,
            violations_total=violations_total,
        )

    def warning(self, message: str, **kwargs: Any) -> None:
        """Log a warning message."""
        self._log(logging.WARNING, message, **kwargs)

    def error(self, message: str, **kwargs: Any) -> None:
        """Log an error message."""
        self._log(logging.ERROR, message, **kwargs)

    def info(self, message: str, **kwargs: Any) -> None:
        """Log an info message."""
        self._log(logging.INFO, message, **kwargs)

    def debug(self, message: str, **kwargs: Any) -> None:
        """Log a debug message."""
        self._log(logging.DEBUG, message, **kwargs)


# Global logger instance
_logger: TruGuardLogger | None = None


def get_logger() -> TruGuardLogger:
    """Get the global TruGuard logger instance."""
    global _logger
    if _logger is None:
        _logger = TruGuardLogger()
    return _logger


def set_logger(logger: TruGuardLogger) -> None:
    """Set the global TruGuard logger instance."""
    global _logger
    _logger = logger


class Timer:
    """Context manager for timing operations."""

    def __init__(self) -> None:
        self.start_time: float = 0
        self.end_time: float = 0
        self._elapsed_ms: float = 0

    def __enter__(self) -> "Timer":
        self.start_time = time.perf_counter()
        return self

    def __exit__(self, *args: Any) -> None:
        self.end_time = time.perf_counter()
        self._elapsed_ms = (self.end_time - self.start_time) * 1000

    @property
    def elapsed_ms(self) -> float:
        """Get elapsed time in milliseconds.
        
        Can be called during or after the timer context.
        During the context, returns current elapsed time.
        After the context, returns final elapsed time.
        """
        if self._elapsed_ms > 0:
            # Timer has finished, return cached value
            return self._elapsed_ms
        elif self.start_time > 0:
            # Timer is running, calculate current elapsed time
            return (time.perf_counter() - self.start_time) * 1000
        else:
            return 0.0
