"""
AkDevz AI Market Intelligence — Conversational AI Trading Assistant & Educational Copilot
Answers trader inquiries with strict mathematical evidence, news correlation, and zero hallucinations.
"""
import sys
from pathlib import Path

PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent
if str(PROJECT_ROOT) not in sys.path:
    sys.path.insert(0, str(PROJECT_ROOT))

import json
import argparse
import numpy as np
from datetime import datetime
from zoneinfo import ZoneInfo
import pymysql

from python.config.settings import settings
from python.data.market_feed import MarketFeed
from python.data.data_normalizer import DataNormalizer
from python.analytics.technical_engine import TechnicalEngine
from python.analytics.support_resistance import SupportResistanceEngine
from python.intelligence.groq_analyzer import GroqAnalyzer
from python.intelligence.gemini_analyzer import GeminiAnalyzer

IST = ZoneInfo("Asia/Kolkata")

def get_db_connection():
    try:
        return pymysql.connect(
            host=settings.DB_HOST,
            port=settings.DB_PORT,
            user=settings.DB_USER,
            password=settings.DB_PASSWORD,
            database=settings.DB_NAME,
            cursorclass=pymysql.cursors.DictCursor
        )
    except Exception:
        return None

def fetch_recent_news(symbol: str, limit: int = 3) -> list:
    conn = get_db_connection()
    if not conn:
        return []
    try:
        with conn.cursor() as cur:
            cur.execute("""
                SELECT title, source_name, sentiment, impact_score, published_at
                FROM news_articles_raw
                ORDER BY published_at DESC
                LIMIT %s
            """, (limit,))
            return cur.fetchall() or []
    except Exception:
        return []
    finally:
        conn.close()

