create extension if not exists pgcrypto;

create table users (
    id uuid primary key default gen_random_uuid(),
    oidc_subject text not null unique,
    email text not null,
    display_name text,
    created_at timestamptz not null default now()
);

create table albums (
    id uuid primary key default gen_random_uuid(),
    name text not null,
    description text not null default '',
    created_at timestamptz not null default now()
);

create table photos (
    id uuid primary key default gen_random_uuid(),
    album_id uuid not null references albums(id) on delete cascade,
    filename text not null,
    content_type text not null,
    size_bytes bigint not null default 0,
    status text not null default 'uploaded', -- uploaded | processing | ready | error
    error text,
    width int,
    height int,
    taken_at timestamptz,
    -- Bumped on every (re)process; cache-buster for preview/thumb URLs.
    processed_at timestamptz,
    created_at timestamptz not null default now()
);

create index photos_album_idx on photos (album_id);

create table shares (
    id uuid primary key default gen_random_uuid(),
    album_id uuid not null references albums(id) on delete cascade,
    token text not null unique,
    label text not null default '',
    password_hash text,
    allow_download boolean not null default true,
    expires_at timestamptz,
    -- Brute-force lockout state for password-protected shares.
    failed_attempts int not null default 0,
    locked_until timestamptz,
    created_at timestamptz not null default now()
);

create index shares_album_idx on shares (album_id);

create table ratings (
    share_id uuid not null references shares(id) on delete cascade,
    photo_id uuid not null references photos(id) on delete cascade,
    rating int not null check (rating between 1 and 5),
    updated_at timestamptz not null default now(),
    primary key (share_id, photo_id)
);

-- Cascaded photo deletes fire per-row FK triggers; without this each one
-- sequential-scans the table.
create index ratings_photo_idx on ratings (photo_id);

create table tags (
    id uuid primary key default gen_random_uuid(),
    share_id uuid not null references shares(id) on delete cascade,
    photo_id uuid not null references photos(id) on delete cascade,
    tag text not null,
    created_at timestamptz not null default now(),
    unique (share_id, photo_id, tag)
);

create index tags_photo_idx on tags (photo_id);

create table jobs (
    id uuid primary key default gen_random_uuid(),
    kind text not null,
    payload jsonb not null default '{}',
    status text not null default 'queued', -- queued | running | done | failed
    attempts int not null default 0,
    max_attempts int not null default 5,
    run_at timestamptz not null default now(),
    locked_by text,
    locked_at timestamptz,
    last_error text,
    created_at timestamptz not null default now()
);

create index jobs_poll_idx on jobs (status, run_at);
