/**
 * The v1 release matrix, version 1. Fixed by #14.
 *
 * This is the SAME data the SQL function reads — seeded by
 * migrations/custom/0002_seed_release_matrix.sql. It lives here as well
 * because the evaluation surface renders dimmed cells from it (#23), and the
 * screen and the policy must not be able to disagree.
 *
 * A rule change is a NEW VERSION, never an update. Without the version
 * history a past release cannot be reconstructed for a protest.
 */
export const MATRIX_VERSION = 1

export type ReleaseLevel =
  | 'none' | 'invited' | 'acknowledged' | 'submitted'
  | 'open' | 'evaluating' | 'finalist' | 'awarded'

export type DisclosureClass =
  | 'vendor_identity' | 'participation_signal' | 'scenario_quantity'
  | 'answer_text' | 'exception_text' | 'price_quote' | 'derived_cost'
  | 'vault_document' | 'own_scoring'

const ORDER: ReleaseLevel[] = [
  'none', 'invited', 'acknowledged', 'submitted', 'open', 'evaluating', 'finalist', 'awarded',
]

/** The level at which each class first opens. Anything below it is withheld. */
const OPENS_AT: Record<DisclosureClass, ReleaseLevel> = {
  // The retailer's pre-bid signal — non-content, and what #12 actually promised them.
  vendor_identity: 'invited',
  participation_signal: 'invited',

  // Exact quantities sit behind the acknowledgement gate (#14 decision 4).
  scenario_quantity: 'acknowledged',

  // Sealed until the deadline. `open` is the moment the whole field opens at
  // once — the reason bid shopping is structurally impossible (#14 decision 2).
  answer_text: 'open',
  exception_text: 'open',
  vault_document: 'open',
  price_quote: 'open',
  derived_cost: 'open',

  // A vendor's own scoring, released to them at award (#14 decision 3).
  own_scoring: 'awarded',
}

export function isReleased(cls: DisclosureClass, level: ReleaseLevel): boolean {
  return ORDER.indexOf(level) >= ORDER.indexOf(OPENS_AT[cls])
}

/**
 * TWO-ENVELOPE, deferred not declined (#14 decision 2).
 *
 * Moving `price_quote` and `derived_cost` from 'open' to a level reached only
 * after scoring locks is a one-row change here plus an irreversible lock
 * transition. That is the point of choosing a matrix over inline policies.
 */
