"""qualitative_sell_strategy_v1 산출물의 SQLite 시계열 저장소.

GAS/xlsx 구조와 완전히 분리된 추가(additive) 저장소다 — 이 모듈이 다루는 데이터는
순수 Python 산출물(KIS API 수집 + confluence 판단 결과)이며, GAS가 쓰지도 읽지도
않고 사람이 시트에서 직접 편집하지도 않는다. 기존 outputs/qualitative_sell_strategy/
*.json 파일 출력을 대체하지 않고 병행 저장한다(JSON은 1회성 점검용, SQLite는 시계열
추이 조회용). 표준 라이브러리 sqlite3만 사용 — 추가 의존성 없음.
"""
from __future__ import annotations

import json
import sqlite3
from pathlib import Path
from dataclasses import dataclass
from typing import Any

from src.quant_engine.storage_backend_v1 import StoreSpec, default_sqlite_store_path, normalize_store_spec

SCHEMA = """
CREATE TABLE IF NOT EXISTS sell_strategy_results (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    code TEXT NOT NULL,
    generated_at TEXT NOT NULL,
    action TEXT,
    conviction TEXT,
    market_regime TEXT,
    composite_score REAL,
    rationale TEXT,
    raw_json TEXT NOT NULL,
    inserted_at TEXT DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_sell_strategy_code_time
    ON sell_strategy_results(code, generated_at);

CREATE TABLE IF NOT EXISTS satellite_recommendations (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    ticker TEXT NOT NULL,
    generated_at TEXT NOT NULL,
    satellite_action TEXT,
    attractiveness_score REAL,
    market_regime TEXT,
    raw_json TEXT NOT NULL,
    inserted_at TEXT DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_satellite_ticker_time
    ON satellite_recommendations(ticker, generated_at);
"""


@dataclass(frozen=True)
class QualitativeSellStoreSpec(StoreSpec):
    pass


def default_qualitative_sell_store_path(root: Path) -> Path:
    return default_sqlite_store_path(root, "qualitative_sell_strategy/qualitative_sell_strategy.db")


def resolve_store_path(spec: QualitativeSellStoreSpec, root: Path) -> Path:
    backend, location = normalize_store_spec(
        spec,
        root,
        default_sqlite_name="qualitative_sell_strategy/qualitative_sell_strategy.db",
    )
    if backend != "sqlite":
        raise ValueError(
            "qualitative_sell_strategy_store_v1 currently executes on sqlite only; "
            "the caller contract already allows future PostgreSQL swap-in."
        )
    return Path(location)


def init_db(db_path: Path) -> None:
    db_path.parent.mkdir(parents=True, exist_ok=True)
    conn = sqlite3.connect(db_path)
    try:
        conn.executescript(SCHEMA)
        conn.commit()
    finally:
        conn.close()


def insert_sell_strategy_result(db_path: Path, result: dict[str, Any]) -> None:
    """build_qualitative_sell_inputs_v1.process_one()의 반환값(dict)을 그대로 받는다."""
    init_db(db_path)
    decision = result.get("decision") or {}
    conn = sqlite3.connect(db_path)
    try:
        conn.execute(
            "INSERT INTO sell_strategy_results "
            "(code, generated_at, action, conviction, market_regime, composite_score, rationale, raw_json) "
            "VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
            (
                result.get("code"),
                result.get("generated_at"),
                decision.get("action"),
                decision.get("conviction"),
                decision.get("market_regime"),
                decision.get("composite_score"),
                decision.get("rationale"),
                json.dumps(result, ensure_ascii=False, default=str),
            ),
        )
        conn.commit()
    finally:
        conn.close()


def insert_satellite_recommendation(db_path: Path, generated_at: str, candidate: dict[str, Any]) -> None:
    """build_satellite_candidate_recommendations_v1.py results[i] 항목 하나를 받는다."""
    init_db(db_path)
    score = candidate.get("score") or {}
    conn = sqlite3.connect(db_path)
    try:
        conn.execute(
            "INSERT INTO satellite_recommendations "
            "(ticker, generated_at, satellite_action, attractiveness_score, market_regime, raw_json) "
            "VALUES (?, ?, ?, ?, ?, ?)",
            (
                candidate.get("ticker"),
                generated_at,
                score.get("satellite_action"),
                score.get("attractiveness_score"),
                score.get("market_regime"),
                json.dumps(candidate, ensure_ascii=False, default=str),
            ),
        )
        conn.commit()
    finally:
        conn.close()


def fetch_recent_sell_strategy_results(db_path: Path, code: str, limit: int = 20) -> list[dict[str, Any]]:
    if not db_path.exists():
        return []
    conn = sqlite3.connect(db_path)
    conn.row_factory = sqlite3.Row
    try:
        rows = conn.execute(
            "SELECT code, generated_at, action, conviction, market_regime, composite_score, rationale "
            "FROM sell_strategy_results WHERE code = ? ORDER BY generated_at DESC LIMIT ?",
            (code, limit),
        ).fetchall()
        return [dict(row) for row in rows]
    finally:
        conn.close()
