import os
from typing import List, Optional, Dict, Any

import psycopg2
import psycopg2.extras


def get_conn():
    user = os.getenv("DB_USER")
    password = os.getenv("DB_PASSWORD")
    if not user or not password:
        raise RuntimeError("DB_USER 또는 DB_PASSWORD가 설정되지 않았습니다.")

    return psycopg2.connect(
        host="ncue.net",
        port=5432,
        dbname="tts",
        user=user,
        password=password,
    )


def init_db():
    with get_conn() as conn:
        with conn.cursor() as cur:
            cur.execute(
                """
                CREATE TABLE IF NOT EXISTS tts_items (
                    id SERIAL PRIMARY KEY,
                    text TEXT NOT NULL,
                    filename TEXT,
                    size_bytes BIGINT,
                    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
                );
                """
            )
            cur.execute(
                """
                ALTER TABLE tts_items
                ADD COLUMN IF NOT EXISTS size_bytes BIGINT;
                """
            )
            cur.execute(
                """
                CREATE INDEX IF NOT EXISTS tts_items_created_at_idx
                ON tts_items (created_at DESC);
                """
            )
        conn.commit()


def create_item(text: str) -> Dict[str, Any]:
    with get_conn() as conn:
        with conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor) as cur:
            cur.execute(
                """
                INSERT INTO tts_items (text)
                VALUES (%s)
                RETURNING id, created_at;
                """,
                (text,),
            )
            row = cur.fetchone()
        conn.commit()
    return row


def update_filename(tts_id: int, filename: str) -> None:
    with get_conn() as conn:
        with conn.cursor() as cur:
            cur.execute(
                """
                UPDATE tts_items
                SET filename = %s
                WHERE id = %s;
                """,
                (filename, tts_id),
            )
        conn.commit()


def update_size_bytes(tts_id: int, size_bytes: int) -> None:
    with get_conn() as conn:
        with conn.cursor() as cur:
            cur.execute(
                """
                UPDATE tts_items
                SET size_bytes = %s
                WHERE id = %s;
                """,
                (size_bytes, tts_id),
            )
        conn.commit()


def list_items() -> List[Dict[str, Any]]:
    with get_conn() as conn:
        with conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor) as cur:
            cur.execute(
                """
                SELECT id, created_at, filename, size_bytes
                FROM tts_items
                ORDER BY created_at DESC;
                """
            )
            rows = cur.fetchall()
    return rows


def get_item(tts_id: int) -> Optional[Dict[str, Any]]:
    with get_conn() as conn:
        with conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor) as cur:
            cur.execute(
                """
                SELECT id, text, filename, size_bytes, created_at
                FROM tts_items
                WHERE id = %s;
                """,
                (tts_id,),
            )
            row = cur.fetchone()
    return row


def delete_items(ids: List[int]) -> List[Dict[str, Any]]:
    with get_conn() as conn:
        with conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor) as cur:
            cur.execute(
                """
                SELECT id, filename
                FROM tts_items
                WHERE id = ANY(%s);
                """,
                (ids,),
            )
            rows = cur.fetchall()

            cur.execute(
                """
                DELETE FROM tts_items
                WHERE id = ANY(%s);
                """,
                (ids,),
            )
        conn.commit()
    return rows


def delete_item_by_id(tts_id: int) -> None:
    with get_conn() as conn:
        with conn.cursor() as cur:
            cur.execute(
                """
                DELETE FROM tts_items
                WHERE id = %s;
                """,
                (tts_id,),
            )
        conn.commit()
