"""Quandl / Nasdaq Data Link provider.

Financial and economic datasets via the Nasdaq Data Link API.
Requires API key for access.

Docs: https://docs.data.nasdaq.com/
"""

from __future__ import annotations

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

import requests

from ..models import Bar, Quote, TimeFrame


class QuandlProvider:
    """Quandl / Nasdaq Data Link data provider.
    
    Supports financial, economic, and alternative datasets.
    
    Usage:
        provider = QuandlProvider(api_key="your_key")
        data = provider.get_dataset("WIKI/AAPL")
        bars = provider.get_bars("AAPL", start=datetime(2023, 1, 1))
    """
    
    name = "quandl"
    BASE_URL = "https://data.nasdaq.com"
    
    def __init__(self, api_key: Optional[str] = None) -> None:
        """Initialize Quandl provider.
        
        Args:
            api_key: Nasdaq Data Link (Quandl) 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="quandl")
                self._api_key = creds.get("quandl_api_key", "")
            except Exception:
                pass
        
        if not self._api_key:
            print("[CPZ SDK] Quandl API key not found. Get a key at data.nasdaq.com")
    
    def _request(self, path: str, params: Optional[Dict[str, Any]] = None) -> Any:
        """Make API request with api_key auth."""
        if params is None:
            params = {}
        params["api_key"] = self._api_key
        
        url = f"{self.BASE_URL}{path}"
        response = requests.get(url, params=params, timeout=30)
        response.raise_for_status()
        return response.json()
    
    def get_dataset(
        self,
        dataset_code: str,
        start: Optional[datetime] = None,
        end: Optional[datetime] = None,
        limit: int = 500,
    ) -> Dict[str, Any]:
        """Get a Quandl dataset.
        
        Args:
            dataset_code: Full dataset code (e.g., "WIKI/AAPL")
            start: Start date filter
            end: End date filter
            limit: Maximum rows
            
        Returns:
            Dataset dict with column_names and data arrays
        """
        params: Dict[str, Any] = {"limit": limit}
        
        if start:
            params["start_date"] = start.strftime("%Y-%m-%d")
        if end:
            params["end_date"] = end.strftime("%Y-%m-%d")
        
        try:
            data = self._request(f"/api/v3/datasets/{dataset_code}.json", params=params)
            return data.get("dataset", {})
        except Exception as e:
            print(f"[CPZ SDK] Error fetching Quandl dataset {dataset_code}: {e}")
            return {}
    
    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 via the WIKI dataset.
        
        Args:
            symbol: Stock symbol (e.g., "AAPL")
            timeframe: Bar timeframe (only daily data available from WIKI)
            start: Start datetime
            end: End datetime
            limit: Maximum bars
            
        Returns:
            List of Bar objects
        """
        if isinstance(timeframe, str):
            timeframe = TimeFrame.from_string(timeframe)
        
        dataset_code = f"WIKI/{symbol.upper()}"
        row_limit = limit or 500
        
        dataset = self.get_dataset(dataset_code, start=start, end=end, limit=row_limit)
        
        if not dataset:
            return []
        
        column_names = [c.lower() for c in dataset.get("column_names", [])]
        rows = dataset.get("data", [])
        
        def _col_index(names: List[str], *candidates: str) -> Optional[int]:
            for name in candidates:
                if name in names:
                    return names.index(name)
            return None
        
        date_idx = _col_index(column_names, "date")
        open_idx = _col_index(column_names, "open", "adj. open")
        high_idx = _col_index(column_names, "high", "adj. high")
        low_idx = _col_index(column_names, "low", "adj. low")
        close_idx = _col_index(column_names, "close", "adj. close")
        volume_idx = _col_index(column_names, "volume", "adj. volume")
        
        if date_idx is None or close_idx is None:
            print(f"[CPZ SDK] Cannot map Quandl columns for {symbol}: {column_names}")
            return []
        
        bars: List[Bar] = []
        for row in rows:
            try:
                timestamp = datetime.strptime(str(row[date_idx]), "%Y-%m-%d")
                
                bars.append(Bar(
                    symbol=symbol,
                    timestamp=timestamp,
                    open=float(row[open_idx]) if open_idx is not None and row[open_idx] is not None else 0.0,
                    high=float(row[high_idx]) if high_idx is not None and row[high_idx] is not None else 0.0,
                    low=float(row[low_idx]) if low_idx is not None and row[low_idx] is not None else 0.0,
                    close=float(row[close_idx]) if row[close_idx] is not None else 0.0,
                    volume=float(row[volume_idx]) if volume_idx is not None and row[volume_idx] is not None else 0.0,
                    vwap=None,
                ))
            except (ValueError, IndexError, TypeError):
                continue
        
        bars.sort(key=lambda x: x.timestamp)
        
        if limit and len(bars) > limit:
            bars = bars[-limit:]
        
        return bars
    
    def search(self, query: str, page: int = 1) -> List[Dict[str, Any]]:
        """Search for datasets on Quandl.
        
        Args:
            query: Search query string
            page: Results page number
            
        Returns:
            List of dataset metadata dicts
        """
        try:
            data = self._request("/api/v3/datasets.json", params={
                "query": query,
                "page": page,
            })
            return data.get("datasets", [])
        except Exception as e:
            print(f"[CPZ SDK] Error searching Quandl for '{query}': {e}")
            return []
