"""Bigdata.com data provider.

Alternative data platform with sentiment, ESG, analyst ratings, and price data.
Requires API key from bigdata.com.

Docs: https://api.bigdata.com/docs
"""

from __future__ import annotations

from datetime import datetime
from typing import Any, Dict, List, Optional

import requests

from ..models import Bar, Quote, TimeFrame


class BigdataProvider:
    """Bigdata.com data provider.

    Supports sentiment, ESG scores, analyst ratings, earnings, and price data.

    Usage:
        provider = BigdataProvider(api_key="your_key")
        bars = provider.get_bars("AAPL", start=datetime(2023, 1, 1))
    """

    name = "bigdata"
    supported_assets = ["stocks"]
    BASE_URL = "https://api.bigdata.com"

    def __init__(self, api_key: Optional[str] = None) -> None:
        """Initialize Bigdata provider.

        Args:
            api_key: Bigdata.com API key.
        """
        self._api_key = api_key or ""

        if not self._api_key:
            try:
                from ...common.cpz_ai import CPZAIClient
                cpz_client = CPZAIClient.from_env()
                creds = cpz_client.get_data_credentials(provider="bigdata")
                self._api_key = creds.get("bigdata_api_key", "")
            except Exception:
                pass

        if not self._api_key:
            print("[CPZ SDK] Bigdata API key not found. Get a key at bigdata.com")

    def _request(
        self,
        path: str,
        body: Optional[Dict[str, Any]] = None,
        method: str = "GET",
    ) -> Any:
        """Make API request."""
        url = f"{self.BASE_URL}{path}"
        headers = {"X-API-KEY": self._api_key}

        if method == "POST":
            response = requests.post(url, json=body, headers=headers, timeout=30)
        else:
            response = requests.get(url, headers=headers, timeout=30)

        response.raise_for_status()
        return response.json()

    def _resolve_entity_id(self, symbol: str) -> Optional[str]:
        """Resolve a ticker symbol to an rp_entity_id."""
        try:
            data = self._request(
                f"/v1/companies/find-by-details?name={symbol}&type=company"
            )
            if isinstance(data, list) and data:
                return data[0].get("rp_entity_id")
            if isinstance(data, dict):
                return data.get("rp_entity_id")
        except Exception as e:
            print(f"[CPZ SDK] Error resolving entity ID for {symbol}: {e}")
        return None

    def get_bars(
        self,
        symbol: str,
        timeframe: TimeFrame | str = TimeFrame.DAY,
        start: Optional[datetime] = None,
        end: Optional[datetime] = None,
        limit: Optional[int] = None,
    ) -> List[Bar]:
        """Get historical bars from Bigdata.

        Args:
            symbol: Stock symbol (e.g., "AAPL")
            timeframe: Bar timeframe
            start: Start datetime
            end: End datetime
            limit: Maximum bars

        Returns:
            List of Bar objects
        """
        if isinstance(timeframe, str):
            timeframe = TimeFrame.from_string(timeframe)

        entity_id = self._resolve_entity_id(symbol)
        if not entity_id:
            print(f"[CPZ SDK] Could not resolve entity ID for {symbol}")
            return []

        body: Dict[str, Any] = {
            "identifier": {"type": "rp_entity_id", "value": entity_id},
        }
        if start or end:
            date_range: Dict[str, str] = {}
            if start:
                date_range["start"] = start.strftime("%Y-%m-%d")
            if end:
                date_range["end"] = end.strftime("%Y-%m-%d")
            body["date_range"] = date_range

        is_intraday = timeframe in (
            TimeFrame.MINUTE_1, TimeFrame.MINUTE_5, TimeFrame.MINUTE_15,
            TimeFrame.MINUTE_30, TimeFrame.HOUR_1, TimeFrame.HOUR_4,
        )
        endpoint = "/v1/price/intraday/query" if is_intraday else "/v1/price/daily/query"

        try:
            data = self._request(endpoint, body=body, method="POST")

            fields = data.get("fields", [])
            values = data.get("values", [])

            if not fields or not values:
                return []

            field_idx = {f: i for i, f in enumerate(fields)}
            bars: List[Bar] = []

            for row in values:
                try:
                    ts_raw = row[field_idx.get("date", field_idx.get("timestamp", 0))]
                    if isinstance(ts_raw, str):
                        timestamp = datetime.strptime(ts_raw.split("T")[0], "%Y-%m-%d")
                    else:
                        timestamp = datetime.utcfromtimestamp(ts_raw)

                    bars.append(Bar(
                        symbol=symbol,
                        timestamp=timestamp,
                        open=float(row[field_idx.get("open", 0)]),
                        high=float(row[field_idx.get("high", 0)]),
                        low=float(row[field_idx.get("low", 0)]),
                        close=float(row[field_idx.get("close", 0)]),
                        volume=float(row[field_idx.get("volume", 0)]),
                        vwap=None,
                    ))
                except (ValueError, KeyError, IndexError):
                    continue

            bars.sort(key=lambda x: x.timestamp)

            if limit and len(bars) > limit:
                bars = bars[-limit:]

            return bars

        except Exception as e:
            print(f"[CPZ SDK] Error fetching Bigdata bars for {symbol}: {e}")
            return []

    def get_fundamentals(
        self,
        symbol: str,
        statement_type: str = "income_statement",
    ) -> Dict[str, Any]:
        """Get fundamental financial data.

        Args:
            symbol: Stock symbol
            statement_type: One of "income_statement", "balance_sheet", "cash_flow"

        Returns:
            Dict with financial statement data
        """
        entity_id = self._resolve_entity_id(symbol)
        if not entity_id:
            return {}

        try:
            return self._request(
                f"/v1/financials/{statement_type}/query",
                body={"identifier": {"type": "rp_entity_id", "value": entity_id}},
                method="POST",
            )
        except Exception as e:
            print(f"[CPZ SDK] Error fetching Bigdata fundamentals for {symbol}: {e}")
            return {}

    def get_sentiment(self, symbol: str) -> Dict[str, Any]:
        """Get sentiment data for a symbol.

        Args:
            symbol: Stock symbol

        Returns:
            Dict with sentiment scores and metadata
        """
        entity_id = self._resolve_entity_id(symbol)
        if not entity_id:
            return {}

        try:
            return self._request(
                "/v1/sentiment/query",
                body={"identifier": {"type": "rp_entity_id", "value": entity_id}},
                method="POST",
            )
        except Exception as e:
            print(f"[CPZ SDK] Error fetching Bigdata sentiment for {symbol}: {e}")
            return {}

    def get_esg_scores(self, symbol: str) -> Dict[str, Any]:
        """Get ESG (Environmental, Social, Governance) scores.

        Args:
            symbol: Stock symbol

        Returns:
            Dict with ESG scores
        """
        entity_id = self._resolve_entity_id(symbol)
        if not entity_id:
            return {}

        try:
            return self._request(
                "/v1/esg/query",
                body={"identifier": {"type": "rp_entity_id", "value": entity_id}},
                method="POST",
            )
        except Exception as e:
            print(f"[CPZ SDK] Error fetching Bigdata ESG scores for {symbol}: {e}")
            return {}

    def get_analyst_ratings(self, symbol: str) -> Dict[str, Any]:
        """Get analyst ratings and recommendations.

        Args:
            symbol: Stock symbol

        Returns:
            Dict with analyst ratings data
        """
        entity_id = self._resolve_entity_id(symbol)
        if not entity_id:
            return {}

        try:
            return self._request(
                "/v1/analyst-ratings/query",
                body={"identifier": {"type": "rp_entity_id", "value": entity_id}},
                method="POST",
            )
        except Exception as e:
            print(f"[CPZ SDK] Error fetching Bigdata analyst ratings for {symbol}: {e}")
            return {}

    def get_earnings(self, symbol: str) -> Dict[str, Any]:
        """Get earnings data.

        Args:
            symbol: Stock symbol

        Returns:
            Dict with earnings data
        """
        entity_id = self._resolve_entity_id(symbol)
        if not entity_id:
            return {}

        try:
            return self._request(
                "/v1/earnings/query",
                body={"identifier": {"type": "rp_entity_id", "value": entity_id}},
                method="POST",
            )
        except Exception as e:
            print(f"[CPZ SDK] Error fetching Bigdata earnings for {symbol}: {e}")
            return {}
