"""
Vermögen — Vermögens-Tracker für Zeyd & Talla
FastAPI Backend + SQLite + Static Frontend
Stripe Link Design mit Lora-Schrift
"""
import os
import sqlite3
import datetime
from pathlib import Path
from contextlib import contextmanager
from fastapi import FastAPI, Request, HTTPException, Depends
from fastapi.responses import FileResponse, JSONResponse
from fastapi.security import HTTPBasic, HTTPBasicCredentials
from fastapi.middleware.cors import CORSMiddleware

FRONTEND_DIR = Path(__file__).parent / "frontend"
DATA_DIR = Path(os.environ.get("DATA_DIR", str(Path(__file__).parent / "data")))
DB_PATH = DATA_DIR / "vermogen.db"
AUTH_USER = "zeyd"
AUTH_PASS = "talla2024"

# Ensure data directory exists
DATA_DIR.mkdir(parents=True, exist_ok=True)

app = FastAPI(title="Vermögen")
security = HTTPBasic()

# ── Database ───────────────────────────────────────────

@contextmanager
def get_db():
    conn = sqlite3.connect(str(DB_PATH))
    conn.row_factory = sqlite3.Row
    conn.execute("PRAGMA journal_mode=WAL")
    conn.execute("PRAGMA foreign_keys=ON")
    try:
        yield conn
        conn.commit()
    finally:
        conn.close()

def init_db():
    with get_db() as db:
        db.execute("""
            CREATE TABLE IF NOT EXISTS vermoegen (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                name TEXT NOT NULL,
                kategorie TEXT NOT NULL,
                anzahl INTEGER DEFAULT 1,
                gramm REAL,
                feingehalt REAL,
                feingold REAL,
                betrag REAL DEFAULT 0,
                ziel_prozent REAL,
                ist_prozent REAL,
                notiz TEXT,
                sort_order INTEGER DEFAULT 0,
                created_at TEXT DEFAULT (datetime('now','localtime')),
                updated_at TEXT DEFAULT (datetime('now','localtime'))
            )
        """)
        # Seed only if empty
        count = db.execute("SELECT COUNT(*) FROM vermoegen").fetchone()[0]
        if count == 0:
            seed_data(db)

def seed_data(db):
    gold_items = [
        # name, kategorie, anzahl, gramm, feingehalt, feingold, betrag, ziel, notiz, sort
        ("3 × 1g Barren (999.9)", "Gold", 3, 1.00, 0.9999, 2.9997, 384.00, None, None, 1),
        ("2 × 10g Barren (999.9)", "Gold", 2, 10.00, 0.9999, 19.998, 2568.00, None, None, 2),
        ("5 × Çeyrek Lira (22K)", "Gold", 5, 1.804, 0.9167, 8.270, 1080.00, None, "1,804g/Stk · 22 Karat", 3),
        ("2 × Yarım Lira (22K)", "Gold", 2, 3.608, 0.9167, 6.614, 864.00, None, "3,608g/Stk · 22 Karat", 4),
        ("1 × Tam Lira (22K)", "Gold", 1, 7.216, 0.9167, 6.615, 864.00, None, "7,216g/Stk · 22 Karat", 5),
        ("2 × Tam Reşat (22K)", "Gold", 2, 7.216, 0.9167, 13.230, 1750.40, None, "7,216g/Stk · 22 Karat", 6),
    ]

    other_items = [
        # name, kategorie, anzahl, gramm, feingehalt, feingold, betrag, ziel, notiz, sort
        ("Silber", "Silber", 1, None, None, None, 194.22, 6.0, None, 7),
        ("Krypto", "Krypto", 1, None, None, None, 0.0, 2.0, None, 8),
        ("MSCI World Islamic", "ETF", 1, None, None, None, 0.0, 25.0, "Zeyd schuldet 1.000€", 9),
        ("MSCI EM Islamic", "ETF", 1, None, None, None, 0.0, 12.0, "Zeyd schuldet 200€", 10),
        ("Bargeld", "Bargeld", 1, None, None, None, 800.00, None, "+500€ verliehen an Orhan", 11),
    ]

    for item in gold_items + other_items:
        db.execute("""
            INSERT INTO vermoegen (name, kategorie, anzahl, gramm, feingehalt, feingold, betrag, ziel_prozent, notiz, sort_order)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
        """, item)

    # Calculate and store percentages
    update_percentages(db)

def update_percentages(db=None):
    """Recalculate ist_prozent for all assets based on total."""
    close_db = False
    if db is None:
        db = sqlite3.connect(str(DB_PATH))
        db.row_factory = sqlite3.Row
        close_db = True

    total = db.execute("SELECT COALESCE(SUM(betrag), 0) FROM vermoegen").fetchone()[0]
    if total > 0:
        rows = db.execute("SELECT id, betrag FROM vermoegen").fetchall()
        for row in rows:
            pct = round((row["betrag"] / total) * 100, 1)
            db.execute("UPDATE vermoegen SET ist_prozent = ?, updated_at = datetime('now','localtime') WHERE id = ?",
                       (pct, row["id"]))
    if close_db:
        db.commit()
        db.close()

# ── Auth ───────────────────────────────────────────────

def check_auth(credentials: HTTPBasicCredentials = Depends(security)):
    if credentials.username != AUTH_USER or credentials.password != AUTH_PASS:
        raise HTTPException(401, "Unauthorized")
    return credentials

