"""Trust Tax Auditor for measuring validation overhead.

This module provides the Auditor class that implements the AuditHook protocol
and collects metrics about validation performance.
"""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import TYPE_CHECKING

from axm.logging import get_logger

if TYPE_CHECKING:
    from axm.catalog.rules.engine import DataQualityReport

logger = get_logger("axm-audit")


@dataclass
class AuditMetrics:
    """Accumulated metrics for validation sessions."""

    total_validations: int = 0
    total_duration_ns: int = 0
    entries: dict[str, int] = field(default_factory=dict)

    # Quality check metrics
    quality_checks: int = 0
    quality_violations: int = 0
    quality_reports: list[DataQualityReport] = field(default_factory=list)

    # Function tracking metrics
    function_calls: int = 0
    function_duration_ns: int = 0
    function_names: set[str] = field(default_factory=set)

    # Pipeline timing metrics (for Trust Tax)
    pipeline_duration_ns: int = 0

    @property
    def total_ms(self) -> float:
        """Total validation time in milliseconds."""
        return self.total_duration_ns / 1_000_000

    @property
    def pipeline_ms(self) -> float:
        """Total pipeline execution time in milliseconds."""
        return self.pipeline_duration_ns / 1_000_000

    @property
    def trust_tax_percent(self) -> float:
        """Trust Tax as percentage of total execution time.

        Returns:
            Validation overhead percentage (0.0 if no pipeline data).
        """
        if self.pipeline_duration_ns <= 0:
            return 0.0
        return (self.total_duration_ns / self.pipeline_duration_ns) * 100


class Auditor:
    """Trust Tax auditor with loguru integration.

    Implements the AuditHook protocol to receive validation events
    and collect metrics for observability.
    """

    def __init__(self) -> None:
        """Initialize auditor with empty metrics."""
        self.metrics = AuditMetrics()

    def on_validate_start(self, entry_name: str) -> None:
        """Called before validation begins.

        Args:
            entry_name: Name of the entry being validated.
        """
        # Currently we track in on_validate_end with duration_ns
        pass

    def on_validate_end(
        self, entry_name: str, is_valid: bool, duration_ns: int
    ) -> None:
        """Called after validation completes.

        Args:
            entry_name: Name of the entry that was validated.
            is_valid: Whether validation passed.
            duration_ns: Validation duration in nanoseconds.
        """
        self.metrics.total_validations += 1
        self.metrics.total_duration_ns += duration_ns
        self.metrics.entries[entry_name] = duration_ns

        # Structured logging with loguru
        logger.bind(
            event="trust_tax.validation",
            entry=entry_name,
            duration_ns=duration_ns,
            duration_ms=duration_ns / 1_000_000,
            is_valid=is_valid,
        ).debug(f"Validated {entry_name}: {duration_ns / 1_000_000:.2f}ms")

    def on_quality_check(self, report: DataQualityReport, duration_ns: int) -> None:
        """Record data quality check result.

        Args:
            report: The DataQualityReport from RuleEngine.
            duration_ns: Time taken for quality check in nanoseconds.
        """
        self.metrics.quality_checks += 1
        self.metrics.quality_violations += sum(
            1 for r in report.results if not r.passed
        )
        self.metrics.quality_reports.append(report)

        # Structured logging
        logger.bind(
            event="quality_check",
            passed=report.passed,
            has_errors=report.has_errors,
            has_warnings=report.has_warnings,
            duration_ms=duration_ns / 1_000_000,
        ).info(report.summary())

    def on_function_call(self, func_name: str, duration_ns: int) -> None:
        """Record function execution time.

        Args:
            func_name: Name of the function that was called.
            duration_ns: Execution duration in nanoseconds.
        """
        self.metrics.function_calls += 1
        self.metrics.function_duration_ns += duration_ns
        self.metrics.function_names.add(func_name)

        logger.bind(
            event="function_call",
            function=func_name,
            duration_ns=duration_ns,
            duration_ms=duration_ns / 1_000_000,
        ).debug(f"Function {func_name}: {duration_ns / 1_000_000:.2f}ms")

    def on_pipeline_start(self, pipeline_name: str) -> None:
        """Called before pipeline execution begins.

        Args:
            pipeline_name: Name of the pipeline being executed.
        """
        logger.bind(
            event="pipeline_start",
            pipeline=pipeline_name,
        ).info(f"Pipeline '{pipeline_name}' starting")

    def on_pipeline_end(self, pipeline_name: str, duration_ns: int) -> None:
        """Called after pipeline execution completes.

        Args:
            pipeline_name: Name of the pipeline that was executed.
            duration_ns: Total pipeline execution duration in nanoseconds.
        """
        self.metrics.pipeline_duration_ns = duration_ns

        logger.bind(
            event="pipeline_end",
            pipeline=pipeline_name,
            duration_ns=duration_ns,
            duration_ms=duration_ns / 1_000_000,
            trust_tax_percent=self.metrics.trust_tax_percent,
        ).info(
            f"Pipeline '{pipeline_name}' completed: "
            f"{duration_ns / 1_000_000:.2f}ms "
            f"(Trust Tax: {self.metrics.trust_tax_percent:.2f}%)"
        )


# Global auditor instance
auditor = Auditor()
