"""
PostgreSQL store — production-grade, supports concurrent writes.

Install:  pip install "clawid[postgres]"

Usage:
    store = PostgreSQLStore("postgresql://user:pass@host:5432/mydb")
"""

import json
import time

from .base import ClawIDStore


class PostgreSQLStore(ClawIDStore):

    def __init__(self, dsn: str):
        try:
            import psycopg2
            import psycopg2.extras
            self._psycopg2 = psycopg2
        except ImportError:
            raise ImportError(
                "psycopg2 is required for PostgreSQLStore.\n"
                "Install it with:  pip install 'clawid[postgres]'"
            )
        self.conn = psycopg2.connect(dsn)
        self.conn.autocommit = False
        self._migrate()

    def _migrate(self) -> None:
        with self.conn.cursor() as cur:
            cur.execute("""
                CREATE TABLE IF NOT EXISTS clawid_assets (
                    clawid     TEXT PRIMARY KEY,
                    metadata   JSONB           NOT NULL,
                    created_at DOUBLE PRECISION NOT NULL,
                    updated_at DOUBLE PRECISION NOT NULL
                )
            """)
            cur.execute(
                "CREATE INDEX IF NOT EXISTS idx_clawid_created ON clawid_assets(created_at)"
            )
        self.conn.commit()

    def save(self, clawid: str, metadata: dict) -> None:
        now = time.time()
        with self.conn.cursor() as cur:
            cur.execute(
                """
                INSERT INTO clawid_assets (clawid, metadata, created_at, updated_at)
                VALUES (%s, %s, %s, %s)
                ON CONFLICT (clawid) DO UPDATE SET
                    metadata   = EXCLUDED.metadata,
                    updated_at = EXCLUDED.updated_at
                """,
                (clawid, json.dumps(metadata), now, now),
            )
        self.conn.commit()

    def get(self, clawid: str) -> dict | None:
        with self.conn.cursor() as cur:
            cur.execute(
                "SELECT metadata FROM clawid_assets WHERE clawid = %s", (clawid,)
            )
            row = cur.fetchone()
        if row is None:
            return None
        meta = row[0]
        return meta if isinstance(meta, dict) else json.loads(meta)

    def delete(self, clawid: str) -> bool:
        with self.conn.cursor() as cur:
            cur.execute(
                "DELETE FROM clawid_assets WHERE clawid = %s", (clawid,)
            )
            deleted = cur.rowcount > 0
        self.conn.commit()
        return deleted

    def exists(self, clawid: str) -> bool:
        with self.conn.cursor() as cur:
            cur.execute(
                "SELECT 1 FROM clawid_assets WHERE clawid = %s", (clawid,)
            )
            return cur.fetchone() is not None

    def close(self) -> None:
        self.conn.close()
