/**
 * Export control, ownership, and the evidence behind both.
 *
 * `schema/compliance.ts` spends its opening page on one regulatory fact —
 * country of incorporation is not a valid key, because the licence test reaches
 * through the corporate tree to the ULTIMATE PARENT — and the demo book used to
 * exercise none of it: no ownership on any account, no decision anywhere, one
 * authorisation and one artefact on the same account. A distinctive idea that
 * renders as an empty panel teaches nobody anything.
 *
 * So this file seeds the argument rather than a sample row:
 *
 *   an ordinary US counterparty that clears cleanly, on a live allocation;
 *   a UK counterparty whose ultimate parent moved to Hong Kong between the
 *     proposal and the hold, which is the case the doctrine exists for and the
 *     only one on the book that needs a person to look at it;
 *   an enquiry closed at qualification, before any allocation existed, because
 *     the Singapore incorporation did not change where the parent sits;
 *   a sovereign buyer operating under a named licence that expires this
 *     quarter, and a research institute whose case-by-case authorisation has
 *     ALREADY LAPSED and which nobody has noticed.
 *
 * Two boundaries hold throughout.
 *
 * **Only invented, prefixed accounts carry any of this.** The supply side of
 * this book is real, named companies. Fabricating a corporate parent, a licence
 * or a lapsed certification against a real business is worse than fabricating a
 * contract value: it is an allegation. Real accounts are left exactly as the
 * base seed found them.
 *
 * **Nothing here is a legal determination.** `decision` is set by a named
 * person under a stated `ruleVersion`, with the three coordinates it turned on
 * recorded beside it, which is what makes it auditable two years later.
 */
import { and, eq, inArray } from 'drizzle-orm';
import {
  accounts,
  allocations,
  capacityRequests,
  complianceArtifacts,
  complianceDecisions,
  contacts,
  demandDeals,
  exportAuthorizations,
  users,
} from '../../schema/index';
import type { DemoContext } from './index';

/**
 * The revision of the check every determination below was taken under.
 *
 * It doubles as the idempotency key: re-running the seed must not record a
 * second determination for the same counterparty under the same rules, which
 * is also the real-world rule — a decision is superseded, never duplicated.
 */
const RULE_VERSION = 'hq-test/2026.02';

/**
 * Counted the way the calendar slice counts: `total` is what the book asks for,
 * `added` what this run actually wrote. A summary that reported only the new
 * rows would print zero on every re-run, which reads as a failure rather than
 * as idempotency working.
 */
export interface ComplianceSummary {
  authorizations: { total: number; added: number };
  artifacts: { total: number; added: number };
  decisions: { total: number; added: number };
}

/**
 * Ownership for the invented demand book.
 *
 * `ultimateParentName` is set even where the counterparty is its own ultimate
 * parent: "verified, nothing above it" and "nobody has looked" are different
 * states, and only the first is safe to sell against. Quillon is deliberately
 * left blank — it is still at qualification, and a CRM that quietly fills in an
 * unverified ownership chain is worse than one that admits the gap.
 */
function ownershipBook(prefix: string) {
  return [
    {
      account: `${prefix}Halcyon Research`,
      jurisdiction: 'Delaware, United States',
      ultimateParentName: `${prefix}Halcyon Research, Inc.`,
      ultimateParentCountry: 'United States',
      verifiedDaysAgo: 58,
    },
    {
      account: `${prefix}Verity Health AI`,
      jurisdiction: 'Germany',
      ultimateParentName: `${prefix}Verity Health AG`,
      ultimateParentCountry: 'Germany',
      verifiedDaysAgo: 96,
    },
    {
      account: `${prefix}Northwind Robotics`,
      jurisdiction: 'Delaware, United States',
      ultimateParentName: `${prefix}Northwind Robotics, Inc.`,
      ultimateParentCountry: 'United States',
      verifiedDaysAgo: 140,
    },
    {
      // The account the doctrine exists for. Incorporated in England, and on
      // `country` alone indistinguishable from any other British startup — but
      // a Series A extension moved voting control to a Hong Kong holding
      // company, and the headquarters test follows the parent, not the paper.
      account: `${prefix}Tessellate Labs`,
      jurisdiction: 'England & Wales',
      ultimateParentName: `${prefix}Tessellate Holdings (HK) Limited`,
      ultimateParentCountry: 'Hong Kong SAR, China',
      verifiedDaysAgo: 6,
    },
    {
      // Verified two quarters before a 24-month commitment went to legal, which
      // is exactly the staleness the column exists to make visible.
      account: `${prefix}Aurelian Systems`,
      jurisdiction: 'Delaware, United States',
      ultimateParentName: `${prefix}Aurelian Industries, Inc.`,
      ultimateParentCountry: 'United States',
      verifiedDaysAgo: 210,
    },
  ];
}