def generate_assistant_response(user_query: str, symbol: str = "NSE:NIFTY50-INDEX", mode: str = "general") -> dict:
    # 1. Fetch genuine market data
    raw_candles = MarketFeed.get_real_candles(symbol, count=60)
    evidence = {}
    ltp = 0.0
    vwap = 0.0
    ema9 = 0.0
    ema20 = 0.0
    rsi = 50.0
    atr = 20.0
    pivots = {}

    if raw_candles and len(raw_candles) >= 10:
        norm_candles = DataNormalizer.normalize_candles(raw_candles)
        np_data = DataNormalizer.to_numpy_arrays(norm_candles)
        c = np_data["close"]
        h = np_data["high"]
        l = np_data["low"]
        v = np_data["volume"]

        ltp = round(float(c[-1]), 2)
        vwap_arr = TechnicalEngine.calculate_vwap(h, l, c, v)
        vwap = round(float(vwap_arr[-1]), 2) if not np.isnan(vwap_arr[-1]) else ltp
        ema9_arr = TechnicalEngine.calculate_ema(c, 9)
        ema9 = round(float(ema9_arr[-1]), 2) if not np.isnan(ema9_arr[-1]) else ltp
        ema20_arr = TechnicalEngine.calculate_ema(c, 20)
        ema20 = round(float(ema20_arr[-1]), 2) if not np.isnan(ema20_arr[-1]) else ltp
        rsi_arr = TechnicalEngine.calculate_rsi(c, 14)
        rsi = round(float(rsi_arr[-1]), 1) if not np.isnan(rsi_arr[-1]) else 50.0
        atr_arr = TechnicalEngine.calculate_atr(h, l, c, 14)
        atr = round(float(atr_arr[-1]), 2) if not np.isnan(atr_arr[-1]) else 25.0

        pivots = SupportResistanceEngine.calculate_daily_pivots(
            high=float(np.max(h[-50:])),
            low=float(np.min(l[-50:])),
            close=float(c[-1])
        )

    recent_news = fetch_recent_news(symbol, 3)

    evidence = {
        "symbol": symbol,
        "ltp": ltp,
        "vwap": vwap,
        "ema_9": ema9,
        "ema_20": ema20,
        "rsi_14": rsi,
        "atr_14": atr,
        "pivot": pivots.get("pivot", ltp),
        "r1": pivots.get("r1", ltp * 1.005),
        "s1": pivots.get("s1", ltp * 0.995),
        "news_headlines": [n.get("title", "") for n in recent_news]
    }

    prompt = f"""
You are the AkDevz Institutional AI Trading Assistant & Educational Copilot for Indian markets (NSE/BSE).
Current Local Time: {datetime.now(IST).strftime('%Y-%m-%d %H:%M:%S IST')}.

User Question: "{user_query}"
Mode: {mode}

Active Quantitative Market Evidence for {symbol}:
- LTP: {ltp} INR
- Session VWAP: {vwap} INR ({'Above VWAP (Bullish Bias)' if ltp >= vwap else 'Below VWAP (Bearish Bias)'})
- 9 EMA: {ema9} | 20 EMA: {ema20} ({'Fast Bullish Crossover' if ema9 >= ema20 else 'Fast Bearish Crossover'})
- RSI (14): {rsi} ({'Overbought' if rsi >= 70 else 'Oversold' if rsi <= 30 else 'Neutral Momentum'})
- ATR (14): {atr} INR
- Daily Floor Pivot: {evidence['pivot']} | Resistance R1: {evidence['r1']} | Support S1: {evidence['s1']}
- Recent Macro News: {', '.join(evidence['news_headlines']) if evidence['news_headlines'] else 'No major break-out announcements'}

Instructions:
1. Provide a direct, professional, institutional answer explaining the user's question clearly.
2. Ground every numerical statement in the exact numbers above.
3. If discussing trades, explain why NO TRADE or WAITING is mathematically superior when confluence is absent.
4. Clearly explain stop-loss logic (structural pivot or 1.5x ATR buffer) and what invalidates the thesis.
5. In educational mode, explain concepts simply using Indian market context (Dalal Street, Nifty, Bank Nifty, PCR, VWAP).
6. Never promise profits. Keep the tone disciplined, risk-managed, and objective.
7. End with a 1-sentence 'What to watch next'.

Format your response in Markdown with clear sections:
### Verdict & Summary
### Quantitative Evidence Breakdown
### Risk & Invalidation Safeguard
### Educational Note
"""

    ai_text = None
    model_used = "Deterministic Quantitative Rules Engine"

    # Try Groq first, then Gemini
    try:
        analyzer = GroqAnalyzer()
        client = analyzer.client
        if client:
            resp = client.chat.completions.create(
                model=settings.GROQ_MODEL,
                messages=[
                    {"role": "system", "content": "You are a professional quantitative trading architect and trading educator for Indian markets."},
                    {"role": "user", "content": prompt}
                ],
                temperature=0.2,
                max_tokens=900
            )
            ai_text = resp.choices[0].message.content
            model_used = f"Groq ({settings.GROQ_MODEL})"
    except Exception:
        pass

    if not ai_text:
        try:
            gemini = GeminiAnalyzer()
            client = gemini.client
            if client:
                model = client.GenerativeModel(settings.GEMINI_MODEL)
                res = model.generate_content(prompt)
                ai_text = res.text
                model_used = f"Gemini ({settings.GEMINI_MODEL})"
        except Exception:
            pass

    # Deterministic quantitative fallback if LLM is offline
    if not ai_text:
        bias = "BULLISH" if ltp > vwap and ema9 > ema20 else ("BEARISH" if ltp < vwap and ema9 < ema20 else "SIDEWAYS / CHOPPY")
        ai_text = f"""### Verdict & Summary
For **{symbol}**, the current price is **₹{ltp:,.2f}**. Market structure displays a **{bias}** regime.
When price is {'above VWAP (₹' + str(vwap) + ')' if ltp >= vwap else 'below VWAP (₹' + str(vwap) + ')'}, quantitative discipline mandates respecting intraday mean reversion. If there is no clean directional breakout above R1 (₹{evidence['r1']:,.2f}) or breakdown below S1 (₹{evidence['s1']:,.2f}), **NO TRADE** is the mathematically optimal choice to preserve capital.

### Quantitative Evidence Breakdown
- **Current LTP:** ₹{ltp:,.2f}
- **Session VWAP:** ₹{vwap:,.2f} (Delta: {round(ltp - vwap, 2):+0.2f} pts)
- **Fast EMA Structure:** 9 EMA = ₹{ema9:,.2f} | 20 EMA = ₹{ema20:,.2f}
- **RSI (14):** {rsi} ({'Neutral' if 40 <= rsi <= 60 else 'Momentum Driven'})
- **Intraday Volatility (ATR 14):** ₹{atr:,.2f} pts

### Risk & Invalidation Safeguard
- **Stop-Loss Architecture:** A protective stop should always rest beyond the structural pivot level (₹{evidence['pivot']:,.2f}) or 1.5× ATR (₹{round(atr * 1.5, 2)} buffer).
- **Invalidation Condition:** If price closes contrary to the session VWAP with expanding volume, any speculative bias is immediately invalidated.

### Educational Note
*Trading is an exercise in probabilistic expectancy, not certainty. Forcing trades during non-trending periods results in fee and slippage attrition. Patience is an active quantitative edge.*
"""

    return {
        "status": "success",
        "symbol": symbol,
        "query": user_query,
        "mode": mode,
        "model": model_used,
        "evidence": evidence,
        "response": ai_text,
        "timestamp": datetime.now(IST).strftime("%Y-%m-%d %H:%M:%S IST")
    }

def main():
    parser = argparse.ArgumentParser(description="Conversational AI Trading Assistant")
    parser.add_argument("--query", type=str, required=True, help="User question")
    parser.add_argument("--symbol", type=str, default="NSE:NIFTY50-INDEX", help="Symbol context")
    parser.add_argument("--mode", type=str, default="general", help="Interaction mode")
    args = parser.parse_args()

    result = generate_assistant_response(args.query, args.symbol, args.mode)
    print(json.dumps(result))

if __name__ == "__main__":
    main()
