# app/v1/routers/tradeengineGPT.py
from fastapi import APIRouter, Depends, HTTPException, Body, Query
from typing import Dict, Any, Optional
from datetime import datetime
import logging
from bson import ObjectId

from app.db import database
from app.v1.dependencies.auth import get_current_userdetails
from app.v1.services.zerodha.client import ZerodhaClient

from app.v1.services.tradeGPT import (
    refresh_movers_service,
    get_top10_service,
    create_snapshot_service,
    get_snapshot_service,
    chat_symbol_service,
    place_short_order_service,
    kite_postback_service,
    # optional service - keep in services module (see notes)
    get_live_signals_service,
)

router = APIRouter()
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)


def get_zerodha_client_from_db(
    db=Depends(database.get_mongo_db),
    current_user=Depends(get_current_userdetails),
) -> ZerodhaClient:
    """
    Build Zerodha client for the current user from DB settings.
    Throws HTTPException(404) if not configured.
    """
    user_id = str(current_user.get("_id"))
    settings = db["zerodha_settings"].find_one({"user_id": user_id})
    if not settings:
        raise HTTPException(status_code=404, detail="Zerodha settings not found for user")
    return ZerodhaClient(
        api_key=settings["api_key"],
        api_secret=settings["api_secret"],
        access_token=settings.get("access_token", ""),
    )


# ---------------- MOVERS / TOP10 ----------------
@router.post("/movers/refresh", summary="Refresh movers aggregator (poll sources, merge, dedupe)")
def refresh_movers(db=Depends(database.get_mongo_db), current_user=Depends(get_current_userdetails)):
    try:
        result = refresh_movers_service(db)
        return {"status": "ok", "result": result}
    except HTTPException:
        raise
    except Exception as e:
        logger.exception("refresh_movers failed")
        raise HTTPException(status_code=500, detail=str(e))


@router.get("/movers/top10", summary="Return Top10 movers (cached)")
def top10(db=Depends(database.get_mongo_db)):
    try:
        top = get_top10_service(db)
        return {"status": "ok", "top10": top}
    except HTTPException:
        raise
    except Exception as e:
        logger.exception("get_top10 failed")
        raise HTTPException(status_code=500, detail=str(e))


# ---------------- SNAPSHOTS ----------------
@router.get("/symbol/{symbol}/snapshot", summary="Create and return fresh snapshot for a symbol")
def create_snapshot(
    symbol: str,
    db=Depends(database.get_mongo_db),
    zerodha: ZerodhaClient = Depends(get_zerodha_client_from_db),
):
    try:
        doc = create_snapshot_service(db, zerodha, symbol)
        return {"status": "ok", "snapshot_id": str(doc["_id"]), "snapshot": doc["snapshot"]}
    except HTTPException:
        raise
    except Exception as e:
        logger.exception("create_snapshot failed")
        raise HTTPException(status_code=500, detail=str(e))


@router.get("/symbol/{symbol}/snapshot/{snapshot_id}", summary="Get existing snapshot by id")
def get_snapshot(symbol: str, snapshot_id: str, db=Depends(database.get_mongo_db)):
    try:
        doc = get_snapshot_service(db, snapshot_id)
        if not doc:
            raise HTTPException(status_code=404, detail="Snapshot not found")
        return {"status": "ok", "snapshot": doc}
    except HTTPException:
        raise
    except Exception as e:
        logger.exception("get_snapshot failed")
        raise HTTPException(status_code=500, detail=str(e))


# ---------------- SYMBOL CHAT ----------------
@router.post("/symbol/{symbol}/chat", summary="Ask LLM about a symbol using snapshot + question")
def symbol_chat(
    symbol: str,
    payload: Dict[str, Any] = Body(...),
    db=Depends(database.get_mongo_db),
    zerodha: ZerodhaClient = Depends(get_zerodha_client_from_db),
    current_user=Depends(get_current_userdetails),
):
    """
    payload: { "question": str, "snapshot_id": Optional[str] }
    Returns: { status: ok, response: LLM_JSON }
    """
    try:
        user = current_user
        resp = chat_symbol_service(db, zerodha, user, symbol, payload)
        return {"status": "ok", "response": resp}
    except HTTPException:
        raise
    except Exception as e:
        logger.exception("symbol_chat failed")
        raise HTTPException(status_code=500, detail=str(e))


# ---------------- ORDERING ----------------
@router.post("/orders/short", summary="Place manual short order (requires explicit user_confirmation)")
def place_short_order(
    payload: Dict[str, Any] = Body(...),
    db=Depends(database.get_mongo_db),
    zerodha: ZerodhaClient = Depends(get_zerodha_client_from_db),
    current_user=Depends(get_current_userdetails),
):
    """
    payload: { symbol, quantity, price(optional), order_type, user_confirmation:true }
    """
    try:
        user = current_user
        result = place_short_order_service(db, zerodha, user, payload)
        return {"status": "ok", "placed": result}
    except HTTPException:
        raise
    except Exception as e:
        logger.exception("place_short_order failed")
        raise HTTPException(status_code=500, detail=str(e))


