from __future__ import annotations

import json
import sqlite3
from typing import Any


class HeavenRepository:
    def add(
        self,
        connection: sqlite3.Connection,
        *,
        user_id: int,
        mode: str,
        reading_date: str,
        subject_key: str,
        result: dict[str, Any],
        created_at: str,
    ) -> int:
        cursor = connection.execute(
            """
            INSERT INTO heaven_readings (
                user_id, mode, reading_date, subject_key, result_json,
                interpretation_status, created_at, updated_at
            ) VALUES (?, ?, ?, ?, ?, 'pending', ?, ?)
            """,
            (
                user_id,
                mode,
                reading_date,
                subject_key,
                json.dumps(result, ensure_ascii=False, separators=(",", ":")),
                created_at,
                created_at,
            ),
        )
        return int(cursor.lastrowid)

    def get(
        self, connection: sqlite3.Connection, user_id: int, reading_id: int
    ) -> sqlite3.Row | None:
        return connection.execute(
            "SELECT * FROM heaven_readings WHERE id = ? AND user_id = ?",
            (reading_id, user_id),
        ).fetchone()

    def latest_fortune(
        self, connection: sqlite3.Connection, user_id: int, reading_date: str
    ) -> sqlite3.Row | None:
        return connection.execute(
            """
            SELECT * FROM heaven_readings
            WHERE user_id = ? AND mode = 'fortune' AND reading_date = ?
            ORDER BY id DESC LIMIT 1
            """,
            (user_id, reading_date),
        ).fetchone()

    def ensure_fortune(
        self,
        connection: sqlite3.Connection,
        *,
        user_id: int,
        reading_date: str,
        result: dict[str, Any],
        created_at: str,
    ) -> tuple[sqlite3.Row, bool]:
        cursor = connection.execute(
            """
            INSERT OR IGNORE INTO heaven_readings (
                user_id, mode, reading_date, subject_key, result_json,
                interpretation_status, created_at, updated_at
            ) VALUES (?, 'fortune', ?, '', ?, 'pending', ?, ?)
            """,
            (
                user_id,
                reading_date,
                json.dumps(result, ensure_ascii=False, separators=(",", ":")),
                created_at,
                created_at,
            ),
        )
        row = self.latest_fortune(connection, user_id, reading_date)
        if row is None:
            raise RuntimeError("每日解运记录写入失败")
        return row, cursor.rowcount == 0

    def list(
        self,
        connection: sqlite3.Connection,
        user_id: int,
        mode: str | None,
        reading_date: str | None,
        limit: int = 60,
    ) -> tuple[sqlite3.Row, ...]:
        clauses = ["user_id = ?"]
        values: list[Any] = [user_id]
        if mode:
            clauses.append("mode = ?")
            values.append(mode)
        if reading_date:
            clauses.append("reading_date = ?")
            values.append(reading_date)
        values.append(limit)
        statement = (
            f"SELECT * FROM heaven_readings WHERE {' AND '.join(clauses)} ORDER BY id DESC LIMIT ?"
        )
        return tuple(
            connection.execute(
                statement,
                values,
            ).fetchall()
        )

    def update_interpretation(
        self,
        connection: sqlite3.Connection,
        reading_id: int,
        user_id: int,
        content: str,
        status: str,
        request_id: str | None,
        updated_at: str,
    ) -> None:
        connection.execute(
            """
            UPDATE heaven_readings
            SET interpretation = ?, interpretation_status = ?, request_id = ?, updated_at = ?
            WHERE id = ? AND user_id = ?
            """,
            (content, status, request_id, updated_at, reading_id, user_id),
        )

    def delete(self, connection: sqlite3.Connection, user_id: int, reading_id: int) -> int:
        cursor = connection.execute(
            "DELETE FROM heaven_readings WHERE id = ? AND user_id = ?",
            (reading_id, user_id),
        )
        return cursor.rowcount
