-- Extensions
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "pgcrypto"; -- For additional crypto if needed

-- Schema: api (exposed to PostgREST)
CREATE SCHEMA api;

-- Users Table
CREATE TABLE api.users (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    email TEXT UNIQUE NOT NULL CHECK (email ~* '^.+@.+\..+$'),
    verifier TEXT NOT NULL, -- SRP-6a verifier
    salt TEXT NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Secrets Table
CREATE TABLE api.secrets (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    owner_id UUID NOT NULL REFERENCES api.users(id),
    encrypted_data BYTEA NOT NULL,
    iv TEXT NOT NULL,
    auth_tag TEXT NOT NULL,
    type TEXT DEFAULT 'manual',
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Access Policies (Many-to-Many for sharing)
CREATE TABLE api.access_policies (
    secret_id UUID NOT NULL REFERENCES api.secrets(id) ON DELETE CASCADE,
    user_id UUID NOT NULL REFERENCES api.users(id) ON DELETE CASCADE,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    PRIMARY KEY (secret_id, user_id)
);

-- Roles & Permissions (PostgREST)
-- We need a role for the anonymous web user and one for authenticated users.
-- Note: 'web_anon' and 'todo_user' are placeholders. We should use:
-- 'web_anon' (unauthenticated)
-- 'authenticated' (logged in via JWT)

CREATE ROLE web_anon NOLOGIN;
GRANT USAGE ON SCHEMA api TO web_anon;
GRANT SELECT ON api.users TO web_anon; -- Needed for login (salt lookup)

CREATE ROLE authenticated NOLOGIN;
GRANT USAGE ON SCHEMA api TO authenticated;
GRANT ALL ON api.secrets TO authenticated;
GRANT SELECT ON api.access_policies TO authenticated;
GRANT SELECT ON api.users TO authenticated;

-- Row Level Security (RLS)
ALTER TABLE api.secrets ENABLE ROW LEVEL SECURITY;

-- Helper function to get current user ID from JWT
CREATE OR REPLACE FUNCTION api.uid() RETURNS UUID AS $$
    SELECT NULLIF(current_setting('request.jwt.claim.sub', true), '')::uuid;
$$ LANGUAGE SQL STABLE;

-- RLS Policy for Secrets
CREATE POLICY secrets_owner_policy ON api.secrets
    FOR ALL
    TO authenticated
    USING (
        owner_id = api.uid()
    )
    WITH CHECK (
        owner_id = api.uid()
    );

CREATE POLICY secrets_shared_policy ON api.secrets
    FOR SELECT
    TO authenticated
    USING (
        EXISTS (
            SELECT 1 FROM api.access_policies 
            WHERE secret_id = api.secrets.id 
            AND user_id = api.uid()
        )
    );

-- Grant privileges to the authenticator role (the one PostgREST connects as)
-- In the docker-compose, we used user:pass. We need to grant role usage to 'user'.
-- Ideally, create a separate 'authenticator' role.
CREATE ROLE authenticator NOINHERIT LOGIN PASSWORD 'mysecretpassword';
GRANT web_anon TO authenticator;
GRANT authenticated TO authenticator;

-- BUT since we are using 'user' from the postgres docker image as the connector,
-- we'll just grant to 'user' or 'postgres'.
-- Simpler for dev: Grant to the user specified in connection string.
GRANT web_anon TO "user";
GRANT authenticated TO "user";
