import { pgTable, uuid, text, timestamp, jsonb, boolean } from "drizzle-orm/pg-core";
import { sql } from "drizzle-orm";

// Shape of the multi_entry_summary jsonb (ADR-0004). Co-located with the column
// so the schema is self-contained; the detection logic in
// src/lib/bulkUpload/multiEntry.ts imports these.
export interface MultiEntryEntry {
  raw: string;
  description: string;
}
export interface MultiEntryColumn {
  field: string;
  header: string;
  entries: MultiEntryEntry[];
}
export interface MultiEntrySample {
  address: string;
  count: number;
  columns: MultiEntryColumn[];
}
export interface MultiEntrySummary {
  multiValuedFields: string[];
  countDistribution: Record<string, number>;
  largestCount: number;
  // Step 1 (verify) sample: the largest-count row when multi-entry, else the
  // first classified row. `null` ⇒ nothing to verify.
  sample: MultiEntrySample | null;
  // Step 2 (order): one sample per distinct entry-count ≥ 2 present in the file,
  // keyed by count. Each count needs its OWN confirmed permutation — a smaller
  // count's ordering can't be derived from a larger one (ADR-0004, amended
  // 2026-06-05). Absent on uploads detected before that amendment.
  samplesByCount?: Record<string, MultiEntrySample>;
}

// User-confirmed building-part ordering (ADR-0004, amended 2026-06-05). Keyed by
// entry-count: a permutation is captured for EVERY distinct count ≥ 2 in the
// file (the v2 fact layer can't derive one count's order from another).
// permutations[count][k] = the 0-based file position holding building part k,
// where 0 = Main building, 1..N-1 = Extension 1..N-1.
// e.g. { "2": [1, 0] } => for 2-part rows the main building is file position 1.
export interface MultiEntryOrdering {
  permutations: Record<string, number[]>;
  // True once EVERY detected count ≥ 2 has a permutation; gates Finalise when the
  // upload is multi-entry.
  confirmed: boolean;
}

export const bulkAddressUploads = pgTable("bulk_address_uploads", {
  id: uuid("id").defaultRandom().primaryKey(),
  portfolioId: text("portfolio_id").notNull(),
  userId: text("user_id").notNull(),
  s3Bucket: text("s3_bucket").notNull(),
  s3Key: text("s3_key").notNull(),
  filename: text("filename").notNull(),
  status: text("status").notNull().default("ready_for_processing"),
  sourceHeaders: text("source_headers").array().notNull().default(sql`'{}'`),
  columnMapping: jsonb("column_mapping").$type<Record<string, string>>(),
  multiEntrySummary: jsonb("multi_entry_summary").$type<MultiEntrySummary>(),
  multiEntryOrdering: jsonb("multi_entry_ordering").$type<MultiEntryOrdering>(),
  verifyAck: boolean("verify_ack").notNull().default(false),
  taskId: uuid("task_id"),
  combinedOutputS3Uri: text("combined_output_s3_uri"),
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
  updatedAt: timestamp("updated_at", { withTimezone: true })
    .notNull()
    .defaultNow()
    .$onUpdate(() => new Date()),
});