/**
 * Counterparties that exist in this book because of compliance rather than in
 * spite of it, and the two segments nothing else seeds.
 *
 * A sovereign programme and a research institute are not decoration: they buy
 * differently — procurement measured in quarters, named end uses, authorisation
 * conditions written into the order form — and they are where export control
 * stops being theoretical. The third is the enquiry that never became a deal.
 */
function complianceAccounts(prefix: string) {
  return [
    {
      name: `${prefix}Meridian Sovereign Cloud`,
      segment: 'sovereign' as const,
      country: 'United Arab Emirates',
      region: 'Abu Dhabi',
      jurisdiction: 'United Arab Emirates',
      ultimateParentName: `${prefix}Meridian National Holdings PJSC`,
      ultimateParentCountry: 'United Arab Emirates',
      verifiedDaysAgo: 33,
      lastActivityDaysAgo: 4,
      description:
        'Fictional national compute programme, for demonstration only. Buys under a ' +
        'named export licence with conditions on end use and physical access.',
      contact: { name: 'Nadia Al-Farsi', title: 'Head of Procurement' },
    },
    {
      name: `${prefix}Calderwood Institute for Computational Science`,
      segment: 'research_institution' as const,
      country: 'United Kingdom',
      region: 'Cambridge',
      jurisdiction: 'England & Wales',
      ultimateParentName: `${prefix}University of Calderwood`,
      ultimateParentCountry: 'United Kingdom',
      verifiedDaysAgo: 260,
      lastActivityDaysAgo: 31,
      description:
        'Fictional research institute, for demonstration only. Mixed-nationality ' +
        'research staff, so end use and access are conditions rather than notes.',
      contact: { name: 'Dr Rhiannon Vale', title: 'Director of Research Computing' },
    },
    {
      // No deal, no contact, no allocation — and that is the record. An enquiry
      // screened out at qualification still has to leave evidence behind, or
      // the next seller to meet them starts the same conversation from nothing.
      name: `${prefix}Sable Ridge Analytics`,
      segment: 'enterprise' as const,
      country: 'Singapore',
      region: 'Singapore',
      jurisdiction: 'Singapore',
      ultimateParentName: `${prefix}Sable Ridge Group Holdings`,
      ultimateParentCountry: 'China',
      verifiedDaysAgo: 12,
      lastActivityDaysAgo: 12,
      description:
        'Fictional company, for demonstration only. Enquiry closed at qualification ' +
        'on the ultimate-parent test.',
      contact: null,
    },
  ];
}

