"""
Financial Modeling Prep (FMP) provider
Free tier: 250 requests/day - optimized for batch operations only
"""
from typing import Optional, List, Dict
from datetime import datetime
import requests
import pandas as pd

from .base import BaseProvider
from ..models import Quote, HistoricalData
from ..core import ProviderRateLimiter
from ..config import Config


class FMPProvider(BaseProvider):
    """Financial Modeling Prep API provider - batch optimized"""
    
    BASE_URL = "https://financialmodelingprep.com/api/v3"
    
    def __init__(self, api_key: Optional[str] = None, rate_limiter: Optional[ProviderRateLimiter] = None):
        super().__init__("fmp")
        self.rate_limiter = rate_limiter
        self.api_key = api_key or Config.FMP_API_KEY
        
        if not self.api_key:
            self._available = False
            self._last_error = "FMP API key not configured"
        else:
            self._available = True
    
    def get_quote(self, symbol: str) -> Optional[Quote]:
        """
        Get single quote - NOT RECOMMENDED for FMP due to rate limits.
        Use get_multiple_quotes() instead for efficiency.
        """
        if not self._available:
            return None
        
        # Warn: single quotes are inefficient for FMP
        print(f"⚠️  [FMP] Single quote inefficient. Use batch for better rate limit usage.")
        
        quotes = self.get_multiple_quotes([symbol])
        return quotes[0] if quotes else None
    
    def get_multiple_quotes(self, symbols: List[str]) -> List[Quote]:
        """
        Get quotes for multiple symbols - OPTIMIZED batch endpoint.
        FMP supports comma-separated symbols in single request.
        """
        if not self._available:
            return []
        
        quotes = []
        
        try:
            if self.rate_limiter:
                self.rate_limiter.wait_if_needed("fmp")
            
            # FMP batch endpoint: /v3/quote/{symbol1,symbol2,symbol3}
            symbols_str = ",".join(symbols)
            url = f"{self.BASE_URL}/quote/{symbols_str}"
            
            params = {"apikey": self.api_key}
            response = requests.get(url, params=params, timeout=10)
            response.raise_for_status()
            
            data = response.json()
            
            if not data or not isinstance(data, list):
                return []
            
            # Parse each quote
            for item in data:
                if not isinstance(item, dict):
                    continue
                
                symbol = item.get("symbol")
                price = item.get("price")
                
                if not symbol or not price:
                    continue
                
                quote = Quote(
                    symbol=symbol,
                    timestamp=datetime.fromtimestamp(item.get("timestamp", datetime.now().timestamp())),
                    price=float(price),
                    open=float(item.get("open", 0)) if item.get("open") else None,
                    high=float(item.get("dayHigh", 0)) if item.get("dayHigh") else None,
                    low=float(item.get("dayLow", 0)) if item.get("dayLow") else None,
                    close=float(price),
                    volume=int(item.get("volume", 0)) if item.get("volume") else None,
                    change=float(item.get("change", 0)) if item.get("change") else None,
                    change_percent=float(item.get("changesPercentage", 0)) if item.get("changesPercentage") else None,
                    previous_close=float(item.get("previousClose", 0)) if item.get("previousClose") else None,
                    market_cap=int(item.get("marketCap", 0)) if item.get("marketCap") else None,
                    exchange=item.get("exchange"),
                    source="fmp",
                    metadata={
                        "name": item.get("name"),
                        "eps": item.get("eps"),
                        "pe": item.get("pe"),
                        "shares_outstanding": item.get("sharesOutstanding")
                    }
                )
                quotes.append(quote)
            
            return quotes
            
        except Exception as e:
            self._handle_error(e, f"get_multiple_quotes({len(symbols)} symbols)")
            return []
    
    def get_historical(self,
                      symbol: str,
                      start: datetime,
                      end: datetime,
                      interval: str = "1d") -> Optional[HistoricalData]:
        """Get historical data"""
        if not self._available:
            return None
        
        try:
            if self.rate_limiter:
                self.rate_limiter.wait_if_needed("fmp")
            
            # FMP uses different endpoint for historical
            # Daily: /v3/historical-price-full/{symbol}
            url = f"{self.BASE_URL}/historical-price-full/{symbol}"
            
            params = {
                "apikey": self.api_key,
                "from": start.strftime("%Y-%m-%d"),
                "to": end.strftime("%Y-%m-%d")
            }
            
            response = requests.get(url, params=params, timeout=10)
            response.raise_for_status()
            
            data = response.json()
            
            if not data or "historical" not in data:
                return None
            
            historical = data["historical"]
            if not historical:
                return None
            
            # Convert to DataFrame
            df = pd.DataFrame(historical)
            
            # Standardize columns
            df = df.rename(columns={
                "date": "Date",
                "open": "Open",
                "high": "High",
                "low": "Low",
                "close": "Close",
                "volume": "Volume",
                "adjClose": "Adj Close"
            })
            
            # Convert date to datetime
            df["Date"] = pd.to_datetime(df["Date"])
            df = df.set_index("Date")
            
            # Sort by date (FMP returns newest first)
            df = df.sort_index()
            
            return HistoricalData(
                symbol=symbol,
                data=df,
                start_date=start,
                end_date=end,
                interval=interval,
                source="fmp"
            )
            
        except Exception as e:
            self._handle_error(e, f"get_historical({symbol})")
            return None
    
    # ========================================================================
    # Extended APIs
    # ========================================================================
    
    def get_profile(self, symbol: str) -> Dict:
        """Get company profile"""
        if not self._available:
            return {}
        
        try:
            if self.rate_limiter:
                self.rate_limiter.wait_if_needed("fmp")
            
            url = f"{self.BASE_URL}/profile/{symbol}"
            params = {"apikey": self.api_key}
            
            response = requests.get(url, params=params, timeout=10)
            response.raise_for_status()
            
            data = response.json()
            return data[0] if data and isinstance(data, list) else {}
            
        except Exception as e:
            self._handle_error(e, f"get_profile({symbol})")
            return {}
    
    def get_financials(self, symbol: str, period: str = "annual", limit: int = 5) -> pd.DataFrame:
        """Get financial statements"""
        if not self._available:
            return pd.DataFrame()
        
        try:
            if self.rate_limiter:
                self.rate_limiter.wait_if_needed("fmp")
            
            # Income statement
            url = f"{self.BASE_URL}/income-statement/{symbol}"
            params = {
                "apikey": self.api_key,
                "period": period,
                "limit": limit
            }
            
            response = requests.get(url, params=params, timeout=10)
            response.raise_for_status()
            
            data = response.json()
            if not data:
                return pd.DataFrame()
            
            return pd.DataFrame(data)
            
        except Exception as e:
            self._handle_error(e, f"get_financials({symbol})")
            return pd.DataFrame()
