"""Supabase/asyncpg database pool implementing DatabasePool protocol."""

from pathlib import Path
from typing import Any

import asyncpg


class SupabasePool:
    """asyncpg pool wrapper matching DatabasePool protocol."""

    def __init__(self, pool: asyncpg.Pool) -> None:
        self._pool = pool

    async def fetch_one(self, query: str, *args: Any) -> dict[str, Any] | None:
        """Fetch a single record."""
        async with self._pool.acquire() as conn:
            row = await conn.fetchrow(query, *args)
            return dict(row) if row else None

    async def fetch_all(self, query: str, *args: Any) -> list[dict[str, Any]]:
        """Fetch multiple records."""
        async with self._pool.acquire() as conn:
            rows = await conn.fetch(query, *args)
            return [dict(r) for r in rows]

    async def execute(self, query: str, *args: Any) -> None:
        """Execute a write query."""
        async with self._pool.acquire() as conn:
            await conn.execute(query, *args)

    async def close(self) -> None:
        """Close the connection pool."""
        await self._pool.close()


async def create_pool(database_url: str) -> SupabasePool:
    """Create connection pool from Supabase URL.

    Args:
        database_url: PostgreSQL connection string.

    Returns:
        SupabasePool instance ready for use.
    """
    pool = await asyncpg.create_pool(database_url, min_size=2, max_size=10)
    if pool is None:
        raise RuntimeError("Failed to create database pool")
    return SupabasePool(pool)


async def run_migrations(database_url: str) -> list[str]:
    """Run all migrations in order.

    Migrations are numbered SQL files in the migrations/ directory.
    Already-applied migrations are tracked in the _migrations table.

    Args:
        database_url: PostgreSQL connection string.

    Returns:
        List of migration filenames that were applied.
    """
    migrations_dir = Path(__file__).parent / "migrations"
    applied: list[str] = []

    pool = await asyncpg.create_pool(database_url, min_size=1, max_size=2)
    if pool is None:
        raise RuntimeError("Failed to create database pool for migrations")

    try:
        async with pool.acquire() as conn:
            # Create migrations tracking table
            await conn.execute("""
                CREATE TABLE IF NOT EXISTS _migrations (
                    name TEXT PRIMARY KEY,
                    applied_at TIMESTAMPTZ DEFAULT NOW()
                )
            """)

            # Get already applied
            rows = await conn.fetch("SELECT name FROM _migrations")
            already_applied = {r["name"] for r in rows}

            # Run new migrations in order
            for sql_file in sorted(migrations_dir.glob("*.sql")):
                if sql_file.name not in already_applied:
                    sql = sql_file.read_text()
                    await conn.execute(sql)
                    await conn.execute(
                        "INSERT INTO _migrations (name) VALUES ($1)", sql_file.name
                    )
                    applied.append(sql_file.name)
    finally:
        await pool.close()

    return applied
