from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
import sqlite3
import pandas as pd

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_methods=["*"],
    allow_headers=["*"],
)

def query_db(query):
    conn = sqlite3.connect('data/climate_risk.db')
    conn.row_factory = sqlite3.Row
    cur = conn.cursor()
    cur.execute(query)
    rows = cur.fetchall()
    conn.close()
    return [dict(row) for row in rows]

@app.get("/api/dates")
def get_dates():
    try:
        data = query_db("SELECT DISTINCT pricing_date FROM shocks_equity ORDER BY pricing_date DESC")
        return [d['pricing_date'] for d in data]
    except Exception:
        return []

@app.get("/api/scenarios")
def get_scenarios():
    data = query_db("SELECT DISTINCT scenario FROM shocks_equity")
    return data

@app.get("/api/matrix/{scenario_name}")
def get_matrix(scenario_name: str, date: str = None):
    # Retrieve the latest date if not provided
    if not date:
        dates = get_dates()
        date = dates[0] if dates else '2026-03-16'
        
    credit_data = query_db(f"SELECT * FROM shocks_credit WHERE scenario='{scenario_name}' AND pricing_date='{date}'")
    equity_data = query_db(f"SELECT * FROM shocks_equity WHERE scenario='{scenario_name}' AND pricing_date='{date}'")
    
    try:
        curve_data = query_db(f"SELECT * FROM shocks_curve WHERE scenario='{scenario_name}' AND pricing_date='{date}'")
    except Exception:
        curve_data = [] 
        
    try:
        fx_data = query_db(f"SELECT * FROM shocks_fx WHERE scenario='{scenario_name}' AND pricing_date='{date}'")
    except Exception:
        fx_data = []
    
    formatted_assets = []
    
    # Format Equities
    for e in equity_data:
        formatted_assets.append({
            "asset_code": e["asset_code"],
            "type": "Equity",
            "tenor": "-",
            "base_val": f"{e.get('base_price', 0):.2f}",
            "stress_val": f"{e.get('stress_price', 0):.2f}",
            "base_vol": f"{e.get('base_implied_vol', 0)*100:.2f}%",
            "stress_vol": f"{e.get('stress_implied_vol', 0)*100:.2f}%",
        })

    # Format Credits
    for c in credit_data:
        formatted_assets.append({
            "asset_code": c["asset_code"],
            "type": "Credit/Bond",
            "tenor": "-",
            "base_val": f"{c.get('base_spread_bps', 0):.1f} bps",
            "stress_val": f"{c.get('stress_spread_bps', 0):.1f} bps",
            "base_vol": f"PD: {c.get('base_pd', 0)*100:.4f}%",
            "stress_vol": f"PD: {c.get('stress_pd', 0)*100:.4f}%",
        })
        
    # Format Curves
    for cv in curve_data:
        asset_code_display = cv.get('curve_name', cv.get("asset_code", "N/A"))
        formatted_assets.append({
            "asset_code": asset_code_display,
            "type": "Yield Curve",
            "tenor": f"{cv.get('tenor_days', 0)}D",
            "base_val": f"{cv.get('base_zero', 0)*100:.3f}%",
            "stress_val": f"{cv.get('stress_zero', 0)*100:.3f}%",
            "base_vol": f"σ = {cv.get('base_hw_sigma', 0)*100:.2f}%",
            "stress_vol": f"σ = {cv.get('stress_hw_sigma', 0)*100:.2f}%"
        })
        
    # Format FX
    for fx_item in fx_data:
        formatted_assets.append({
            "asset_code": fx_item["asset_code"],
            "type": "FX Pair",
            "tenor": "-",
            "base_val": f"{fx_item.get('base_spot', 0):.4f}",
            "stress_val": f"{fx_item.get('stress_spot', 0):.4f}",
            "base_vol": f"{fx_item.get('base_vol', 0.1)*100:.2f}%",
            "stress_vol": f"{fx_item.get('stress_vol', 0.1)*100:.2f}%"
        })
        
    # New Global Math Rules reflecting Merton Equations and Engine payload mapping
    global_rules = {
        "description": "ISDA SIMM Fully Compliant Pre-Calc Math Engine (Merton & HW1F Native)",
        "equity_rule": "기업 고유 리스크(σ_v)를 상수로 락업(Lock-up)하고, 자산 하락 시 극대화되는 자본 구조적 레버리지(V/E)에 의한 내재 변동성 순수 자가 팽창(Organic Amplification)을 구동합니다.\n\n[적용 수식]\n• Stressed Spot = Merton_Call( V*(1+ΔV), Debt )\n• Stressed Vol = σ(V) * (V'/E') * N(d1)",
        "credit_rule": "Merton 방정식에 따라 부도거리(DD)가 좁혀지며 시장 부도확률(PD)과 스프레드가 기하급수적으로 팽창합니다.\n\n[적용 수식]\n• Stressed Spread = (-1/T) * ln( PD_Risk_Neutral )",
        "curve_rule": "Hull-White 1-Factor (HW1F) Affine 공식을 사용하여 만기(T)별 Zero Rate Shift 곡선을 정밀 도출합니다.\n\n[적용 수식]\n• Zero_Rate' = Zero_0 + ΔRate * [(1 - exp(-aT))/(aT)]\n• HW_Vol' = Base_Vol * (1.30 ISDA Scalar)",
        "fx_rule": "수출/수입 산업 구조의 FX 노출도(Beta)에 기반하여 환율 점프 및 변동성을 연산합니다.\n\n[적용 수식]\n• FX_Spot' = Spot_0 * (1 + ΔGDP * FX_β)"
    }
    
    return {
        "scenario": scenario_name,
        "global_rules": global_rules,
        "assets": formatted_assets
    }
