"""
Standalone script that fetches NIFTY option chain via indiaopt
and prints a JSON summary to stdout, including OI buildup analysis.

Called from main.py:
    python option_chain_helper.py NIFTY
"""
import sys
import json
import asyncio
from indiaopt import NSEClient


async def fetch(symbol: str) -> dict:
    async with NSEClient() as nse:
        r = await nse.fetch_option_chain(symbol)

        rows = [row.to_dict() if hasattr(row, 'to_dict') else vars(row) for row in r.data]
        rows = sorted(rows, key=lambda x: float(x['strike']))

        spot = float(r.spot_price)

        above = [x for x in rows if float(x['strike']) >= spot]
        below = [x for x in rows if float(x['strike']) <= spot]

        resistance_row = max(above, key=lambda x: float(x.get('call_oi') or 0)) if above else None
        support_row = max(below, key=lambda x: float(x.get('put_oi') or 0)) if below else None
        top_call = max(rows, key=lambda x: float(x.get('call_oi') or 0))
        top_put = max(rows, key=lambda x: float(x.get('put_oi') or 0))

        # --- OI BUILDUP: Top 3 strikes by Call COI and Put COI ---
        top_call_coi = sorted(
            [x for x in rows if (x.get('call_coi') or 0) > 0],
            key=lambda x: -float(x['call_coi'])
        )[:3]
        top_put_coi = sorted(
            [x for x in rows if (x.get('put_coi') or 0) > 0],
            key=lambda x: -float(x['put_coi'])
        )[:3]

        top_call_coi_list = [
            {"strike": float(x['strike']), "coi": int(x['call_coi']), "oi": int(x.get('call_oi') or 0)}
            for x in top_call_coi
        ]
        top_put_coi_list = [
            {"strike": float(x['strike']), "coi": int(x['put_coi']), "oi": int(x.get('put_oi') or 0)}
            for x in top_put_coi
        ]

        # Total Call COI and Put COI across all strikes (fresh positioning)
        total_call_coi = sum(int(x.get('call_coi') or 0) for x in rows)
        total_put_coi = sum(int(x.get('put_coi') or 0) for x in rows)

        # Net Writer Bias: if Put COI > Call COI => writers bullish; else bearish
        net_coi = total_put_coi - total_call_coi

        # Normalize to a -10 to +10 score
        # Scale: 100,000 contracts net = 10 points
        net_bias_score = round(max(-10, min(10, net_coi / 10000)), 1)

        if net_bias_score >= 3:
            net_bias_label = "BULLISH"
        elif net_bias_score <= -3:
            net_bias_label = "BEARISH"
        else:
            net_bias_label = "NEUTRAL"

        result = {
            "symbol": symbol,
            "spot": spot,
            "expiry": str(r.expiry),
            "atm": float(r.atm_strike),
            "max_pain": float(r.max_pain_strike),
            "pcr": round(float(r.pcr), 3),
            "total_call_oi": int(r.total_call_oi),
            "total_put_oi": int(r.total_put_oi),
            "resistance": {
                "level": float(resistance_row['strike']) if resistance_row else None,
                "call_oi": int(resistance_row['call_oi']) if resistance_row else 0,
                "call_coi": int(resistance_row.get('call_coi') or 0) if resistance_row else 0,
            },
            "support": {
                "level": float(support_row['strike']) if support_row else None,
                "put_oi": int(support_row['put_oi']) if support_row else 0,
                "put_coi": int(support_row.get('put_coi') or 0) if support_row else 0,
            },
            "top_call_oi": {
                "strike": float(top_call['strike']),
                "oi": int(top_call['call_oi']),
            },
            "top_put_oi": {
                "strike": float(top_put['strike']),
                "oi": int(top_put['put_oi']),
            },
            # NEW: OI buildup analysis
            "oi_buildup": {
                "total_call_coi": total_call_coi,
                "total_put_coi": total_put_coi,
                "net_coi": net_coi,
                "net_bias_score": net_bias_score,
                "net_bias_label": net_bias_label,
                "top_call_coi": top_call_coi_list,
                "top_put_coi": top_put_coi_list,
            },
        }
        return result


def main():
    symbol = sys.argv[1] if len(sys.argv) > 1 else "NIFTY"
    try:
        data = asyncio.run(fetch(symbol))
        print(json.dumps(data))
    except Exception as e:
        print(json.dumps({"error": str(e)}), file=sys.stderr)
        sys.exit(1)


if __name__ == "__main__":
    main()