@router.post("/callback")
def post_callback(
    payload: dict,
    db=Depends(database.get_mongo_db),
    current_user=Depends(get_current_userdetails)
):
    request_token = payload.get("request_token")
    user_id = str(current_user.get("_id"))

    if not request_token:
        raise HTTPException(status_code=400, detail="Missing request token")

    settings = db["zerodha_settings"].find_one({"user_id": user_id})
    if not settings:
        raise HTTPException(status_code=404, detail="Zerodha settings not found")

    client = ZerodhaClient(settings["api_key"], settings["api_secret"])
    session = client.generate_session(request_token)

    db["zerodha_settings"].update_one(
        {"user_id": user_id},
        {"$set": {"access_token": session["access_token"]}}
    )

    return {"status": "connected"}

@router.post("/postback")
async def kite_postback(payload: dict):
    try:
        # Zerodha sends JSON postback with order status
        # Save to DB, trigger alerts, etc.
        logging.info("Zerodha postback received: %s", payload)
        database.get_mongo_db()["zerodha_postbacks"].insert_one(payload)
        return {"status": "received"}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@router.get("/profile")
def get_zerodha_profile(
    db=Depends(database.get_mongo_db),
    current_user=Depends(get_current_userdetails)
):
    settings = db["zerodha_settings"].find_one({"user_id": str(current_user["_id"])})
    if not settings or not settings.get("access_token"):
        raise HTTPException(status_code=403, detail="Not authenticated with Zerodha")

    client = ZerodhaClient(settings["api_key"], settings["api_secret"], settings["access_token"])
    try:
        profile = client.get_profile()
        return {"status": "ok", "profile": profile}
    except Exception:
        raise HTTPException(status_code=403, detail="Invalid/expired Zerodha access token")


# ---------------- KITE POSTBACK ----------------
@router.post("/webhook/kite/postback", summary="Kite Connect postback handler (order updates)")
def kite_postback(payload: Dict[str, Any] = Body(...)):
    try:
        res = kite_postback_service(payload)
        return {"status": "received", "result": res}
    except HTTPException:
        raise
    except Exception as e:
        logger.exception("kite_postback failed")
        raise HTTPException(status_code=500, detail=str(e))


# ---------------- STREAM FEEDBACK ----------------
@router.post("/stream/feedback/{id}", summary="Stream feedback (thumbs up/down)")
def stream_feedback(id: str, payload: Dict[str, Any] = Body(...), db=Depends(database.get_mongo_db)):
    fb = payload.get("feedback")  # 'up' or 'down'
    if fb not in ("up", "down"):
        raise HTTPException(status_code=400, detail="feedback must be 'up' or 'down'")
    try:
        # Ensure _id uses ObjectId if possible
        try:
            db["stream"].update_one({"_id": ObjectId(id)}, {"$set": {"user_feedback": fb}})
        except Exception:
            # fallback: maybe id stored as string key
            db["stream"].update_one({"_id": id}, {"$set": {"user_feedback": fb}})
    except Exception as e:
        logger.exception("feedback update failed")
        raise HTTPException(status_code=500, detail=str(e))
    return {"status": "ok"}


# ---------------- HEALTH & TEST ----------------
@router.get("/health", summary="Health check")
def health():
    from app.v1.services.tradeGPT import validate_openai_config
    openai_status = validate_openai_config()
    return {
        "status": "ok", 
        "time": datetime.utcnow().isoformat(),
        "openai_configured": openai_status
    }

@router.post("/test/llm", summary="Test ChatGPT integration")
def test_llm(payload: Dict[str, Any] = Body({"question": "Is this working?"})):
    """Test endpoint to verify ChatGPT integration"""
    from app.v1.services.tradeGPT import call_chatgpt_analyze_service
    
    mock_snapshot = {
        "symbol": "TEST",
        "quote": {"last_price": 100.0},
        "candles": {"5minute": [{"t": "2023-01-01", "o": 99, "h": 101, "l": 98, "c": 100, "v": 1000}]}
    }
    
    question = payload.get("question", "Analyze this test data")
    result = call_chatgpt_analyze_service(mock_snapshot, question)
    return {"status": "ok", "llm_response": result}


# ---------------- BACKWARDS-COMPAT: /trade/live (legacy frontends) ----------------
@router.get("/live", summary="(compat) Live enriched signals - fallback for legacy frontend")
def trade_live(
    mover: str = Query("gainers", description="Which top movers to run on: gainers | losers"),
    limit: int = Query(50, description="Max symbols to scan"),
    db=Depends(database.get_mongo_db),
    current_user=Depends(get_current_userdetails),
    zerodha: ZerodhaClient = Depends(get_zerodha_client_from_db),
):
    """
    Backwards-compatible endpoint returning rich strategy results.
    Delegates to get_live_signals_service in services (implement there).
    """
    try:
        user_id = str(current_user.get("_id"))
        # get_live_signals_service should be implemented in app.v1.services.tradeGPT
        resp = get_live_signals_service(db=db, zerodha=zerodha, mover=mover, limit=limit, user_id=user_id)
        # Expect resp to be {"results": [...]}
        results = resp.get("results", []) if isinstance(resp, dict) else []
        return {"status": "success", "scanned": len(results), "results": results}
    except HTTPException:
        raise
    except Exception as e:
        logger.exception("trade_live failed")
        raise HTTPException(status_code=500, detail=str(e))