# ── Middleware ─────────────────────────────────────────

@app.middleware("http")
async def add_frame_options(request: Request, call_next):
    response = await call_next(request)
    response.headers["X-Frame-Options"] = "ALLOWALL"
    response.headers["Content-Security-Policy"] = "frame-ancestors 'self' http://*:* https://*:*;"
    return response

# ── Static ────────────────────────────────────────────

@app.get("/")
def serve_frontend(auth=Depends(check_auth)):
    return FileResponse(FRONTEND_DIR / "index.html")

@app.get("/icon.svg")
def serve_icon():
    return FileResponse(FRONTEND_DIR / "icon.svg", media_type="image/svg+xml")

# ── API ───────────────────────────────────────────────

@app.get("/api/health")
def health():
    return {"status": "ok"}

@app.get("/api/summary")
def get_summary(auth=Depends(check_auth)):
    with get_db() as db:
        total = db.execute("SELECT COALESCE(SUM(betrag), 0) FROM vermoegen").fetchone()[0]
        gold_betrag = db.execute("SELECT COALESCE(SUM(betrag), 0) FROM vermoegen WHERE kategorie='Gold'").fetchone()[0]
        gold_gramm = db.execute("SELECT COALESCE(SUM(feingold), 0) FROM vermoegen WHERE kategorie='Gold'").fetchone()[0]
        gold_brutto = db.execute("SELECT COALESCE(SUM(gramm * anzahl), 0) FROM vermoegen WHERE kategorie='Gold'").fetchone()[0]
        count = db.execute("SELECT COUNT(*) FROM vermoegen").fetchone()[0]

    return {
        "total_eur": round(total, 2),
        "gold_eur": round(gold_betrag, 2),
        "gold_fein_g": round(gold_gramm, 2),
        "gold_brutto_g": round(gold_brutto, 2),
        "count": count,
        "stand": datetime.datetime.now().strftime("%d.%m.%Y %H:%M")
    }

@app.get("/api/vermoegen")
def get_vermoegen(auth=Depends(check_auth)):
    with get_db() as db:
        rows = db.execute(
            "SELECT * FROM vermoegen ORDER BY sort_order"
        ).fetchall()
    return [dict(r) for r in rows]

@app.put("/api/vermoegen/{item_id}")
async def update_vermoegen(item_id: int, request: Request, auth=Depends(check_auth)):
    data = await request.json()
    allowed = ["name", "kategorie", "anzahl", "gramm", "feingehalt", "betrag", "ziel_prozent", "notiz"]
    updates = {k: v for k, v in data.items() if k in allowed}

    if not updates:
        raise HTTPException(400, "Keine gültigen Felder")

    # Recalculate feingold if gramm or feingehalt changed
    if "gramm" in updates or "feingehalt" in updates:
        with get_db() as db:
            row = db.execute("SELECT * FROM vermoegen WHERE id=?", (item_id,)).fetchone()
            if not row:
                raise HTTPException(404, "Nicht gefunden")
            anzahl = updates.get("anzahl", row["anzahl"])
            gramm = updates.get("gramm", row["gramm"])
            feingehalt = updates.get("feingehalt", row["feingehalt"])
            if gramm and feingehalt:
                updates["feingold"] = round(gramm * anzahl * feingehalt, 4)

    set_clause = ", ".join(f"{k}=?" for k in updates.keys())
    values = list(updates.values())

    with get_db() as db:
        db.execute(
            f"UPDATE vermoegen SET {set_clause}, updated_at=datetime('now','localtime') WHERE id=?",
            values + [item_id]
        )
        update_percentages(db)

    return {"status": "ok", "id": item_id}

@app.post("/api/vermoegen")
async def create_vermoegen(request: Request, auth=Depends(check_auth)):
    data = await request.json()
    name = data.get("name", "").strip()
    if not name:
        raise HTTPException(400, "Name erforderlich")

    kategorie = data.get("kategorie", "Sonstiges")
    anzahl = data.get("anzahl", 1)
    gramm = data.get("gramm")
    feingehalt = data.get("feingehalt")
    feingold = None
    if gramm and feingehalt:
        feingold = round(gramm * anzahl * feingehalt, 4)
    betrag = data.get("betrag", 0)
    ziel = data.get("ziel_prozent")
    notiz = data.get("notiz")

    with get_db() as db:
        # Get next sort_order
        max_sort = db.execute("SELECT COALESCE(MAX(sort_order), 0) FROM vermoegen").fetchone()[0]
        cursor = db.execute("""
            INSERT INTO vermoegen (name, kategorie, anzahl, gramm, feingehalt, feingold, betrag, ziel_prozent, notiz, sort_order)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
        """, (name, kategorie, anzahl, gramm, feingehalt, feingold, betrag, ziel, notiz, max_sort + 1))
        update_percentages(db)
        return {"status": "ok", "id": cursor.lastrowid}

@app.delete("/api/vermoegen/{item_id}")
def delete_vermoegen(item_id: int, auth=Depends(check_auth)):
    with get_db() as db:
        db.execute("DELETE FROM vermoegen WHERE id=?", (item_id,))
        update_percentages(db)
    return {"status": "ok"}

# ── Init on startup ────────────────────────────────────

init_db()

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=3003)
