"""Economic data module for fetching FRED, World Bank, IMF, ECB and other data."""

from __future__ import annotations

from typing import TYPE_CHECKING

from savvy._client import call_tool, extract_data_from_response, extract_metadata_from_response
from savvy.models import DataResult

if TYPE_CHECKING:
    import pandas as pd


def fetch(
    series_id: str,
    *,
    start: str | None = None,
    end: str | None = None,
    provider: str | None = None,
    country: str | None = None,
) -> "pd.DataFrame":
    """
    Fetch economic data from FRED, World Bank, IMF, ECB, and other sources.

    Args:
        series_id: The series identifier (e.g., "UNRATE", "GDP", "CPIAUCSL").
        start: Start date in YYYY-MM-DD or YYYY format.
        end: End date in YYYY-MM-DD or YYYY format.
        provider: Force a specific provider ("fred", "world_bank", "imf", "ecb",
                 "bls", "treasury", "census"). Default is auto-detection.
        country: Country filter for international data (e.g., "Germany", "US").

    Returns:
        DataFrame with columns: date, value (and possibly others).

    Raises:
        AuthenticationError: If API key is invalid or missing.
        DataNotFoundError: If the series is not found.
        ValidationError: If the parameters are invalid.

    Example:
        >>> import savvy
        >>> df = savvy.economic_data.fetch("UNRATE", start="2020-01-01")
        >>> print(df.head())
                 date  value
        0  2020-01-01    3.6
        1  2020-02-01    3.5
        2  2020-03-01    4.4
    """
    kwargs: dict = {
        "action": "fetch",
        "series_id": series_id,
    }

    if start:
        kwargs["start_date"] = start
    if end:
        kwargs["end_date"] = end
    if provider:
        kwargs["provider"] = provider
    if country:
        kwargs["country"] = country

    response = call_tool("economic_data", **kwargs)

    records = extract_data_from_response(response)
    metadata = extract_metadata_from_response(response)

    result = DataResult.from_response(records, metadata)
    return result.to_dataframe()


def search(
    query: str,
    *,
    provider: str | None = None,
    country: str | None = None,
    limit: int = 10,
) -> list[dict]:
    """
    Search for available economic data series.

    Args:
        query: Search term or indicator concept (e.g., "inflation", "unemployment").
        provider: Limit search to specific provider.
        country: Filter by country (e.g., "Germany", "US").
        limit: Maximum number of results (default: 10).

    Returns:
        List of dictionaries with series information:
        - provider: The data provider
        - series_id: The series identifier
        - name: Human-readable name
        - frequency: Data frequency (daily, monthly, etc.)

    Example:
        >>> import savvy
        >>> results = savvy.economic_data.search("inflation")
        >>> for r in results[:3]:
        ...     print(f"{r['provider']}: {r['series_id']} - {r['name']}")
        fred: CPIAUCSL - Consumer Price Index
        fred: CPILFESL - Core CPI
        world_bank: FP.CPI.TOTL.ZG - Inflation, consumer prices
    """
    import re

    kwargs: dict = {
        "action": "search",
        "query": query,
        "limit": limit,
    }

    if provider:
        kwargs["provider"] = provider
    if country:
        kwargs["country"] = country

    response = call_tool("economic_data", **kwargs)

    # Parse the markdown table response
    results = []
    text = ""
    if "content" in response:
        for item in response.get("content", []):
            if item.get("type") == "text":
                text = item.get("text", "")
                break

    # Parse markdown table
    # | Provider | Series ID | Name | Frequency |
    for line in text.split("\n"):
        if line.startswith("|") and "Provider" not in line and "---" not in line:
            parts = [p.strip() for p in line.split("|")[1:-1]]
            if len(parts) >= 4:
                # Remove backticks from series_id
                series_id = parts[1].strip("`")
                results.append({
                    "provider": parts[0].lower(),
                    "series_id": series_id,
                    "name": parts[2],
                    "frequency": parts[3] if parts[3] != "—" else None,
                })

    return results


def compare(
    indicator: str,
    countries: list[str],
    *,
    start: str | None = None,
    end: str | None = None,
) -> "pd.DataFrame":
    """
    Compare an economic indicator across multiple countries.

    Args:
        indicator: The indicator to compare (e.g., "unemployment", "gdp_growth").
        countries: List of country names or ISO codes (e.g., ["US", "DE", "JP"]).
        start: Start date in YYYY-MM-DD or YYYY format.
        end: End date in YYYY-MM-DD or YYYY format.

    Returns:
        DataFrame with columns: date, and one column per country.

    Example:
        >>> import savvy
        >>> df = savvy.economic_data.compare(
        ...     "unemployment",
        ...     ["US", "Germany", "Japan"],
        ...     start="2020-01-01"
        ... )
        >>> print(df.head())
                 date    US  Germany  Japan
        0  2020-01-01   3.6      3.4    2.4
    """
    kwargs: dict = {
        "action": "compare",
        "indicator": indicator,
        "countries": countries,
        "save_as_dataset": True,  # Get structured data
    }

    if start:
        kwargs["start_date"] = start
    if end:
        kwargs["end_date"] = end

    response = call_tool("economic_data", **kwargs)

    records = extract_data_from_response(response)
    metadata = extract_metadata_from_response(response)

    result = DataResult.from_response(records, metadata)
    return result.to_dataframe()


def providers() -> list[dict]:
    """
    List available data providers.

    Returns:
        List of provider information dictionaries.

    Example:
        >>> import savvy
        >>> for p in savvy.economic_data.providers():
        ...     print(f"{p['name']}: {p['description']}")
    """
    response = call_tool("economic_data", action="providers")

    # Parse the markdown response
    providers_list = []
    text = ""
    if "content" in response:
        for item in response.get("content", []):
            if item.get("type") == "text":
                text = item.get("text", "")
                break

    # Simple parsing - extract provider names and basic info
    import re

    current_provider = None
    for line in text.split("\n"):
        if line.startswith("## ") and "`" in line:
            # Extract provider name from format: ## Display Name (`name`)
            match = re.search(r"`(\w+)`", line)
            if match:
                current_provider = {"name": match.group(1)}
                # Extract display name
                display_match = re.match(r"## (.+?) \(", line)
                if display_match:
                    current_provider["display_name"] = display_match.group(1)
                providers_list.append(current_provider)
        elif current_provider and line.startswith("- **"):
            # Parse key-value pairs
            if "URL:" in line:
                match = re.search(r"URL:\*\* (.+)", line)
                if match:
                    current_provider["url"] = match.group(1)
            elif "Coverage:" in line:
                match = re.search(r"Coverage:\*\* (.+)", line)
                if match:
                    current_provider["coverage"] = match.group(1)

    return providers_list
