"""Analyzer base class and built-in DummyAnalyzer.

This module defines the abstract :class:`Analyzer` interface and a
concrete :class:`DummyAnalyzer` used to verify the framework.

Analyzers must never:
- Access SQLite or SQLAlchemy
- Read files directly
- Perform logging
- Modify the analysis context

All inputs are provided through :class:`~analyzer.context.AnalysisContext`.
"""

from __future__ import annotations

import time
from abc import ABC, abstractmethod

from analyzer.context import AnalysisContext
from analyzer.feature import Feature, FeatureSet
from analyzer.result import AnalysisResult


class Analyzer(ABC):
    """Abstract base class for all analyzers.

    Subclasses must define ``name``, ``version``, and implement
    :meth:`analyze`.

    Attributes:
        name: Unique analyzer identifier.
        version: Analyzer version string.
    """

    name: str
    version: str

    @abstractmethod
    def analyze(self, context: AnalysisContext) -> AnalysisResult:
        """Analyze the given context and return a result.

        Args:
            context: The analysis context containing track, audio,
                and settings.

        Returns:
            An :class:`AnalysisResult` with extracted features.
        """
        ...


class DummyAnalyzer(Analyzer):
    """Built-in analyzer for framework verification.

    Produces a single feature ``framework.version = "0.1"``.
    No DSP.  No audio analysis.
    """

    name = "dummy"
    version = "0.1"

    def analyze(self, context: AnalysisContext) -> AnalysisResult:
        """Return a single framework version feature.

        Args:
            context: The analysis context (unused but required by
                the interface).

        Returns:
            An :class:`AnalysisResult` with one feature.
        """
        start = time.perf_counter()

        feature = Feature(
            name="framework.version",
            value="0.1",
            analyzer=self.name,
            version=self.version,
        )
        feature_set = FeatureSet([feature])

        elapsed_ms = (time.perf_counter() - start) * 1000.0

        return AnalysisResult(
            analyzer_name=self.name,
            analyzer_version=self.version,
            execution_time_ms=elapsed_ms,
            success=True,
            warnings=(),
            feature_set=feature_set,
        )
