"""
AkDevz AI Market Intelligence — Option Chain Collector & Analysis Engine
Retrieves authenticated FYERS options chain, calculates strike-wise PCR and OI concentration.
"""
from typing import Dict, Any, List, Optional
from python.fyers.rest_client import FyersRestClient
from python.analytics.options_engine import OptionsEngine

class OptionChainCollector:
    def __init__(self, rest_client: Optional[FyersRestClient] = None):
        self.client = rest_client or FyersRestClient()

    def get_option_chain_snapshot(
        self,
        symbol: str,
        strike_count: int = 15,
        expiry: str = ""
    ) -> Dict[str, Any]:
        """
        Queries FYERS API V3 option chain endpoint and performs quantitative analysis:
        - PCR (Put-Call Ratio) on OI and Volume
        - Max Call OI Strike (Key Resistance)
        - Max Put OI Strike (Key Support)
        - Filtered liquid strikes
        """
        try:
            chain_raw = self.client.get_option_chain(symbol, strike_count=strike_count, expiry=expiry)
        except Exception as e:
            return {
                "symbol": symbol,
                "status": "ERROR",
                "message": f"Option chain fetch failed: {str(e)}",
                "strikes": [],
                "pcr_oi": 1.0,
                "pcr_volume": 1.0,
                "max_call_oi_strike": None,
                "max_put_oi_strike": None,
            }

        # Handle different response wrappers from FYERS options-chain-v3
        options_chain = chain_raw.get("optionsChain", [])
        if not options_chain and isinstance(chain_raw, list):
            options_chain = chain_raw

        if not options_chain:
            return {
                "symbol": symbol,
                "status": "EMPTY",
                "message": "No active option chain data returned from FYERS.",
                "strikes": [],
                "pcr_oi": 1.0,
                "pcr_volume": 1.0,
                "max_call_oi_strike": None,
                "max_put_oi_strike": None,
            }

        total_ce_oi = 0
        total_pe_oi = 0
        total_ce_vol = 0
        total_pe_vol = 0

        max_ce_oi = -1
        max_pe_oi = -1
        max_ce_strike = None
        max_pe_strike = None

        processed_strikes = []

        for item in options_chain:
            strike = float(item.get("strike_price", 0.0))
            opt_type = str(item.get("option_type", "")).upper()
            oi = int(item.get("oi", 0))
            vol = int(item.get("volume", 0))
            ltp = float(item.get("ltp", 0.0))
            iv = float(item.get("iv", 0.0))

            if opt_type == "CE":
                total_ce_oi += oi
                total_ce_vol += vol
                if oi > max_ce_oi:
                    max_ce_oi = oi
                    max_ce_strike = strike
            elif opt_type == "PE":
                total_pe_oi += oi
                total_pe_vol += vol
                if oi > max_pe_oi:
                    max_pe_oi = oi
                    max_pe_strike = strike

            processed_strikes.append({
                "symbol": item.get("symbol", ""),
                "strike": strike,
                "type": opt_type,
                "ltp": ltp,
                "oi": oi,
                "volume": vol,
                "iv": iv,
                "delta": float(item.get("delta", 0.0)),
                "theta": float(item.get("theta", 0.0)),
                "gamma": float(item.get("gamma", 0.0)),
                "vega": float(item.get("vega", 0.0)),
            })

        pcr_oi = (total_pe_oi / total_ce_oi) if total_ce_oi > 0 else 1.0
        pcr_vol = (total_pe_vol / total_ce_vol) if total_ce_vol > 0 else 1.0

        return {
            "symbol": symbol,
            "status": "VALID",
            "strikes_count": len(processed_strikes),
            "total_ce_oi": total_ce_oi,
            "total_pe_oi": total_pe_oi,
            "pcr_oi": round(pcr_oi, 2),
            "pcr_volume": round(pcr_vol, 2),
            "max_call_oi_strike": max_ce_strike,
            "max_put_oi_strike": max_pe_strike,
            "strikes": processed_strikes[:strike_count * 2]
        }