export async function seedCompliance(context: DemoContext): Promise<ComplianceSummary> {
  const { db, prefix, at, quarterAt } = context;

  /**
   * Near-term, but never past the quarter the calendar opens on.
   *
   * A plain `at(24)` spends a quarter of the year pointing into the NEXT
   * quarter, and the export-authorisation lane is then empty for whoever opens
   * the page today — which is precisely how the one seeded authorisation
   * managed to be invisible for half of every quarter.
   */
  const soonInThisQuarter = (days: number): Date => {
    const target = at(days);
    const lastCall = quarterAt(0, 0.93);
    return target < lastCall ? target : lastCall;
  };

  /** Whoever signs the demo book's determinations. A decision needs a decider. */
  const [decider] = await db.select({ id: users.id }).from(users).orderBy(users.createdAt).limit(1);
  const decidedByUserId = decider?.id ?? null;

  const accountIdByName = async (name: string): Promise<string | null> => {
    const [row] = await db
      .select({ id: accounts.id })
      .from(accounts)
      .where(eq(accounts.name, name))
      .limit(1);
    return row?.id ?? null;
  };

  // ------------------------------------------------------------- ownership

  for (const owner of ownershipBook(prefix)) {
    await db
      .update(accounts)
      .set({
        jurisdiction: owner.jurisdiction,
        ultimateParentName: owner.ultimateParentName,
        ultimateParentCountry: owner.ultimateParentCountry,
        ownershipVerifiedAt: at(-owner.verifiedDaysAgo),
      })
      .where(eq(accounts.name, owner.account));
  }

  for (const candidate of complianceAccounts(prefix)) {
    const existingId = await accountIdByName(candidate.name);
    const [inserted] = existingId
      ? []
      : await db
          .insert(accounts)
          .values({
            name: candidate.name,
            side: 'demand',
            customerSegment: candidate.segment,
            country: candidate.country,
            region: candidate.region,
            jurisdiction: candidate.jurisdiction,
            ultimateParentName: candidate.ultimateParentName,
            ultimateParentCountry: candidate.ultimateParentCountry,
            ownershipVerifiedAt: at(-candidate.verifiedDaysAgo),
            description: candidate.description,
            source: 'seed',
            confidence: 'confirmed',
            lastActivityAt: at(-candidate.lastActivityDaysAgo),
          })
          .returning({ id: accounts.id });

    const accountId = existingId ?? inserted?.id;
    if (!accountId || !candidate.contact) continue;

    const [existingContact] = await db
      .select({ id: contacts.id })
      .from(contacts)
      .where(
        and(eq(contacts.accountId, accountId), eq(contacts.fullName, candidate.contact.name)),
      )
      .limit(1);
    if (existingContact) continue;

    await db.insert(contacts).values({
      accountId,
      fullName: candidate.contact.name,
      title: candidate.contact.title,
      affiliation: 'staff',
      isDecisionMaker: true,
      confidence: 'confirmed',
      source: 'seed',
      email: null,
    });
  }

  // ------------------------------------------------- jurisdiction constraints

  /*
   * An excluded jurisdiction is a commercial constraint, not a preference, and
   * both of these narrow the inventory that can lawfully or contractually
   * serve the deal.
   *
   * Verity's is data protection rather than export control: a German health
   * customer excluding US-jurisdiction operators is refusing the reach of the
   * CLOUD Act over its processor, which no `allowedRegions` list can express —
   * a US-owned operator running an EU region is still a US-jurisdiction
   * operator. It is also what forces the deal onto the Finnish block.
   *
   * Halcyon's is the frontier-lab posture on model weights, which is about
   * where the machines and their operators sit rather than where the data does.
   */
  const exclusionBook = [
    { account: `${prefix}Verity Health AI`, jurisdictions: ['United States'] },
    {
      account: `${prefix}Halcyon Research`,
      jurisdictions: ['China', 'Hong Kong SAR, China', 'Russia'],
    },
  ];

  for (const exclusion of exclusionBook) {
    const accountId = await accountIdByName(exclusion.account);
    if (!accountId) continue;
    const dealIds = (
      await db
        .select({ id: demandDeals.id })
        .from(demandDeals)
        .where(eq(demandDeals.accountId, accountId))
    ).map((deal) => deal.id);
    if (dealIds.length === 0) continue;
    await db
      .update(capacityRequests)
      .set({ excludedJurisdictions: exclusion.jurisdictions })
      .where(inArray(capacityRequests.demandDealId, dealIds));
  }

  // -------------------------------------------------------- authorisations

  const verityId = await accountIdByName(`${prefix}Verity Health AI`);
  const meridianId = await accountIdByName(`${prefix}Meridian Sovereign Cloud`);
  const calderwoodId = await accountIdByName(`${prefix}Calderwood Institute for Computational Science`);
  const halcyonId = await accountIdByName(`${prefix}Halcyon Research`);
  const tessellateId = await accountIdByName(`${prefix}Tessellate Labs`);
  const sableRidgeId = await accountIdByName(`${prefix}Sable Ridge Analytics`);

  const authorizationBook = [
    {
      accountId: verityId,
      authorizationType: 'dc_veu',
      reference: `${prefix}DC-VEU-2026-0417`,
      scopeNotes:
        'Illustrative demo record. Covers EU-resident training workloads only; ' +
        'inference in other regions is out of scope.',
      issuedAt: at(-320),
      // A month out, but never past the quarter the calendar opens on — the
      // previous fixed +45 days spent half of every quarter out of view.
      expiresAt: soonInThisQuarter(34),
      evidenceUrl: 'https://example.invalid/demo-authorisation',
      verifiedAt: at(-40),
      // Rules in flux for this counterparty: re-verify, do not trust the date.
      volatile: true,
    },
    {
      // The sovereign programme's licence to exist as a customer at all. Ninety
      // per cent through the quarter or three weeks out, whichever comes first:
      // a renewal this close is the most expensive thing on the calendar to
      // miss, because everything sold under it stops being lawful on the day.
      accountId: meridianId,
      authorizationType: 'licence',
      reference: `${prefix}EXP-L-2026-08841`,
      scopeNotes:
        'Illustrative demo record. Named facility only, capped at 4,096 covered ' +
        'accelerators, conditioned on no foreign-national physical access and on ' +
        'quarterly end-use reporting. Resale outside the named facility voids it.',
      issuedAt: at(-155),
      expiresAt: soonInThisQuarter(24),
      evidenceUrl: 'https://example.invalid/demo-licence',
      verifiedAt: at(-21),
      volatile: true,
    },
    {
      // Lapsed, and nobody has noticed — which is the entire argument for
      // indexing and alerting on this column. A fixed offset rather than a
      // quarter fraction because "already expired" is a claim about today, not
      // about the quarter; it lands in the current quarter most of the year.
      accountId: calderwoodId,
      authorizationType: 'case_by_case',
      reference: `${prefix}CBC-2025-1179`,
      scopeNotes:
        'Illustrative demo record. Capped at 5,000 GPU-hours per quarter for one ' +
        'named research programme, with no deemed-export cover for non-UK staff. ' +
        'EXPIRED: the successor application is still with counsel.',
      issuedAt: at(-400),
      expiresAt: at(-26),
      evidenceUrl: 'https://example.invalid/demo-case-by-case',
      verifiedAt: at(-400),
      volatile: false,
    },
  ];

  let authorizationsPlanned = 0;
  let authorizationsAdded = 0;
  for (const authorization of authorizationBook) {
    if (!authorization.accountId) continue;
    authorizationsPlanned += 1;
    const [existing] = await db
      .select({ id: exportAuthorizations.id })
      .from(exportAuthorizations)
      .where(eq(exportAuthorizations.reference, authorization.reference))
      .limit(1);
    if (existing) continue;
    await db.insert(exportAuthorizations).values({
      accountId: authorization.accountId,
      authorizationType: authorization.authorizationType,
      reference: authorization.reference,
      scopeNotes: authorization.scopeNotes,
      issuedAt: authorization.issuedAt,
      expiresAt: authorization.expiresAt,
      evidenceUrl: authorization.evidenceUrl,
      verifiedByUserId: decidedByUserId,
      verifiedAt: authorization.verifiedAt,
      volatile: authorization.volatile,
    });
    authorizationsAdded += 1;
  }

  // ------------------------------------------------------------- artefacts

  const artifactBook = [
    {
      accountId: verityId,
      claim: 'soc2',
      scope: `${prefix}EU training platform`,
      // A true certification, not an alignment claim — the distinction the
      // column exists for, and the one procurement actually gates on.
      isCertified: true,
      soc2Type: 'type_ii',
      observationWindowStart: at(-365),
      observationWindowEnd: at(-10),
      auditFirm: 'Demo Assurance LLP',
      // Carved out, so the colocation provider's physical controls are NOT
      // attested by this report however it reads in the covering letter.
      carveOutMethod: 'carve_out',
      productsInScope: ['training', 'managed inference'],
      evidenceUrl: 'https://example.invalid/demo-soc2',
      // Inside the current quarter and ahead of the deal it gates: a report
      // that lapses mid-procurement stalls the procurement.
      expiresAt: quarterAt(0, 0.72),
    },
    {
      accountId: meridianId,
      claim: 'iso27001',
      scope: `${prefix}Sovereign region — dedicated tenancy`,
      isCertified: true,
      // No observation window: an ISO certificate has a validity period rather
      // than an audited period, and inventing one would misdescribe it.
      soc2Type: null,
      observationWindowStart: null,
      observationWindowEnd: null,
      auditFirm: 'Demo Certification Bureau',
      carveOutMethod: null,
      productsInScope: ['dedicated capacity', 'managed inference'],
      evidenceUrl: 'https://example.invalid/demo-iso27001',
      // In this quarter but behind the licence, so the two deadlines on this
      // account read as a sequence rather than as one crowded week.
      expiresAt: soonInThisQuarter(45),
    },
    {
      // Not a certification at all, and flagged as such. A penetration test is
      // routinely presented alongside certifications as though it were one,
      // and its scope is usually the narrower half of the story.
      accountId: calderwoodId,
      claim: 'pentest',
      scope: `${prefix}Research computing — external perimeter only`,
      isCertified: false,
      soc2Type: null,
      observationWindowStart: null,
      observationWindowEnd: null,
      auditFirm: 'Demo Offensive Security Ltd',
      carveOutMethod: null,
      productsInScope: ['research computing'],
      evidenceUrl: 'https://example.invalid/demo-pentest',
      // Next quarter, so the artefact lane does not empty the moment this one
      // closes. An annual test is stale before it is expired.
      expiresAt: quarterAt(1, 0.25),
    },
  ];

  let artifactsPlanned = 0;
  let artifactsAdded = 0;
  for (const artifact of artifactBook) {
    if (!artifact.accountId) continue;
    artifactsPlanned += 1;
    const [existing] = await db
      .select({ id: complianceArtifacts.id })
      .from(complianceArtifacts)
      .where(
        and(
          eq(complianceArtifacts.accountId, artifact.accountId),
          eq(complianceArtifacts.claim, artifact.claim),
        ),
      )
      .limit(1);
    if (existing) continue;
    await db.insert(complianceArtifacts).values({
      accountId: artifact.accountId,
      claim: artifact.claim,
      scope: artifact.scope,
      isCertified: artifact.isCertified,
      soc2Type: artifact.soc2Type,
      observationWindowStart: artifact.observationWindowStart,
      observationWindowEnd: artifact.observationWindowEnd,
      auditFirm: artifact.auditFirm,
      carveOutMethod: artifact.carveOutMethod,
      productsInScope: artifact.productsInScope,
      evidenceUrl: artifact.evidenceUrl,
      verifiedByUserId: decidedByUserId,
      verifiedAt: at(-12),
      expiresAt: artifact.expiresAt,
    });
    artifactsAdded += 1;
  }

  // ------------------------------------------------------------- decisions

  /**
   * The allocation a determination was made against, where there is one.
   *
   * The predicate is on the allocation edge — a buyer matched to specific
   * capacity in a specific jurisdiction — so a decision that points at nothing
   * is a decision about a counterparty in the abstract. Both exist here: two of
   * the three below hang off a real allocation, and the third is an enquiry
   * refused before any capacity was ever reserved.
   */
  const allocationForAccount = async (accountId: string): Promise<string | null> => {
    const [row] = await db
      .select({ id: allocations.id })
      .from(allocations)
      .innerJoin(demandDeals, eq(demandDeals.id, allocations.demandDealId))
      .where(eq(demandDeals.accountId, accountId))
      .limit(1);
    return row?.id ?? null;
  };

  const decisionBook = [
    {
      accountId: halcyonId,
      withAllocation: true,
      beneficialOwnerName: `${prefix}Halcyon Research, Inc.`,
      ultimateParentCountry: 'United States',
      physicalJurisdiction: 'United States',
      endUse: 'Frontier model pre-training on the customer’s own corpus.',
      decision: 'allow',
      rationale:
        'Counterparty, ultimate parent and physical capacity are all US. No licence ' +
        'requirement arises, and the site is one we hold under our own MSA rather ' +
        'than resold. Ownership re-verified against the cap table, not the website.',
      decidedDaysAgo: 58,
      // Even a clean allow is conditional. Reselling the block or the parent
      // changing are the two events that would make this answer wrong without
      // anything about the deal appearing to change.
      reEvaluationTriggers: ['resale', 'ownership_change'],
    },
    {
      accountId: tessellateId,
      withAllocation: true,
      beneficialOwnerName: `${prefix}Tessellate Holdings (HK) Limited`,
      ultimateParentCountry: 'Hong Kong SAR, China',
      physicalJurisdiction: 'United States',
      endUse: 'Burst inference for a consumer product. End customer not disclosed.',
      decision: 'needs_review',
      rationale:
        'The Series A extension moved 62% of voting rights to a Hong Kong holding ' +
        'company, so the headquarters test reaches through the English entity and ' +
        'the counterparty’s own country does not settle the question. Two things ' +
        'are open: whether a licence is required for the covered items at this ' +
        'scale, and whether a community-pool tenancy can evidence the physical ' +
        'control any licence would condition on. The hold stands; it does not ' +
        'convert until counsel answers both.',
      decidedDaysAgo: 5,
      reEvaluationTriggers: ['ownership_change', 'migration', 'authorization_expiry'],
    },
    {
      accountId: sableRidgeId,
      withAllocation: false,
      beneficialOwnerName: `${prefix}Sable Ridge Group Holdings`,
      ultimateParentCountry: 'China',
      physicalJurisdiction: 'United States',
      endUse: 'Undisclosed. Described only as "training for a customer of ours".',
      decision: 'block',
      rationale:
        'Singapore incorporation, ultimate parent headquartered in a jurisdiction ' +
        'for which covered advanced-computing items require a licence. The place of ' +
        'incorporation does not change that analysis. No licence or listed-entity ' +
        'authorisation on file, and the end use was not disclosed on request, so the ' +
        'enquiry is closed rather than progressed. Reopen only against a granted ' +
        'licence naming this entity.',
      decidedDaysAgo: 12,
      reEvaluationTriggers: ['ownership_change'],
    },
  ];

  let decisionsPlanned = 0;
  let decisionsAdded = 0;
  for (const determination of decisionBook) {
    if (!determination.accountId) continue;
    decisionsPlanned += 1;
    const [existing] = await db
      .select({ id: complianceDecisions.id })
      .from(complianceDecisions)
      .where(
        and(
          eq(complianceDecisions.accountId, determination.accountId),
          eq(complianceDecisions.ruleVersion, RULE_VERSION),
        ),
      )
      .limit(1);
    if (existing) continue;

    await db.insert(complianceDecisions).values({
      accountId: determination.accountId,
      allocationId: determination.withAllocation
        ? await allocationForAccount(determination.accountId)
        : null,
      beneficialOwnerName: determination.beneficialOwnerName,
      ultimateParentCountry: determination.ultimateParentCountry,
      physicalJurisdiction: determination.physicalJurisdiction,
      endUse: determination.endUse,
      decision: determination.decision,
      rationale: determination.rationale,
      ruleVersion: RULE_VERSION,
      decidedByUserId,
      decidedAt: at(-determination.decidedDaysAgo),
      reEvaluationTriggers: determination.reEvaluationTriggers,
    });
    decisionsAdded += 1;
  }

  return {
    authorizations: { total: authorizationsPlanned, added: authorizationsAdded },
    artifacts: { total: artifactsPlanned, added: artifactsAdded },
    decisions: { total: decisionsPlanned, added: decisionsAdded },
  };
}
