/**
 * Export control and compliance.
 *
 * This file exists because of a single regulatory fact that generic CRMs
 * cannot express: **country of incorporation is not a valid key.**
 *
 * US export controls on advanced computing apply an *ultimate parent* test.
 * A licence is required to export covered items to entities headquartered in
 * — or whose ultimate parent is headquartered in — certain country groups,
 * **even when the entity itself sits elsewhere**. A Singapore-registered
 * subsidiary of a restricted parent is restricted. The tiered "AI Diffusion
 * Rule" that briefly governed this was rescinded in May 2025, but the
 * headquarters test predates it, survived it, and was reaffirmed in
 * subsequent guidance. Nothing comprehensive replaced the tiers, so what
 * remains is: the parent test, named-entity authorisations, and case-by-case
 * licensing.
 *
 * Two consequences shape the schema:
 *
 * 1. Compliance is a **predicate on the allocation edge**, evaluated when a
 *    specific buyer is matched to specific capacity in a specific
 *    jurisdiction — not a boolean on an account. Two suppliers in the same
 *    country can have opposite legal status.
 *
 * 2. The decision must be **recorded and auditable**, and re-evaluated when
 *    capacity is resold or a workload migrates. A decision made at signature
 *    does not remain true.
 *
 * PIG records and surfaces these facts. It is not legal advice and does not
 * make the determination for you: `decision` is set by a human or by an
 * explicit rule version, and always carries its evidence.
 */
import {
  boolean,
  index,
  jsonb,
  pgTable,
  text,
  timestamp,
  uuid,
} from 'drizzle-orm/pg-core';
import { accounts } from './crm';
import { users } from './identity';
import { allocations } from './allocations';

/**
 * A named authorisation permitting business that would otherwise need a
 * licence. These expire — some on the order of months — and an expired
 * authorisation silently converts lawful business into unlawful business,
 * so `expiresAt` is indexed and alerted on.
 */
export const exportAuthorizations = pgTable(
  'export_authorizations',
  {
    id: uuid('id').primaryKey().defaultRandom(),
    accountId: uuid('account_id')
      .notNull()
      .references(() => accounts.id, { onDelete: 'cascade' }),

    /**
     * `none`          No authorisation on file
     * `licence`       An individually issued export licence
     * `listed_entity` Named on a published authorisation list
     * `dc_veu`        Validated end user / datacentre authorisation
     * `case_by_case`  Reviewed individually, typically with a volume cap
     */
    authorizationType: text('authorization_type').notNull().default('none'),
    reference: text('reference'),
    scopeNotes: text('scope_notes'),

    issuedAt: timestamp('issued_at', { withTimezone: true }),
    expiresAt: timestamp('expires_at', { withTimezone: true }),

    /** Where this was verified from. Never assert an authorisation unsourced. */
    evidenceUrl: text('evidence_url'),
    verifiedByUserId: uuid('verified_by_user_id').references(() => users.id, {
      onDelete: 'set null',
    }),
    verifiedAt: timestamp('verified_at', { withTimezone: true }),

    /**
     * Set when the underlying rules are in flux for this counterparty, which
     * they frequently are. Drives periodic re-verification rather than
     * trusting a stale check.
     */
    volatile: boolean('volatile').notNull().default(false),

    createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
  },
  (t) => [
    index('export_authorizations_account_idx').on(t.accountId),
    index('export_authorizations_expiry_idx').on(t.expiresAt),
  ],
);

/**
 * The blocking predicate, evaluated when capacity is matched to a buyer.
 *
 * Stored rather than computed on the fly so that the reasoning behind a
 * decision survives the rule changing, the staff changing, and the deal being
 * audited two years later. `ruleVersion` records which version of the check
 * produced this outcome, so a rule change can be replayed across open
 * allocations rather than quietly changing history.
 */
