begin;

create table if not exists device_model_profiles (
  profile_ref text primary key,
  schema_version text not null,
  vendor text not null,
  model text not null,
  device_type text not null,
  protocol text not null,
  profile jsonb not null,
  created_at timestamptz not null default now(),
  updated_at timestamptz not null default now()
);

create table if not exists device_contours (
  id uuid primary key,
  owner_scope text not null,
  name text not null,
  lifecycle_state text not null default 'active'
    check (lifecycle_state in ('active', 'suspended', 'retired')),
  created_at timestamptz not null default now(),
  updated_at timestamptz not null default now(),
  unique (owner_scope, name)
);

create table if not exists device_discoveries (
  id uuid primary key,
  identifier_kind text not null,
  identifier_digest text not null,
  identifier_masked text not null,
  model_profile_ref text not null references device_model_profiles(profile_ref),
  protocol text not null,
  lifecycle_state text not null default 'quarantine'
    check (lifecycle_state in ('quarantine', 'claimed', 'rejected', 'expired')),
  first_observed_at timestamptz not null,
  last_observed_at timestamptz not null,
  evidence jsonb not null,
  claimed_device_id uuid,
  claimed_at timestamptz,
  claimed_by text,
  created_at timestamptz not null default now(),
  updated_at timestamptz not null default now(),
  unique (identifier_kind, identifier_digest, model_profile_ref)
);

create index if not exists device_discoveries_state_last_seen_idx
  on device_discoveries (lifecycle_state, last_observed_at desc);

create table if not exists device_instances (
  id uuid primary key,
  contour_id uuid not null references device_contours(id),
  model_profile_ref text not null references device_model_profiles(profile_ref),
  display_name text not null,
  identifier_kind text not null,
  identifier_digest text not null,
  identifier_masked text not null,
  credential_ref text,
  lifecycle_state text not null default 'claimed'
    check (lifecycle_state in ('claimed', 'online', 'offline', 'suspended', 'retired')),
  created_at timestamptz not null default now(),
  updated_at timestamptz not null default now(),
  unique (identifier_kind, identifier_digest, model_profile_ref)
);

alter table device_discoveries
  drop constraint if exists device_discoveries_claimed_device_fk;

alter table device_discoveries
  add constraint device_discoveries_claimed_device_fk
  foreign key (claimed_device_id) references device_instances(id);

create table if not exists device_bindings (
  id uuid primary key,
  contour_id uuid not null references device_contours(id),
  target_kind text not null,
  target_ref text not null,
  capabilities text[] not null,
  lifecycle_state text not null default 'active'
    check (lifecycle_state in ('active', 'revoked')),
  created_at timestamptz not null default now(),
  updated_at timestamptz not null default now(),
  unique (contour_id, target_kind, target_ref)
);

create table if not exists device_audit_events (
  id uuid primary key,
  event_type text not null,
  actor_ref text not null,
  contour_id uuid,
  device_id uuid,
  discovery_id uuid,
  payload jsonb not null,
  occurred_at timestamptz not null default now()
);

create index if not exists device_audit_events_device_time_idx
  on device_audit_events (device_id, occurred_at desc);

commit;
