"""
Parser for MAS Factor Miner results (formerly MAS2)
"""

from typing import List, Dict, Any, Optional

from .base_parser import BaseFactorParser
from ..core.factor import MinedFactor
from ..core.config import AssetType, FactorType


class MasfactorMinerParser(BaseFactorParser):
    """Parser for MAS Factor Miner (masfactorMiner) mining results."""

    @property
    def framework_name(self) -> str:
        return "masfactorMiner"

    def parse_factor(self, data: Dict[str, Any]) -> MinedFactor:
        """Parse a single MAS Factor Miner result"""
        return MinedFactor.from_masfactor_miner(
            data,
            asset_type=self.asset_type,
            factor_type=self.factor_type
        )

    def parse_file_content(self, content: Dict[str, Any] | List[Dict[str, Any]]) -> List[MinedFactor]:
        """Parse MAS Factor Miner file content."""
        if isinstance(content, list):
            factors_data = content
        elif isinstance(content, dict):
            factors_data = content.get("factors", content.get("results", []))
            if not isinstance(factors_data, list):
                factors_data = [content]
        else:
            raise ValueError(f"Unexpected content type: {type(content)}")

        factors = []
        for data in factors_data:
            if not isinstance(data, dict):
                continue
            if "expression" not in data:
                continue
            if not data.get("is_valid", True):
                continue
            try:
                factor = self.parse_factor(data)
                factors.append(factor)
            except Exception as e:
                print(f"Warning: Failed to parse factor: {e}")

        return factors

    def filter_by_score(
        self,
        factors: List[MinedFactor],
        min_score: float = 50.0
    ) -> List[MinedFactor]:
        """Filter factors by score threshold"""
        return [f for f in factors if f.get_metric("score", 0) >= min_score]

    def filter_by_direction(
        self,
        factors: List[MinedFactor],
        direction: int
    ) -> List[MinedFactor]:
        """Filter factors by trading direction (1 for long, -1 for short)"""
        return [f for f in factors if f.get_metric("direction") == direction]

    def get_period_metrics(
        self,
        factor: MinedFactor,
        period: int = 1
    ) -> Dict[str, Any]:
        """Get metrics for a specific period."""
        period_key = f"period_{period}"
        metrics = {}

        for key, value in factor.metrics.items():
            if key.startswith(f"{period_key}_"):
                metrics[key[len(period_key) + 1 :]] = value

        return metrics

    def sort_by_score(self, factors: List[MinedFactor], descending: bool = True) -> List[MinedFactor]:
        """Sort factors by score"""
        return sorted(factors, key=lambda f: f.get_metric("score", 0), reverse=descending)

    def sort_by_period_icir(
        self,
        factors: List[MinedFactor],
        period: int = 1,
        descending: bool = True
    ) -> List[MinedFactor]:
        """Sort factors by ICIR for a specific period"""
        period_key = f"period_{period}_icir"
        return sorted(factors, key=lambda f: abs(f.get_metric(period_key, 0)), reverse=descending)

    def get_best_period(self, factor: MinedFactor) -> Optional[int]:
        """Find the period with the best ICIR for a factor."""
        best_period = None
        best_icir = 0

        for period in [1, 5, 10, 20]:
            icir = factor.get_metric(f"period_{period}_icir", 0)
            if abs(icir) > abs(best_icir):
                best_icir = icir
                best_period = period

        return best_period
