"""Draft 저장소 — SQLite 기반 draft artifact 영속성."""

import json
import logging
import os
import sqlite3
import uuid
from contextlib import contextmanager
from datetime import datetime, timezone

logger = logging.getLogger("sentinel.services.draft_store")


class DraftStore:
    """SQLite 기반 draft artifact 저장소."""

    def __init__(self, db_path: str | None = None):
        self.db_path = db_path or os.path.join(
            os.environ.get("SENTINEL_CHECKPOINT_DIR", "./runtime/checkpoints"),
            "drafts.db",
        )
        self._initialized = False

    def _ensure_initialized(self):
        if self._initialized:
            return
        os.makedirs(os.path.dirname(self.db_path), exist_ok=True)
        self._init_db()
        self._initialized = True

    def _init_db(self):
        with self._conn() as conn:
            conn.execute("""
                CREATE TABLE IF NOT EXISTS drafts (
                    id TEXT PRIMARY KEY,
                    type TEXT NOT NULL,
                    data_json TEXT NOT NULL,
                    review_status TEXT NOT NULL DEFAULT 'pending',
                    created_at TEXT NOT NULL,
                    updated_at TEXT,
                    approval_id TEXT
                )
            """)
            conn.execute("""
                CREATE INDEX IF NOT EXISTS idx_drafts_type ON drafts(type)
            """)
            conn.execute("""
                CREATE INDEX IF NOT EXISTS idx_drafts_status ON drafts(review_status)
            """)

    @contextmanager
    def _conn(self):
        conn = sqlite3.connect(self.db_path)
        conn.row_factory = sqlite3.Row
        try:
            yield conn
            conn.commit()
        finally:
            conn.close()

    def save(self, draft: dict) -> str:
        """draft를 저장합니다. draft['id']가 없으면 생성합니다."""
        self._ensure_initialized()
        draft_id = draft.get("id", uuid.uuid4().hex[:12])
        draft["id"] = draft_id
        now = datetime.now(timezone.utc).isoformat()

        with self._conn() as conn:
            conn.execute(
                """INSERT OR REPLACE INTO drafts (id, type, data_json, review_status, created_at, updated_at)
                   VALUES (?, ?, ?, ?, ?, ?)""",
                (
                    draft_id,
                    draft.get("type", "unknown"),
                    json.dumps(draft, ensure_ascii=False, default=str),
                    draft.get("review_status", "pending"),
                    draft.get("created_at", now),
                    now,
                ),
            )
        return draft_id

    def get(self, draft_id: str) -> dict | None:
        """단일 draft를 조회합니다."""
        self._ensure_initialized()
        with self._conn() as conn:
            row = conn.execute(
                "SELECT * FROM drafts WHERE id = ?", (draft_id,)
            ).fetchone()
            if not row:
                return None
            d = dict(row)
            d["data"] = json.loads(d.pop("data_json"))
            return d

    def list_drafts(
        self,
        draft_type: str | None = None,
        status: str | None = None,
        limit: int = 50,
    ) -> list[dict]:
        """draft 목록을 조회합니다."""
        self._ensure_initialized()
        sql = "SELECT * FROM drafts WHERE 1=1"
        params: list = []
        if draft_type:
            sql += " AND type = ?"
            params.append(draft_type)
        if status:
            sql += " AND review_status = ?"
            params.append(status)
        sql += " ORDER BY created_at DESC LIMIT ?"
        params.append(limit)

        with self._conn() as conn:
            rows = conn.execute(sql, params).fetchall()
            results = []
            for row in rows:
                d = dict(row)
                d["data"] = json.loads(d.pop("data_json"))
                results.append(d)
            return results

    def update_status(self, draft_id: str, status: str, approval_id: str | None = None) -> bool:
        """draft의 review_status를 업데이트합니다."""
        self._ensure_initialized()
        now = datetime.now(timezone.utc).isoformat()
        with self._conn() as conn:
            params: list = [status, now]
            sql = "UPDATE drafts SET review_status = ?, updated_at = ?"
            if approval_id:
                sql += ", approval_id = ?"
                params.append(approval_id)
            sql += " WHERE id = ?"
            params.append(draft_id)
            cur = conn.execute(sql, params)
            return cur.rowcount > 0


# 모듈 레벨 싱글턴
draft_store = DraftStore()
