"""Result models for the Savvy SDK."""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any


@dataclass
class SourceInfo:
    """Information about a data source."""

    provider: str
    series_id: str | None = None
    tool: str | None = None
    fetched_at: str | None = None
    url: str | None = None
    notes: str | None = None

    @classmethod
    def from_dict(cls, data: dict[str, Any]) -> "SourceInfo":
        """Create from API response."""
        return cls(
            provider=data.get("provider", "unknown"),
            series_id=data.get("series_id"),
            tool=data.get("tool"),
            fetched_at=data.get("fetched_at"),
            url=data.get("url"),
            notes=data.get("notes"),
        )


@dataclass
class DataResult:
    """
    Result from a data fetch operation.

    Attributes:
        data_id: Unique identifier for the fetched data.
        name: Human-readable name for the data.
        source: The tool that produced this data.
        provider: Data provider (e.g., "fred", "yahoo_finance").
        series_id: Series identifier (e.g., "UNRATE", "AAPL").
        row_count: Number of data rows.
        columns: List of column names.
        records: Raw data as list of dictionaries.
    """

    data_id: str
    name: str
    source: str
    provider: str
    series_id: str
    row_count: int
    columns: list[str]
    records: list[dict[str, Any]]

    def to_dataframe(self) -> "pd.DataFrame":
        """
        Convert to pandas DataFrame.

        Returns:
            DataFrame with the data records.
        """
        import pandas as pd

        df = pd.DataFrame(self.records)

        # Try to parse date columns
        for col in df.columns:
            if "date" in col.lower() or col.lower() in ("timestamp", "time", "period"):
                try:
                    df[col] = pd.to_datetime(df[col])
                except Exception:
                    pass

        return df

    @classmethod
    def from_response(
        cls,
        records: list[dict[str, Any]],
        metadata: dict[str, Any],
    ) -> "DataResult":
        """Create from API response."""
        columns = list(records[0].keys()) if records else []
        return cls(
            data_id=metadata.get("data_id", ""),
            name=metadata.get("name", ""),
            source=metadata.get("source", ""),
            provider=metadata.get("provider", ""),
            series_id=metadata.get("series_id", ""),
            row_count=len(records),
            columns=columns,
            records=records,
        )


@dataclass
class ChartMetadata:
    """Metadata for a chart including sources and lineage."""

    chart_id: str
    title: str | None = None
    chart_type: str | None = None
    description: str | None = None
    source_attribution: str | None = None
    sources: list[SourceInfo] = field(default_factory=list)
    lineage: list[str] = field(default_factory=list)
    created_at: str | None = None

    @classmethod
    def from_dict(cls, data: dict[str, Any]) -> "ChartMetadata":
        """Create from API response."""
        sources = [SourceInfo.from_dict(s) for s in data.get("sources", [])]
        # Support multiple field names: chart_id, id, or object_id
        chart_id = data.get("chart_id") or data.get("id") or data.get("object_id") or ""
        return cls(
            chart_id=chart_id,
            title=data.get("title"),
            chart_type=data.get("chart_type"),
            description=data.get("description"),
            source_attribution=data.get("source_attribution"),
            sources=sources,
            lineage=data.get("lineage", []),
            created_at=data.get("created_at"),
        )

    def format_attribution(self) -> str:
        """Format attribution string for display."""
        if self.sources:
            parts = []
            for s in self.sources:
                if s.series_id:
                    parts.append(f"{s.series_id} ({s.provider})")
                else:
                    parts.append(s.provider)
            return ", ".join(parts)
        return self.source_attribution or ""


@dataclass
class ChartResult:
    """
    Result from a visualization request.

    Attributes:
        id: Unique identifier for the chart.
        url: URL to the interactive HTML chart.
        png: URL to the PNG image.
        svg: URL to the SVG image.
        python: URL to download the Python code.
        bundle: URL to download the standalone bundle.
        metadata: Optional metadata about the chart.
    """

    id: str
    url: str
    png: str
    svg: str
    python: str
    bundle: str
    metadata: ChartMetadata | None = None

    @classmethod
    def from_response(cls, data: dict[str, Any]) -> "ChartResult":
        """Create from API response."""
        metadata = None
        if "metadata" in data:
            metadata = ChartMetadata.from_dict(data["metadata"])

        return cls(
            id=data["id"],
            url=data["url"],
            png=data["png"],
            svg=data["svg"],
            python=data["python"],
            bundle=data["bundle"],
            metadata=metadata,
        )

    def _repr_html_(self) -> str:
        """Jupyter notebook display."""
        return f'<iframe src="{self.url}" width="100%" height="500" frameborder="0"></iframe>'
