"""
AkDevz AI Market Intelligence — FYERS REST API V3 Client
Strictly complies with FYERS Standard Plan rate limits and response specifications.
"""
import time
import httpx
from typing import List, Dict, Any, Optional
from python.config.settings import settings
from python.fyers.rate_limiter import rate_limiter

class FyersRestClient:
    BASE_URL = "https://api-t1.fyers.in"
    DATA_URL = "https://api-t1.fyers.in/data"

    def __init__(self, app_id: str = "", access_token: str = ""):
        self.app_id = app_id or settings.fyers_app_id
        self.access_token = access_token
        self.client = httpx.Client(timeout=15.0)

    def _get_headers(self) -> Dict[str, str]:
        return {
            "Authorization": f"{self.app_id}:{self.access_token}",
            "Content-Type": "application/json",
        }

    def _request(self, method: str, url: str, **kwargs) -> httpx.Response:
        rate_limiter.acquire()
        headers = self._get_headers()
        if "headers" in kwargs:
            headers.update(kwargs.pop("headers"))

        retries = 3
        backoff = 1.0

        for attempt in range(retries):
            try:
                resp = self.client.request(method, url, headers=headers, **kwargs)
                if resp.status_code == 429:
                    time.sleep(backoff)
                    backoff *= 2.0
                    rate_limiter.acquire()
                    continue
                return resp
            except httpx.RequestError as e:
                if attempt == retries - 1:
                    raise
                time.sleep(backoff)
                backoff *= 1.5

        raise RuntimeError(f"Failed to execute request to {url} after {retries} retries.")

    def get_profile(self) -> Dict[str, Any]:
        url = f"{self.BASE_URL}/api/v3/profile"
        resp = self._request("GET", url)
        if resp.status_code != 200:
            raise RuntimeError(f"FYERS Profile request failed ({resp.status_code}): {resp.text}")
        return resp.json()

    def get_quotes(self, symbols: List[str]) -> Dict[str, Any]:
        """Fetch quotes in chunks of 50 (Standard limit)."""
        if not symbols:
            return {}

        results = {}
        # Chunk symbols into max 50
        chunk_size = 50
        for i in range(0, len(symbols), chunk_size):
            chunk = symbols[i:i + chunk_size]
            symbols_str = ",".join(chunk)
            url = f"{self.DATA_URL}/quotes?symbols={symbols_str}"
            resp = self._request("GET", url)
            if resp.status_code == 200:
                data = resp.json()
                for item in data.get("d", []):
                    sym = item.get("n")
                    val = item.get("v")
                    if sym and val:
                        results[sym] = val

        return results

    def get_history(
        self,
        symbol: str,
        resolution: str = "5",
        range_from: str = "",
        range_to: str = "",
        cont_flag: int = 1,
        oi_flag: int = 1
    ) -> List[List[Any]]:
        url = f"{self.DATA_URL}/history"
        params = {
            "symbol": symbol,
            "resolution": resolution,
            "date_format": "1",
            "range_from": range_from,
            "range_to": range_to,
            "cont_flag": cont_flag,
            "oi_flag": oi_flag,
        }
        resp = self._request("GET", url, params=params)
        if resp.status_code == 200:
            data = resp.json()
            return data.get("candles", [])
        return []

    def get_option_chain(
        self,
        symbol: str,
        strike_count: int = 15,
        expiry: str = ""
    ) -> Dict[str, Any]:
        url = f"{self.DATA_URL}/options-chain-v3"
        params = {
            "symbol": symbol,
            "strikecount": min(50, max(5, strike_count)),
        }
        if expiry:
            params["expiry"] = expiry

        resp = self._request("GET", url, params=params)
        if resp.status_code == 200:
            data = resp.json()
            return data.get("data", data)
        return {}

    def get_market_depth(self, symbol: str) -> Dict[str, Any]:
        url = f"{self.DATA_URL}/depth"
        params = {"symbol": symbol, "ohlcv_flag": "1"}
        resp = self._request("GET", url, params=params)
        if resp.status_code == 200:
            return resp.json()
        return {}
