create table if not exists signal_engine.evidence_snapshot (
    evidence_id text primary key,
    as_of timestamptz not null,
    published_at_cutoff timestamptz not null,
    dataset_id text not null,
    data_hash text not null,
    model_version text not null,
    config_version text not null,
    payload jsonb not null,
    content_hash text not null unique,
    created_at timestamptz not null default now()
);

create table if not exists signal_engine.signal_decision (
    decision_id uuid primary key,
    lot_id uuid not null,
    cycle_id uuid not null,
    evidence_id text not null references signal_engine.evidence_snapshot(evidence_id),
    action text not null,
    sell_fraction numeric(9,6) not null check (sell_fraction between 0 and 1),
    policy_id text not null,
    priority integer not null,
    reason_code text not null,
    reentry_eligible boolean not null,
    created_at timestamptz not null,
    decision_hash text not null unique
);

create table if not exists signal_engine.reentry_watch (
    watch_id uuid primary key,
    sell_decision_id uuid not null unique references signal_engine.signal_decision(decision_id),
    prior_cycle_id uuid not null,
    state text not null,
    minimum_wait_sessions integer not null check (minimum_wait_sessions >= 0),
    minimum_spacing_sessions integer not null check (minimum_spacing_sessions >= 0),
    expires_after_sessions integer not null check (expires_after_sessions > 0),
    created_at timestamptz not null
);

create table if not exists signal_engine.reentry_stage (
    watch_id uuid not null references signal_engine.reentry_watch(watch_id),
    stage_no integer not null,
    target_fraction numeric(9,6) not null check (target_fraction > 0 and target_fraction <= 1),
    status text not null,
    eligible_at timestamptz null,
    executed_cycle_id uuid null,
    primary key (watch_id, stage_no)
);

create or replace function signal_engine.prevent_immutable_change()
returns trigger language plpgsql as $$
begin
  raise exception 'immutable evidence/decision rows cannot be updated or deleted';
end;
$$;

drop trigger if exists evidence_snapshot_immutable on signal_engine.evidence_snapshot;
create trigger evidence_snapshot_immutable
before update or delete on signal_engine.evidence_snapshot
for each row execute function signal_engine.prevent_immutable_change();
