"""tarot.db SQLite — 5 CRUD + _tarot_row_to_dict + init_db."""
import json
import os
import sqlite3
from typing import Any, Dict, Optional

from .config import DB_PATH


def _conn() -> sqlite3.Connection:
    os.makedirs(os.path.dirname(DB_PATH), exist_ok=True)
    conn = sqlite3.connect(DB_PATH, timeout=120.0)
    conn.row_factory = sqlite3.Row
    conn.execute("PRAGMA journal_mode=WAL")
    conn.execute("PRAGMA busy_timeout=120000")
    return conn


def init_db() -> None:
    with _conn() as conn:
        conn.execute("""
            CREATE TABLE IF NOT EXISTS tarot_readings (
                id                  INTEGER PRIMARY KEY AUTOINCREMENT,
                created_at          TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
                spread_type         TEXT NOT NULL,
                category            TEXT,
                question            TEXT,
                cards               TEXT NOT NULL,
                interpretation_json TEXT,
                summary             TEXT,
                model               TEXT,
                tokens_in           INTEGER,
                tokens_out          INTEGER,
                cost_usd            REAL,
                confidence          TEXT,
                favorite            INTEGER NOT NULL DEFAULT 0,
                note                TEXT
            )
        """)
        conn.execute("""
            CREATE INDEX IF NOT EXISTS idx_tarot_created
            ON tarot_readings(created_at DESC)
        """)
        conn.execute("""
            CREATE INDEX IF NOT EXISTS idx_tarot_favorite
            ON tarot_readings(favorite, created_at DESC)
        """)


def save_tarot_reading(data: Dict[str, Any]) -> int:
    interp = data.get("interpretation_json") or {}
    summary = interp.get("summary", "") if isinstance(interp, dict) else ""
    with _conn() as conn:
        cur = conn.execute(
            """INSERT INTO tarot_readings
               (spread_type, category, question, cards, interpretation_json,
                summary, model, tokens_in, tokens_out, cost_usd, confidence)
               VALUES (?,?,?,?,?,?,?,?,?,?,?)""",
            (
                data["spread_type"],
                data.get("category"),
                data.get("question"),
                json.dumps(data.get("cards") or [], ensure_ascii=False),
                json.dumps(interp, ensure_ascii=False) if interp else None,
                summary,
                data.get("model"),
                data.get("tokens_in"),
                data.get("tokens_out"),
                data.get("cost_usd"),
                data.get("confidence"),
            ),
        )
        return int(cur.lastrowid)


def get_tarot_reading(reading_id: int) -> Optional[Dict[str, Any]]:
    with _conn() as conn:
        r = conn.execute("SELECT * FROM tarot_readings WHERE id=?", (reading_id,)).fetchone()
    return _tarot_row_to_dict(r) if r else None


def list_tarot_readings(
    page: int = 1, size: int = 20,
    favorite: Optional[bool] = None,
    spread_type: Optional[str] = None,
    category: Optional[str] = None,
) -> Dict[str, Any]:
    wheres, params = [], []
    if favorite is not None:
        wheres.append("favorite=?")
        params.append(1 if favorite else 0)
    if spread_type:
        wheres.append("spread_type=?")
        params.append(spread_type)
    if category:
        wheres.append("category=?")
        params.append(category)
    where_sql = ("WHERE " + " AND ".join(wheres)) if wheres else ""
    offset = (page - 1) * size
    with _conn() as conn:
        total = conn.execute(
            f"SELECT COUNT(*) c FROM tarot_readings {where_sql}", params
        ).fetchone()["c"]
        rows = conn.execute(
            f"SELECT * FROM tarot_readings {where_sql} ORDER BY created_at DESC LIMIT ? OFFSET ?",
            params + [size, offset],
        ).fetchall()
    return {
        "items": [_tarot_row_to_dict(r) for r in rows],
        "page": page, "size": size, "total": int(total),
    }


def update_tarot_reading(reading_id: int, **kwargs) -> None:
    sets, vals = [], []
    if "favorite" in kwargs and kwargs["favorite"] is not None:
        sets.append("favorite=?")
        vals.append(1 if kwargs["favorite"] else 0)
    if "note" in kwargs and kwargs["note"] is not None:
        sets.append("note=?")
        vals.append(kwargs["note"])
    if not sets:
        return
    vals.append(reading_id)
    with _conn() as conn:
        conn.execute(f"UPDATE tarot_readings SET {','.join(sets)} WHERE id=?", vals)


def delete_tarot_reading(reading_id: int) -> None:
    with _conn() as conn:
        conn.execute("DELETE FROM tarot_readings WHERE id=?", (reading_id,))


def _tarot_row_to_dict(r) -> Dict[str, Any]:
    try:
        interp = json.loads(r["interpretation_json"]) if r["interpretation_json"] else None
    except (ValueError, TypeError):
        interp = None
    try:
        cards = json.loads(r["cards"]) if r["cards"] else []
    except (ValueError, TypeError):
        cards = []
    return {
        "id": r["id"],
        "created_at": r["created_at"],
        "spread_type": r["spread_type"],
        "category": r["category"],
        "question": r["question"],
        "cards": cards,
        "interpretation_json": interp,
        "summary": r["summary"],
        "model": r["model"],
        "tokens_in": r["tokens_in"],
        "tokens_out": r["tokens_out"],
        "cost_usd": r["cost_usd"],
        "confidence": r["confidence"],
        "favorite": int(r["favorite"]),
        "note": r["note"],
    }
