"""
optik - The optical lens for AI model interpretability.

Main API for analyzing object detection models.
"""

from .core.base import BaseModelAdapter
from .models.yolo import YOLOAdapter
from .methods.detection_flow import DetectionFlow
from .methods.counterfactual import CounterfactualProbe
from .methods.grid_trace import GridCellTrace
from .reports.generator import ReportGenerator

__version__ = "0.1.0"
__all__ = ["Optik", "YOLOAdapter", "DetectionFlow", "CounterfactualProbe", "GridCellTrace"]


class Optik:
    """
    Main API for model interpretability analysis.
    
    Example:
        analyzer = Optik.from_yolo("best.pt")
        results = analyzer.analyze("image.jpg")
        analyzer.report(results, "report.html")
    """
    
    def __init__(self, adapter: BaseModelAdapter):
        self.adapter = adapter
        self._detection_flow = None
        self._counterfactual = None
        self._grid_trace = None
    
    @classmethod
    def from_yolo(cls, model_path: str) -> "Optik":
        """Create analyzer for Ultralytics YOLO model."""
        adapter = YOLOAdapter(model_path)
        return cls(adapter)
    
    # Future model support:
    # @classmethod
    # def from_detr(cls, model_path: str) -> "Optik":
    #     adapter = DETRAdapter(model_path)
    #     return cls(adapter)
    
    @property
    def detection_flow_analyzer(self) -> DetectionFlow:
        """Lazy-load DetectionFlow analyzer."""
        if self._detection_flow is None:
            self._detection_flow = DetectionFlow(self.adapter)
        return self._detection_flow
    
    @property
    def counterfactual_analyzer(self) -> CounterfactualProbe:
        """Lazy-load CounterfactualProbe analyzer."""
        if self._counterfactual is None:
            self._counterfactual = CounterfactualProbe(self.adapter)
        return self._counterfactual
    
    @property
    def grid_trace_analyzer(self) -> GridCellTrace:
        """Lazy-load GridCellTrace analyzer."""
        if self._grid_trace is None:
            self._grid_trace = GridCellTrace(self.adapter)
        return self._grid_trace
    
    def analyze(self, image_path: str, methods: list = None) -> dict:
        """
        Run full analysis on an image.
        
        Args:
            image_path: Path to image file
            methods: List of methods to run. Default: all available.
                    Options: ["detection_flow", "grid_trace", "counterfactual"]
        
        Returns:
            Dictionary with analysis results from each method.
        """
        methods = methods or ["detection_flow", "grid_trace"]
        
        results = {
            "image_path": image_path,
            "predictions": self.adapter.predict(image_path),
            "class_names": self.adapter.get_class_names(),
        }
        
        if "detection_flow" in methods:
            results["detection_flow"] = self.detection_flow(image_path)
        
        if "grid_trace" in methods:
            results["grid_trace"] = self.grid_trace(image_path)
        
        return results
    
    def detection_flow(self, image_path: str, detection_idx: int = None) -> dict:
        """
        Run DetectionFlow analysis.
        
        Args:
            image_path: Path to image
            detection_idx: Specific detection to analyze. None = all detections.
        """
        return self.detection_flow_analyzer.compute(image_path, detection_idx)
    
    def counterfactual(
        self, 
        image_path: str, 
        detection_idx: int,
        target: str = "remove"
    ) -> dict:
        """
        Run CounterfactualProbe analysis.
        
        Args:
            image_path: Path to image
            detection_idx: Which detection to analyze
            target: "remove" | "change_class" | "shift_bbox"
        """
        return self.counterfactual_analyzer.find_critical_change(
            image_path, detection_idx, target
        )
    
    def grid_trace(self, image_path: str) -> dict:
        """Run GridCellTrace analysis."""
        return self.grid_trace_analyzer.trace(image_path)
    
    def report(self, results: dict, output_path: str) -> None:
        """Generate HTML report from analysis results."""
        generator = ReportGenerator()
        generator.generate(results, output_path)
