create extension if not exists "pgcrypto";

create table if not exists users (
  id uuid primary key default gen_random_uuid(),
  username text unique not null,
  password_hash text not null,
  is_active boolean not null default true,
  is_locked boolean not null default false,
  created_at timestamptz not null default now()
);

create table if not exists roles (
  id uuid primary key default gen_random_uuid(),
  slug text unique not null,
  name text not null,
  description text not null default '',
  created_at timestamptz not null default now()
);

create table if not exists permissions (
  id uuid primary key default gen_random_uuid(),
  resource text not null,
  action text not null,
  unique (resource, action)
);

create table if not exists role_permissions (
  role_id uuid not null references roles(id) on delete cascade,
  permission_id uuid not null references permissions(id) on delete cascade,
  scope_type text not null default 'global',
  scope_value text null
);

create unique index if not exists role_permissions_scope_uidx
  on role_permissions (role_id, permission_id, scope_type, coalesce(scope_value, ''));

create table if not exists user_roles (
  user_id uuid not null references users(id) on delete cascade,
  role_id uuid not null references roles(id) on delete cascade,
  primary key (user_id, role_id)
);

create table if not exists resource_groups (
  id uuid primary key default gen_random_uuid(),
  slug text unique not null,
  name text not null
);

create table if not exists resource_group_tables (
  group_id uuid not null references resource_groups(id) on delete cascade,
  table_name text not null,
  primary key (group_id, table_name)
);

create table if not exists sessions (
  id uuid primary key default gen_random_uuid(),
  user_id uuid not null references users(id) on delete cascade,
  token_hash text not null unique,
  expires_at timestamptz not null,
  ip text null,
  user_agent text null,
  created_at timestamptz not null default now()
);

create table if not exists audit_events (
  id uuid primary key default gen_random_uuid(),
  created_at timestamptz not null default now(),
  actor_user_id uuid null references users(id) on delete set null,
  action text not null,
  resource_type text not null,
  resource_name text null,
  group_id text null,
  target_connection_id text null,
  sql_text_masked text null,
  payload_before jsonb null,
  payload_after jsonb null,
  ip text null,
  user_agent text null,
  status text not null
);

create table if not exists db_connections (
  id uuid primary key default gen_random_uuid(),
  name text not null,
  host text not null,
  port integer not null,
  database_name text not null,
  is_default boolean not null default false,
  created_at timestamptz not null default now()
);

insert into permissions (resource, action) values
  ('database', 'read'),
  ('database', 'write'),
  ('database', 'delete'),
  ('database', 'schema_change'),
  ('group', 'read'),
  ('group', 'write'),
  ('group', 'delete'),
  ('group', 'schema_change'),
  ('table', 'read'),
  ('table', 'write'),
  ('table', 'delete'),
  ('table', 'schema_change'),
  ('sql_console', 'execute_sql'),
  ('logs', 'view_logs'),
  ('users', 'manage_users'),
  ('roles', 'manage_roles'),
  ('audit', 'read')
on conflict do nothing;

insert into roles (slug, name, description) values
  ('root', 'Root', 'Full access to the control plane'),
  ('folder_admin', 'Folder Admin', 'Admin for selected groups'),
  ('user', 'User', 'Read-only or restricted access')
on conflict do nothing;

insert into resource_groups (slug, name) values
  ('finance', 'Finance'),
  ('users', 'Users'),
  ('logs', 'Logs')
on conflict do nothing;

insert into resource_group_tables (group_id, table_name)
select g.id, x.table_name
from (
  values
    ('finance', 'finance__invoices'),
    ('users', 'users__accounts'),
    ('logs', 'logs__events')
) as x(group_slug, table_name)
join resource_groups g on g.slug = x.group_slug
on conflict do nothing;

insert into db_connections (name, host, port, database_name, is_default)
values ('Default Target DB', 'postgres-target', 5432, 'appdb', true)
on conflict do nothing;
