create table if not exists public.clients (
  id uuid primary key default gen_random_uuid(),
  email text not null,
  normalized_email text not null,
  first_name text,
  last_name text,
  phone text,
  last_login_at timestamptz,
  created_at timestamptz not null default now(),
  updated_at timestamptz not null default now()
);

create unique index if not exists clients_normalized_email_idx
  on public.clients (normalized_email);

create table if not exists public.client_access (
  id bigserial primary key,
  client_id uuid not null references public.clients(id) on delete cascade,
  tablo_id text not null references public.tablos(id) on delete cascade,
  granted_by uuid not null references public.profiles(id),
  granted_at timestamptz not null default now(),
  revoked_at timestamptz,
  created_at timestamptz not null default now()
);

create unique index if not exists client_access_active_unique_idx
  on public.client_access (client_id, tablo_id)
  where revoked_at is null;

create index if not exists client_access_client_id_idx
  on public.client_access (client_id);

create index if not exists client_access_tablo_id_idx
  on public.client_access (tablo_id);

create table if not exists public.client_magic_links (
  id bigserial primary key,
  client_id uuid not null references public.clients(id) on delete cascade,
  email text not null,
  purpose text not null check (purpose in ('invite', 'login')),
  tablo_id text references public.tablos(id) on delete cascade,
  token_hash text,
  jti text,
  redirect_to text,
  expires_at timestamptz not null,
  consumed_at timestamptz,
  created_by uuid references public.profiles(id),
  created_at timestamptz not null default now(),
  constraint client_magic_links_token_reference_check check (
    token_hash is not null or jti is not null
  )
);

create index if not exists client_magic_links_active_idx
  on public.client_magic_links (client_id, purpose, expires_at)
  where consumed_at is null;

create index if not exists client_magic_links_tablo_id_idx
  on public.client_magic_links (tablo_id);

create unique index if not exists client_magic_links_jti_unique_idx
  on public.client_magic_links (jti)
  where jti is not null;

create unique index if not exists client_magic_links_token_hash_unique_idx
  on public.client_magic_links (token_hash)
  where token_hash is not null;

alter table public.clients enable row level security;
alter table public.client_access enable row level security;
alter table public.client_magic_links enable row level security;

drop trigger if exists set_clients_updated_at on public.clients;
create trigger set_clients_updated_at
before update on public.clients
for each row
execute function public.set_updated_at();
