import os
import asyncpg
from typing import Optional

_pool: Optional[asyncpg.Pool] = None


async def init_pool() -> None:
    global _pool
    _pool = await asyncpg.create_pool(
        host=os.environ.get("PGHOST", "timescaledb"),
        port=int(os.environ.get("PGPORT", 5432)),
        database=os.environ.get("PGDATABASE", "leaf"),
        user=os.environ.get("PGUSER", "postgres"),
        password=os.environ.get("PGPASSWORD", ""),
        min_size=2,
        max_size=10,
    )


async def close_pool() -> None:
    if _pool:
        await _pool.close()


async def fetch(sql: str, *args) -> list:
    async with _pool.acquire() as conn:
        return await conn.fetch(sql, *args)


async def fetchrow(sql: str, *args) -> Optional[asyncpg.Record]:
    async with _pool.acquire() as conn:
        return await conn.fetchrow(sql, *args)


async def fetchval(sql: str, *args):
    async with _pool.acquire() as conn:
        return await conn.fetchval(sql, *args)


async def execute(sql: str, *args) -> str:
    async with _pool.acquire() as conn:
        return await conn.execute(sql, *args)


async def get_setting(key: str, namespace: str = "general") -> str | None:
    if _pool is None:
        return None
    return await fetchval(
        "SELECT value FROM setting WHERE namespace = $1 AND key = $2",
        namespace,
        key,
    )


async def set_setting(key: str, value: str, namespace: str = "general") -> None:
    await execute(
        """
        INSERT INTO setting (namespace, key, value)
        VALUES ($1, $2, $3)
        ON CONFLICT (namespace, key) DO UPDATE SET value = EXCLUDED.value, updated_at = now()
        """,
        namespace,
        key,
        value,
    )


async def fetch_as_user(email: str, sql: str, *args) -> list:
    """
    Execute a query with RLS scoped to the given user email.
    Uses SET LOCAL inside a transaction so the setting is connection-safe.
    Requires a non-superuser DB account; superusers bypass RLS.
    """
    async with _pool.acquire() as conn:
        async with conn.transaction():
            await conn.execute(
                "SELECT set_config('app.current_user_email', $1, true)", email
            )
            return await conn.fetch(sql, *args)