export const complianceDecisions = pgTable(
  'compliance_decisions',
  {
    id: uuid('id').primaryKey().defaultRandom(),

    allocationId: uuid('allocation_id').references(() => allocations.id, {
      onDelete: 'cascade',
    }),
    /** The buying party. */
    accountId: uuid('account_id')
      .notNull()
      .references(() => accounts.id, { onDelete: 'cascade' }),

    /**
     * The three coordinates the determination actually turns on. Recorded as
     * they were at decision time, because all three can change afterwards.
     */
    beneficialOwnerName: text('beneficial_owner_name'),
    ultimateParentCountry: text('ultimate_parent_country'),
    physicalJurisdiction: text('physical_jurisdiction'),
    endUse: text('end_use'),

    /** `allow` | `block` | `needs_review` — blocking, never advisory. */
    decision: text('decision').notNull().default('needs_review'),
    rationale: text('rationale'),
    ruleVersion: text('rule_version'),

    decidedByUserId: uuid('decided_by_user_id').references(() => users.id, {
      onDelete: 'set null',
    }),
    decidedAt: timestamp('decided_at', { withTimezone: true }),

    /**
     * What would invalidate this: `resale`, `migration`, `ownership_change`,
     * `authorization_expiry`. A decision is only as good as its assumptions.
     */
    reEvaluationTriggers: jsonb('re_evaluation_triggers')
      .$type<string[]>()
      .notNull()
      .default([]),
    supersededAt: timestamp('superseded_at', { withTimezone: true }),

    createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
  },
  (t) => [
    index('compliance_decisions_allocation_idx').on(t.allocationId),
    index('compliance_decisions_account_idx').on(t.accountId),
    index('compliance_decisions_decision_idx').on(t.decision),
  ],
);

/**
 * Compliance evidence about a counterparty — SOC 2, ISO 27001, ISO 42001,
 * penetration tests, insurance certificates.
 *
 * Never a boolean, for two reasons observed repeatedly in this market.
 *
 * First, **scope**: a SOC 2 report may cover only some of a provider's
 * products, and may carve out the colocation provider as a subservice
 * organisation — meaning the physical security the report appears to attest
 * is explicitly not attested.
 *
 * Second, **"certified" versus "aligned with"**: marketing routinely places
 * "aligns its security programme to SOC 2 and ISO 27001" beside genuine
 * certifications. The distinction decides enterprise procurement, so it gets
 * its own column rather than being lost in prose.
 */
export const complianceArtifacts = pgTable(
  'compliance_artifacts',
  {
    id: uuid('id').primaryKey().defaultRandom(),
    accountId: uuid('account_id')
      .notNull()
      .references(() => accounts.id, { onDelete: 'cascade' }),

    /** e.g. `soc2`, `iso27001`, `iso42001`, `pentest`, `cyber_insurance`. */
    claim: text('claim').notNull(),
    /** Which products or facilities the claim actually covers. */
    scope: text('scope'),

    /** True certification versus self-declared alignment. The whole point. */
    isCertified: boolean('is_certified').notNull().default(false),

    /** SOC 2 specifics, null for other artefact types. */
    soc2Type: text('soc2_type'),
    observationWindowStart: timestamp('observation_window_start', { withTimezone: true }),
    observationWindowEnd: timestamp('observation_window_end', { withTimezone: true }),
    auditFirm: text('audit_firm'),
    /**
     * Whether the report carves out subservice organisations. A carve-out
     * means the colocation provider's controls are NOT covered.
     */
    carveOutMethod: text('carve_out_method'),
    productsInScope: jsonb('products_in_scope').$type<string[]>().notNull().default([]),

    evidenceUrl: text('evidence_url'),
    verifiedByUserId: uuid('verified_by_user_id').references(() => users.id, {
      onDelete: 'set null',
    }),
    verifiedAt: timestamp('verified_at', { withTimezone: true }),
    expiresAt: timestamp('expires_at', { withTimezone: true }),

    createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
  },
  (t) => [
    index('compliance_artifacts_account_idx').on(t.accountId),
    index('compliance_artifacts_claim_idx').on(t.claim),
    index('compliance_artifacts_expiry_idx').on(t.expiresAt),
  ],
);

export type ExportAuthorization = typeof exportAuthorizations.$inferSelect;
export type ComplianceDecision = typeof complianceDecisions.$inferSelect;
export type ComplianceArtifact = typeof complianceArtifacts.$inferSelect;

export type ComplianceMatchDecision = Pick<
  ComplianceDecision,
  'decision' | 'supersededAt'
>;

/**
 * Whether a recorded export-control predicate permits a prospective match.
 *
 * `undefined` means no buyer-specific evaluation was requested, as in a generic
 * inventory search. Once evaluation is requested, absence, review, block and a
 * superseded allow all fail closed. Security classification is not a substitute
 * for an export-control determination.
 */
export function complianceDecisionAllowsMatch(
  decision: ComplianceMatchDecision | null | undefined,
): boolean {
  if (decision === undefined) return true;
  return decision?.decision === 'allow' && decision.supersededAt === null;
}
