import { sql, relations } from "drizzle-orm";
import { pgTable, text, varchar, timestamp, boolean, numeric, integer, pgEnum, index, foreignKey, unique } from "drizzle-orm/pg-core";
import { createInsertSchema } from "drizzle-zod";
import { z } from "zod";

// Enums
export const userRoleEnum = pgEnum("user_role", ["admin", "risk_manager", "auditor"]);
export const riskLevelEnum = pgEnum("risk_level", ["LOW", "MEDIUM", "HIGH", "CRITICAL"]);
export const threatTypeEnum = pgEnum("threat_type", ["INTERNAL_XFER", "MAKER_ONLY", "BULK_ACCESS", "AFTER_HOURS", "GEO_ANOMALY", "VELOCITY_BREACH"]);

// Users table with RBAC
export const users = pgTable("users", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  username: text("username").notNull().unique(),
  password: text("password").notNull(),
  role: userRoleEnum("role").notNull().default("auditor"),
  secondaryRoles: text("secondary_roles").array().notNull().default(sql`ARRAY[]::text[]`),
  fullName: text("full_name").notNull(),
  department: text("department"),
  isActive: boolean("is_active").notNull().default(true),
  lastLogin: timestamp("last_login"),
  // OIDC subject bound on first SSO login (trust-on-first-use → pin). Null until a user's
  // first SSO login binds it; thereafter the verified `sub` must match this value or the
  // login is rejected (OIDC Core §5.7 — sub+iss is the only stable identifier). This is what
  // stops a reassigned username from inheriting the prior holder's account.
  oidcSubject: text("oidc_subject"),
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
});

// Sessions for timeout management
export const sessions = pgTable("sessions", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  userId: varchar("user_id").notNull().references(() => users.id),
  token: text("token").notNull().unique(),
  expiresAt: timestamp("expires_at").notNull(),
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
  lastActivity: timestamp("last_activity").notNull().default(sql`NOW()`),
});

// Threat events detected by the system
export const threatEvents = pgTable("threat_events", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  timestamp: timestamp("timestamp").notNull().default(sql`NOW()`),
  makerId: text("maker_id").notNull(),
  checkerId: text("checker_id"),
  amount: numeric("amount", { precision: 20, scale: 2 }),
  currency: text("currency").notNull().default("UGX"),
  threatType: threatTypeEnum("threat_type").notNull(),
  riskLevel: riskLevelEnum("risk_level").notNull(),
  terminalIp: text("terminal_ip"),
  branch: text("branch"),
  description: text("description"),
  isNeutralized: boolean("is_neutralized").notNull().default(false),
  neutralizedBy: varchar("neutralized_by").references(() => users.id),
  neutralizedAt: timestamp("neutralized_at"),
  anomalyScore: numeric("anomaly_score", { precision: 5, scale: 4 }),
  featureContributions: text("feature_contributions"),
}, (t) => ({
  // Threat-event listings page queries ORDER BY timestamp DESC LIMIT N — backed by index scan, not seq-scan.
  timestampIdx: index("threat_events_timestamp_idx").on(t.timestamp), // ASC canonical — matches prod (indoption 0); btree backward-scan serves ORDER BY DESC. G0 index-drift fix.
}));

// Audit logs for compliance
export const auditLogs = pgTable("audit_logs", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  timestamp: timestamp("timestamp").notNull().default(sql`NOW()`),
  userId: varchar("user_id").references(() => users.id),
  action: text("action").notNull(),
  resource: text("resource").notNull(),
  details: text("details"),
  ipAddress: text("ip_address"),
  previousValue: text("previous_value"),
  newValue: text("new_value"),
}, (t) => ({
  // Hot path: ORDER BY timestamp DESC LIMIT N (recent-events listings, audit-log read load test).
  // Without this index, Postgres parallel-seq-scans the entire table — p95 climbed from ~290 ms
  // to ~500 ms once row count crossed ~70k. Backward-scan on this index is sub-millisecond.
  timestampIdx: index("audit_logs_timestamp_idx").on(t.timestamp), // ASC canonical — matches prod (indoption 0); btree backward-scan serves ORDER BY DESC. G0 index-drift fix.
}));

// System metrics for dashboard
export const systemMetrics = pgTable("system_metrics", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  timestamp: timestamp("timestamp").notNull().default(sql`NOW()`),
  metricName: text("metric_name").notNull(),
  metricValue: numeric("metric_value", { precision: 20, scale: 4 }).notNull(),
  unit: text("unit"),
});

// AI thresholds configuration
export const aiThresholds = pgTable("ai_thresholds", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  thresholdName: text("threshold_name").notNull().unique(),
  thresholdValue: numeric("threshold_value", { precision: 10, scale: 4 }).notNull(),
  description: text("description"),
  updatedBy: varchar("updated_by").references(() => users.id),
  updatedAt: timestamp("updated_at").notNull().default(sql`NOW()`),
});

// Webhook integrations for Core Banking Systems
export const webhookIntegrationEnum = pgEnum("webhook_integration", ["FINACLE", "T24", "FLEXCUBE", "CUSTOM", "SMS_GATEWAY", "EMAIL_GATEWAY"]);
export const webhookEventEnum = pgEnum("webhook_event", ["THREAT_DETECTED", "THREAT_NEUTRALIZED", "SESSION_LOCKED", "COMPLIANCE_ALERT", "BIO_VAULT_BREACH"]);

export const webhookConfigs = pgTable("webhook_configs", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  tenantId: text("tenant_id"), // AS/PLATFORM/2026/008 Chunk B — tenant isolation. Option B two-phase publish: kept NULLABLE in Phase 1 (boot-DDL backfills the prod row + RLS WITH CHECK still rejects NULL/foreign tenant); SET NOT NULL re-asserted in Phase 2 (separate publish).
  name: text("name").notNull(),
  integrationType: webhookIntegrationEnum("integration_type").notNull(),
  endpointUrl: text("endpoint_url").notNull(),
  authType: text("auth_type").notNull().default("bearer"), // bearer, basic, api_key
  authToken: text("auth_token"),
  events: text("events").notNull(), // JSON array of events to trigger
  isActive: boolean("is_active").notNull().default(true),
  retryCount: integer("retry_count").notNull().default(3),
  timeoutMs: integer("timeout_ms").notNull().default(5000),
  createdBy: varchar("created_by").references(() => users.id),
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
  lastTriggered: timestamp("last_triggered"),
}).enableRLS();

// Webhook execution logs
export const webhookLogs = pgTable("webhook_logs", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  tenantId: text("tenant_id"), // AS/PLATFORM/2026/008 Chunk B — derived from parent webhook_configs
  webhookId: varchar("webhook_id").references(() => webhookConfigs.id),
  eventType: webhookEventEnum("event_type").notNull(),
  payload: text("payload").notNull(), // JSON payload sent
  responseStatus: integer("response_status"),
  responseBody: text("response_body"),
  executionTimeMs: integer("execution_time_ms"),
  success: boolean("success").notNull().default(false),
  errorMessage: text("error_message"),
  triggeredAt: timestamp("triggered_at").notNull().default(sql`NOW()`),
}).enableRLS();

// Ghost Core CBS failover event persistence
export const ghostCoreEvents = pgTable("ghost_core_events", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  eventType: text("event_type").notNull(),
  status: text("status").notNull(),
  affectedSystems: text("affected_systems"),
  transactionsProcessed: integer("transactions_processed"),
  shadowLedgerBalance: text("shadow_ledger_balance"),
  duration: integer("duration"),
  details: text("details"),
  tenantId: text("tenant_id"),
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
}).enableRLS();

// SOAR playbook execution history
export const soarExecutions = pgTable("soar_executions", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  playbookId: text("playbook_id").notNull(),
  playbookName: text("playbook_name").notNull(),
  trigger: text("trigger").notNull(),
  status: text("status").notNull(),
  actionsExecuted: integer("actions_executed"),
  actionsTotal: integer("actions_total"),
  startedAt: timestamp("started_at").notNull().default(sql`NOW()`),
  completedAt: timestamp("completed_at"),
  executedBy: text("executed_by"),
  result: text("result"),
  tenantId: text("tenant_id"),
}).enableRLS();

// Observer Agent AI monitoring logs
export const observerLogs = pgTable("observer_logs", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  agentId: text("agent_id").notNull(),
  agentName: text("agent_name").notNull(),
  eventType: text("event_type").notNull(),
  severity: text("severity").notNull(),
  details: text("details"),
  actionTaken: text("action_taken"),
  tenantId: text("tenant_id"),
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
}).enableRLS();

// Notification delivery tracking
export const notificationLogs = pgTable("notification_logs", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  channel: text("channel").notNull(),
  recipient: text("recipient").notNull(),
  subject: text("subject"),
  body: text("body"),
  status: text("status").notNull().default("pending"),
  errorMessage: text("error_message"),
  retryCount: integer("retry_count").notNull().default(0),
  sentAt: timestamp("sent_at"),
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
  tenantId: text("tenant_id"),
}).enableRLS();

// Report export job tracking
export const exportJobs = pgTable("export_jobs", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  exportType: text("export_type").notNull(),
  format: text("format").notNull(),
  status: text("status").notNull().default("pending"),
  filters: text("filters"),
  fileName: text("file_name"),
  fileSize: integer("file_size"),
  downloadUrl: text("download_url"),
  requestedBy: varchar("requested_by").references(() => users.id),
  errorMessage: text("error_message"),
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
  completedAt: timestamp("completed_at"),
  tenantId: text("tenant_id"),
}).enableRLS();

// External API client keys
export const apiKeys = pgTable("api_keys", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  name: text("name").notNull(),
  keyHash: text("key_hash").notNull(),
  keyPrefix: text("key_prefix").notNull(),
  tenantId: text("tenant_id"),
  permissions: text("permissions"),
  rateLimit: integer("rate_limit").notNull().default(1000),
  isActive: boolean("is_active").notNull().default(true),
  lastUsedAt: timestamp("last_used_at"),
  expiresAt: timestamp("expires_at"),
  createdBy: varchar("created_by").references(() => users.id),
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
}).enableRLS();

// Multi-tenant configuration
export const tenants = pgTable("tenants", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  name: text("name").notNull(),
  slug: text("slug").notNull().unique(),
  industry: text("industry").notNull(),
  tier: text("tier").notNull(),
  isActive: boolean("is_active").notNull().default(true),
  settings: text("settings"),
  dataRegion: text("data_region").notNull().default("ug-east"),
  maxUsers: integer("max_users").notNull().default(50),
  encryptionKeyId: text("encryption_key_id"),
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
});

// Backup & disaster recovery tracking
export const backupRecords = pgTable("backup_records", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  backupType: text("backup_type").notNull(),
  status: text("status").notNull(),
  sizeBytes: integer("size_bytes"),
  tablesIncluded: text("tables_included"),
  duration: integer("duration"),
  checksum: text("checksum"),
  storageLocation: text("storage_location"),
  retentionDays: integer("retention_days").notNull().default(90),
  initiatedBy: varchar("initiated_by").references(() => users.id),
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
  completedAt: timestamp("completed_at"),
  // No tenant_id column: backup_records is whole-DB disaster-recovery METADATA with no
  // tenant dimension (F-RP-07, RLS-exempt). The vestigial nullable tenant_id column (always
  // NULL by construction) was DROPPED (M71) so a future writer cannot re-introduce tenant-bound
  // data into an RLS-exempt table — the trap removed at the schema level, not just the code level.
});

// AI-powered threat scoring results
export const aiThreatScores = pgTable("ai_threat_scores", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  threatEventId: varchar("threat_event_id").references(() => threatEvents.id),
  modelVersion: text("model_version").notNull(),
  score: numeric("score", { precision: 5, scale: 4 }).notNull(),
  confidence: numeric("confidence", { precision: 5, scale: 4 }).notNull(),
  explanation: text("explanation"),
  factors: text("factors"),
  processingTimeMs: integer("processing_time_ms"),
  tenantId: text("tenant_id"), // AS/PLATFORM/2026/008 Tenant-Sep Chunk A — RLS-enrolled (nullable in Drizzle; DB NOT NULL via boot-DDL precheck-guarded)
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
}).enableRLS();

// SSO/SAML/OIDC configurations
export const ssoConfigs = pgTable("sso_configs", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  tenantId: text("tenant_id").notNull(),
  provider: text("provider").notNull(),
  entityId: text("entity_id"),
  metadataUrl: text("metadata_url"),
  clientId: text("client_id"),
  clientSecret: text("client_secret"),
  issuerUrl: text("issuer_url"),
  callbackUrl: text("callback_url"),
  isActive: boolean("is_active").notNull().default(true),
  settings: text("settings"),
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
}).enableRLS();

// SOC shift-handover records — externalised from an in-memory Map (failover-readiness audit,
// 2026-07-23). A completed, acknowledged handover is operational state that cannot be retried and
// was lost on every restart. Platform-level (the SOC operates the whole single-tenant deployment;
// no per-tenant scope), DB-authoritative — restart-survival is the point of this table. Nested
// items/escalations/summary/acknowledgement are JSON in text columns (codebase convention).
export const shiftHandovers = pgTable("shift_handovers", {
  id: varchar("id").primaryKey(),
  shiftType: text("shift_type").notNull(),
  shiftDate: timestamp("shift_date").notNull(),
  startTime: timestamp("start_time").notNull(),
  endTime: timestamp("end_time").notNull(),
  outgoingAnalyst: text("outgoing_analyst").notNull(),
  incomingAnalyst: text("incoming_analyst"),
  status: text("status").notNull().default("DRAFT"),
  summary: text("summary").notNull(),                        // JSON ShiftSummary
  openItems: text("open_items").notNull().default("[]"),     // JSON HandoverItem[]
  escalations: text("escalations").notNull().default("[]"),  // JSON Escalation[]
  notes: text("notes").notNull().default(""),
  acknowledgement: text("acknowledgement"),                  // JSON | null
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
  updatedAt: timestamp("updated_at").notNull().default(sql`NOW()`),
});

// Custom translation overrides per tenant
export const i18nOverrides = pgTable("i18n_overrides", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  tenantId: text("tenant_id").notNull(),
  locale: text("locale").notNull(),
  key: text("key").notNull(),
  value: text("value").notNull(),
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
}).enableRLS();

// Insert schemas for new tables
export const insertGhostCoreEventSchema = createInsertSchema(ghostCoreEvents).omit({ id: true, createdAt: true });
export const insertSoarExecutionSchema = createInsertSchema(soarExecutions).omit({ id: true, startedAt: true });
export const insertObserverLogSchema = createInsertSchema(observerLogs).omit({ id: true, createdAt: true });
export const insertNotificationLogSchema = createInsertSchema(notificationLogs).omit({ id: true, createdAt: true });
export const insertExportJobSchema = createInsertSchema(exportJobs).omit({ id: true, createdAt: true });
export const insertApiKeySchema = createInsertSchema(apiKeys).omit({ id: true, createdAt: true });
export const insertTenantSchema = createInsertSchema(tenants).omit({ id: true, createdAt: true });
export const insertBackupRecordSchema = createInsertSchema(backupRecords).omit({ id: true, createdAt: true });
export const insertAiThreatScoreSchema = createInsertSchema(aiThreatScores).omit({ id: true, createdAt: true });
export const insertSsoConfigSchema = createInsertSchema(ssoConfigs).omit({ id: true, createdAt: true });
export const insertI18nOverrideSchema = createInsertSchema(i18nOverrides).omit({ id: true, createdAt: true });

// Select types for new tables
export type GhostCoreEvent = typeof ghostCoreEvents.$inferSelect;
export type SoarExecution = typeof soarExecutions.$inferSelect;
export type ObserverLog = typeof observerLogs.$inferSelect;
export type NotificationLog = typeof notificationLogs.$inferSelect;
export type ExportJob = typeof exportJobs.$inferSelect;
export type ApiKey = typeof apiKeys.$inferSelect;
export type Tenant = typeof tenants.$inferSelect;
export type BackupRecord = typeof backupRecords.$inferSelect;
export type AiThreatScore = typeof aiThreatScores.$inferSelect;
export type SsoConfig = typeof ssoConfigs.$inferSelect;
export type I18nOverride = typeof i18nOverrides.$inferSelect;

// Insert types for new tables
export type InsertGhostCoreEvent = z.infer<typeof insertGhostCoreEventSchema>;
export type InsertSoarExecution = z.infer<typeof insertSoarExecutionSchema>;
export type InsertObserverLog = z.infer<typeof insertObserverLogSchema>;
export type InsertNotificationLog = z.infer<typeof insertNotificationLogSchema>;
export type InsertExportJob = z.infer<typeof insertExportJobSchema>;
export type InsertApiKey = z.infer<typeof insertApiKeySchema>;
export type InsertTenant = z.infer<typeof insertTenantSchema>;
export type InsertBackupRecord = z.infer<typeof insertBackupRecordSchema>;
export type InsertAiThreatScore = z.infer<typeof insertAiThreatScoreSchema>;
export type InsertSsoConfig = z.infer<typeof insertSsoConfigSchema>;
export type InsertI18nOverride = z.infer<typeof insertI18nOverrideSchema>;

// Relations
export const usersRelations = relations(users, ({ many }) => ({
  sessions: many(sessions),
  auditLogs: many(auditLogs),
  neutralizedThreats: many(threatEvents),
}));

export const sessionsRelations = relations(sessions, ({ one }) => ({
  user: one(users, {
    fields: [sessions.userId],
    references: [users.id],
  }),
}));

export const threatEventsRelations = relations(threatEvents, ({ one }) => ({
  neutralizer: one(users, {
    fields: [threatEvents.neutralizedBy],
    references: [users.id],
  }),
}));

export const auditLogsRelations = relations(auditLogs, ({ one }) => ({
  user: one(users, {
    fields: [auditLogs.userId],
    references: [users.id],
  }),
}));

// Insert schemas
export const insertUserSchema = createInsertSchema(users).omit({
  id: true,
  createdAt: true,
  lastLogin: true,
});

export const insertThreatEventSchema = createInsertSchema(threatEvents).omit({
  id: true,
  timestamp: true,
  isNeutralized: true,
  neutralizedBy: true,
  neutralizedAt: true,
});

export const insertAuditLogSchema = createInsertSchema(auditLogs).omit({
  id: true,
  timestamp: true,
});

export const insertSystemMetricSchema = createInsertSchema(systemMetrics).omit({
  id: true,
  timestamp: true,
});

// Login schema
export const loginSchema = z.object({
  username: z.string().min(1, "Username is required"),
  password: z.string().min(1, "Password is required"),
});

// Types
export type InsertUser = z.infer<typeof insertUserSchema>;
export type User = typeof users.$inferSelect;
export type UserRole = "admin" | "risk_manager" | "auditor";

export type InsertThreatEvent = z.infer<typeof insertThreatEventSchema>;
export type ThreatEvent = typeof threatEvents.$inferSelect;
export type RiskLevel = "LOW" | "MEDIUM" | "HIGH" | "CRITICAL";
export type ThreatType = "INTERNAL_XFER" | "MAKER_ONLY" | "BULK_ACCESS" | "AFTER_HOURS" | "GEO_ANOMALY" | "VELOCITY_BREACH";

export type InsertAuditLog = z.infer<typeof insertAuditLogSchema>;
export type AuditLog = typeof auditLogs.$inferSelect;

export type InsertSystemMetric = z.infer<typeof insertSystemMetricSchema>;
export type SystemMetric = typeof systemMetrics.$inferSelect;

export type Session = typeof sessions.$inferSelect;
export type AIThreshold = typeof aiThresholds.$inferSelect;

export const insertWebhookConfigSchema = createInsertSchema(webhookConfigs).omit({
  id: true,
  createdAt: true,
  lastTriggered: true,
});

export type InsertWebhookConfig = z.infer<typeof insertWebhookConfigSchema>;
export type WebhookConfig = typeof webhookConfigs.$inferSelect;
export type WebhookLog = typeof webhookLogs.$inferSelect;
export type WebhookIntegrationType = "FINACLE" | "T24" | "FLEXCUBE" | "CUSTOM" | "SMS_GATEWAY" | "EMAIL_GATEWAY";
export type WebhookEventType = "THREAT_DETECTED" | "THREAT_NEUTRALIZED" | "SESSION_LOCKED" | "COMPLIANCE_ALERT" | "BIO_VAULT_BREACH";

// KYC Types (renamed from "Agentic KYC Types" 2026-07-19 — these types back the
// deterministic screening + operator-attestation path that ships today. Agentic KYC is
// roadmap-not-implemented; see docs/ENGINEERING_ROADMAP_2026.md Feature 5.)
//
// KYCAgentType / KYCAgent / KYCAgentDecision REMOVED (2026-07-16). They typed a 4-agent AI KYC
// workforce — INGESTION / VERIFICATION / LIVENESS / CRITIC — that has NO implementation anywhere:
// no OCR module, no liveness module, and no vision/OCR dependency in package.json. The real KYC
// path is deterministic and never touched them: a NIRA national-ID adapter (which itself refuses
// to fake a match — resolves NOT_CONFIGURED), PEP/SANCTIONS screening (ScreeningKind is exactly
// "PEP" | "SANCTIONS"), name-match/name-normalize, decision-engine, decision-integrity. A registry
// lookup reads no documents and checks no selfies, so OCR and liveness were decoys, not gaps.
//
// These types were one leg of a mutual corroboration with no implementation anchor: a shared type,
// a rendered dashboard, boot-minted API keys, and an AI-BOM declaration to a regulator — four
// confirmations, zero substrate. A reviewer asking "is LIVENESS real?" found all four and stopped.
// Types, UI, config and declarations are CLAIMS; only a module that performs the function is
// evidence. Not required -> removed (the fabricated-seed disposition, as with the 6-node edge mesh).
export type KYCStatus = "PENDING" | "IN_PROGRESS" | "APPROVED" | "REJECTED" | "ESCALATED" | "REVIEW_REQUIRED";
export type KYCRiskTier = "LOW" | "MEDIUM" | "HIGH" | "PEP" | "SANCTIONS";

export interface KYCCustomer {
  id: string;
  nationalId: string;
  fullName: string;
  dateOfBirth: string;
  phoneNumber: string;
  email?: string;
  address?: string;
  photoUrl?: string;
  status: KYCStatus;
  riskTier: KYCRiskTier;
  onboardedAt: string;
  lastVerifiedAt: string;
  // agentDecisions REMOVED with KYCAgentDecision (2026-07-16): a decision record for the 4-agent
  // AI workforce deleted above. It was already structurally empty — GET /api/kyc/customers hardcoded
  // `agentDecisions: []` ("empty arrays in Feature 1") because no agent has ever produced one.
  // Retyping agentType to `string` to keep the shape compiling was considered and rejected: that
  // loosens a real type to preserve dead scaffolding, and leaves a decision record referencing
  // agents that no longer exist in the type system — the dangling reference whole-path removal
  // exists to prevent. The real KYC decision path is decision-engine.ts / decision-integrity.ts.
  lifeEvents: KYCLifeEvent[];
}

export interface KYCLifeEvent {
  id: string;
  customerId: string;
  eventType: "ADDRESS_CHANGE" | "LARGE_DEPOSIT" | "PEP_STATUS" | "SANCTIONS_HIT" | "SIM_SWAP" | "REGION_CHANGE";
  detectedAt: string;
  details: string;
  triggerReVerification: boolean;
}

export interface KYCVerificationRequest {
  customerId: string;
  documentType: "NATIONAL_ID" | "PASSPORT" | "DRIVERS_LICENSE" | "UTILITY_BILL";
  documentData: string; // Base64 or reference
  selfieData?: string;
  ussdSession?: string;
  simSignature?: string;
}

// Active Session Management
export const activeSessions = pgTable("active_sessions", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  userId: varchar("user_id").notNull().references(() => users.id),
  sessionToken: text("session_token").notNull(),
  ipAddress: text("ip_address"),
  userAgent: text("user_agent"),
  deviceType: text("device_type"),
  geoLocation: text("geo_location"),
  riskScore: numeric("risk_score", { precision: 5, scale: 4 }).default("0"),
  isRevoked: boolean("is_revoked").notNull().default(false),
  revokedBy: varchar("revoked_by"),
  revokedAt: timestamp("revoked_at"),
  lastActivity: timestamp("last_activity").notNull().default(sql`NOW()`),
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
  expiresAt: timestamp("expires_at").notNull(),
});

// IP Allowlist/Blocklist Policies
export const ipPolicies = pgTable("ip_policies", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  tenantId: text("tenant_id"),
  policyType: text("policy_type").notNull(), // 'allow' | 'block'
  ipAddress: text("ip_address").notNull(),
  cidrRange: text("cidr_range"),
  description: text("description"),
  isActive: boolean("is_active").notNull().default(true),
  hitCount: integer("hit_count").notNull().default(0),
  lastHitAt: timestamp("last_hit_at"),
  createdBy: varchar("created_by").references(() => users.id),
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
  expiresAt: timestamp("expires_at"),
}).enableRLS();

// API Usage Analytics
export const apiUsageMetrics = pgTable("api_usage_metrics", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  endpoint: text("endpoint").notNull(),
  method: text("method").notNull(),
  statusCode: integer("status_code").notNull(),
  responseTimeMs: integer("response_time_ms").notNull(),
  userId: varchar("user_id"),
  apiKeyId: varchar("api_key_id"),
  tenantId: text("tenant_id"),
  requestSize: integer("request_size"),
  responseSize: integer("response_size"),
  errorMessage: text("error_message"),
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
}, (t) => ({
  // KRI/usage dashboards window by created_at DESC; without this index a 25k+ row table seq-scans on every load.
  createdAtIdx: index("api_usage_metrics_created_at_idx").on(t.createdAt), // ASC canonical — matches prod (indoption 0); btree backward-scan serves ORDER BY DESC. G0 index-drift fix.
})).enableRLS();

// Compliance Reports
export const complianceReports = pgTable("compliance_reports", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  reportType: text("report_type").notNull(), // 'PDPO' | 'PCI_DSS' | 'SOC2' | 'BOu_SAR'
  title: text("title").notNull(),
  status: text("status").notNull().default("generating"), // generating | completed | failed
  framework: text("framework").notNull(),
  period: text("period").notNull(),
  findings: text("findings"),
  evidenceCount: integer("evidence_count").notNull().default(0),
  controlsPassed: integer("controls_passed").notNull().default(0),
  controlsFailed: integer("controls_failed").notNull().default(0),
  controlsTotal: integer("controls_total").notNull().default(0),
  riskScore: numeric("risk_score", { precision: 5, scale: 2 }),
  signedHash: text("signed_hash"),
  // AS/PLATFORM/2026/006 T005 — traceability for a make-real signed attestation: the persisted
  // compliance_check_runs id the report derives from, and that run's sha256 result-set digest. Both
  // are bound into signedHash so the attestation cannot be detached/reused for another run or tenant.
  runId: varchar("run_id"),
  sourceDigest: text("source_digest"),
  generatedBy: varchar("generated_by").references(() => users.id),
  tenantId: text("tenant_id"),
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
  completedAt: timestamp("completed_at"),
}).enableRLS();

// ─── AS/PLATFORM/2026/006 — Real compliance check results (make-real substrate) ───
// Durable, tenant-scoped record of COMPUTED compliance-check outcomes. A run
// (compliance_check_runs) aggregates a set of per-check results
// (compliance_check_results). Results are derived from real system/DB state by
// the registry in server/lib/compliance-checks.ts — never asserted/hardcoded.
// Both tables are RLS-enforced (tenant_id = current_tenant_id()); see
// TENANT_TABLES in server/lib/rls-init.ts. Signed compliance reports sign a
// persisted run's sourceDigest, never a live recompute.
export const complianceCheckRuns = pgTable("compliance_check_runs", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  tenantId: text("tenant_id").notNull(),
  runType: text("run_type").notNull().default("on_demand"), // on_demand | scheduled | report
  triggeredBy: varchar("triggered_by"),
  totalChecks: integer("total_checks").notNull().default(0),
  passCount: integer("pass_count").notNull().default(0),
  failCount: integer("fail_count").notNull().default(0),
  notAssessedCount: integer("not_assessed_count").notNull().default(0),
  sourceDigest: text("source_digest"), // sha256 over the canonical result set (sign-target)
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
}, (t) => [
  // AS/PLATFORM/2026/008 Part B — UNIQUE(tenant_id,id) FK target under Drizzle ownership
  // (referenced by compliance_check_results.ccres_run_fk); name-identical to the live boot-DDL object.
  unique("ccr_tenant_id_uniq").on(t.tenantId, t.id),
]).enableRLS();

export const complianceCheckResults = pgTable("compliance_check_results", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  tenantId: text("tenant_id").notNull(),
  runId: varchar("run_id").notNull(),
  checkId: text("check_id").notNull(),
  scope: text("scope").notNull(), // GLOBAL | TENANT
  status: text("status").notNull(), // PASS | FAIL | NOT_ASSESSED
  detail: text("detail"),
  evidenceRef: text("evidence_ref"),
  evidenceJson: text("evidence_json"),
  checkedAt: timestamp("checked_at").notNull().default(sql`NOW()`),
}, (t) => [
  // AS/PLATFORM/2026/008 Part B — composite FK + index under Drizzle ownership,
  // name+definition-identical to the live boot-DDL objects.
  foreignKey({
    columns: [t.tenantId, t.runId],
    foreignColumns: [complianceCheckRuns.tenantId, complianceCheckRuns.id],
    name: "ccres_run_fk",
  }),
  index("ccres_tenant_run_idx").on(t.tenantId, t.runId),
]).enableRLS();

export const insertComplianceCheckRunSchema = createInsertSchema(complianceCheckRuns).omit({ id: true, createdAt: true });
export const insertComplianceCheckResultSchema = createInsertSchema(complianceCheckResults).omit({ id: true, checkedAt: true });
export type ComplianceCheckRun = typeof complianceCheckRuns.$inferSelect;
export type ComplianceCheckResult = typeof complianceCheckResults.$inferSelect;
export type InsertComplianceCheckRun = z.infer<typeof insertComplianceCheckRunSchema>;
export type InsertComplianceCheckResult = z.infer<typeof insertComplianceCheckResultSchema>;

// ─── AS/PLATFORM/2026/006 T006 — GLOBAL platform operational execution records ───
// report_executions + cicd_pipeline_runs are PLATFORM-GLOBAL operational history,
// NOT tenant-scoped compliance state. The report scheduler is a global cron
// (setInterval, no request/tenant context) and CICD dispatch is a global platform
// action with NO real CI callback wired. These tables are DELIBERATELY NON-RLS
// (no tenant_id; NOT added to TENANT_TABLES in server/lib/rls-init.ts) — mirroring
// the pilot-pack global-cron precedent (audit_logs). aegis_app writes them directly
// under its blanket schema GRANT (no synthetic tenant, no superuser write path).
// scope='GLOBAL' is recorded EXPLICITLY so a reader never mistakes these for
// per-tenant assurance. NO fabricated success: status reflects the REAL executor
// outcome (success | failed | not_implemented) or the REAL dispatch state
// (not_wired — AEGIS fired a webhook but has no callback to learn the CI outcome).
// Read paths derive durable run history from these tables (replacing the prior
// in-memory volatile arrays that were lost on restart).
export const reportExecutions = pgTable("report_executions", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  scheduleId: text("schedule_id").notNull(),
  scheduleName: text("schedule_name").notNull(),
  reportType: text("report_type").notNull(),
  status: text("status").notNull(), // success | failed | not_implemented
  scope: text("scope").notNull().default("GLOBAL"),
  durationMs: integer("duration_ms").notNull().default(0),
  reportSize: integer("report_size").notNull().default(0),
  recipientCount: integer("recipient_count").notNull().default(0), // count only — never recipient addresses
  triggeredBy: text("triggered_by"),
  error: text("error"),
  executedAt: timestamp("executed_at").notNull().default(sql`NOW()`),
}, (t) => ({
  executedAtIdx: index("report_executions_executed_at_idx").on(t.executedAt), // ASC canonical — matches prod (indoption 0) + the boot-DDL create. G0 index-drift fix.
  scheduleIdx: index("report_executions_schedule_id_idx").on(t.scheduleId),
}));

export const cicdPipelineRuns = pgTable("cicd_pipeline_runs", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  pipelineId: text("pipeline_id").notNull(),
  pipelineName: text("pipeline_name").notNull(),
  provider: text("provider").notNull(),
  triggerType: text("trigger_type").notNull(), // change_request | manual | schedule | webhook
  status: text("status").notNull(), // not_wired | success | failed | cancelled
  scope: text("scope").notNull().default("GLOBAL"),
  dispatchOk: integer("dispatch_ok").notNull().default(0), // 1 if the webhook POST returned ok; 0 otherwise
  durationMs: integer("duration_ms").notNull().default(0),
  triggeredBy: text("triggered_by"),
  changeRequestId: text("change_request_id"),
  commitSha: text("commit_sha"),
  executedAt: timestamp("executed_at").notNull().default(sql`NOW()`),
}, (t) => ({
  executedAtIdx: index("cicd_pipeline_runs_executed_at_idx").on(t.executedAt), // ASC canonical — matches prod (indoption 0) + the boot-DDL create. G0 index-drift fix.
  pipelineIdx: index("cicd_pipeline_runs_pipeline_id_idx").on(t.pipelineId),
}));

export const insertReportExecutionSchema = createInsertSchema(reportExecutions).omit({ id: true, executedAt: true });
export const insertCicdPipelineRunSchema = createInsertSchema(cicdPipelineRuns).omit({ id: true, executedAt: true });
export type ReportExecution = typeof reportExecutions.$inferSelect;
export type CicdPipelineRun = typeof cicdPipelineRuns.$inferSelect;
export type InsertReportExecution = z.infer<typeof insertReportExecutionSchema>;
export type InsertCicdPipelineRun = z.infer<typeof insertCicdPipelineRunSchema>;

// Platform Health / SLO Monitoring
export const sloTargets = pgTable("slo_targets", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  serviceName: text("service_name").notNull(),
  metricType: text("metric_type").notNull(), // 'availability' | 'latency' | 'error_rate'
  targetValue: numeric("target_value", { precision: 10, scale: 4 }).notNull(),
  windowDays: integer("window_days").notNull().default(30),
  currentValue: numeric("current_value", { precision: 10, scale: 4 }),
  burnRate: numeric("burn_rate", { precision: 10, scale: 4 }),
  budgetRemaining: numeric("budget_remaining", { precision: 10, scale: 4 }),
  status: text("status").notNull().default("healthy"), // healthy | warning | breached
  lastCheckedAt: timestamp("last_checked_at"),
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
});

export const healthChecks = pgTable("health_checks", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  componentName: text("component_name").notNull(),
  status: text("status").notNull(), // 'healthy' | 'degraded' | 'down'
  responseTimeMs: integer("response_time_ms"),
  details: text("details"),
  lastCheckedAt: timestamp("last_checked_at").notNull().default(sql`NOW()`),
});

// Incident SLA Tracking
export const incidentSLAs = pgTable("incident_slas", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  incidentId: text("incident_id").notNull(),
  severity: text("severity").notNull(), // 'P1' | 'P2' | 'P3' | 'P4'
  title: text("title").notNull(),
  description: text("description"),
  status: text("status").notNull().default("open"), // open | acknowledged | investigating | resolved | closed
  assignedTo: varchar("assigned_to"),
  escalationLevel: integer("escalation_level").notNull().default(0),
  slaTargetMinutes: integer("sla_target_minutes").notNull(),
  acknowledgedAt: timestamp("acknowledged_at"),
  resolvedAt: timestamp("resolved_at"),
  breachedAt: timestamp("breached_at"),
  isSlaBreached: boolean("is_sla_breached").notNull().default(false),
  rootCause: text("root_cause"),
  resolution: text("resolution"),
  tenantId: text("tenant_id"),
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
}).enableRLS();

// Insert schemas for commercial-grade tables
export const insertActiveSessionSchema = createInsertSchema(activeSessions).omit({ id: true, createdAt: true, isRevoked: true });
export const insertIpPolicySchema = createInsertSchema(ipPolicies).omit({ id: true, createdAt: true, hitCount: true });
export const insertApiUsageMetricSchema = createInsertSchema(apiUsageMetrics).omit({ id: true, createdAt: true });
export const insertComplianceReportSchema = createInsertSchema(complianceReports).omit({ id: true, createdAt: true });
export const insertSloTargetSchema = createInsertSchema(sloTargets).omit({ id: true, createdAt: true });
export const insertHealthCheckSchema = createInsertSchema(healthChecks).omit({ id: true });
export const insertIncidentSLASchema = createInsertSchema(incidentSLAs).omit({ id: true, createdAt: true, isSlaBreached: true, escalationLevel: true });

// Select types for commercial-grade tables
export type ActiveSession = typeof activeSessions.$inferSelect;
export type IpPolicy = typeof ipPolicies.$inferSelect;
export type ApiUsageMetric = typeof apiUsageMetrics.$inferSelect;
export type ComplianceReport = typeof complianceReports.$inferSelect;
export type SloTarget = typeof sloTargets.$inferSelect;
export type HealthCheck = typeof healthChecks.$inferSelect;
export type IncidentSLA = typeof incidentSLAs.$inferSelect;

// Insert types for commercial-grade tables
export type InsertActiveSession = z.infer<typeof insertActiveSessionSchema>;
export type InsertIpPolicy = z.infer<typeof insertIpPolicySchema>;
export type InsertApiUsageMetric = z.infer<typeof insertApiUsageMetricSchema>;
export type InsertComplianceReport = z.infer<typeof insertComplianceReportSchema>;
export type InsertSloTarget = z.infer<typeof insertSloTargetSchema>;
export type InsertHealthCheck = z.infer<typeof insertHealthCheckSchema>;
export type InsertIncidentSLA = z.infer<typeof insertIncidentSLASchema>;

// ============ COMMERCIAL-GRADE FEATURES V2 ============

// Rate Limiting & Quota Governance
export const rateLimitPolicies = pgTable("rate_limit_policies", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  name: text("name").notNull(),
  scope: text("scope").notNull().default("global"),
  tenantId: text("tenant_id"),
  apiKeyId: varchar("api_key_id"),
  endpoint: text("endpoint"),
  requestsPerMinute: integer("requests_per_minute").notNull().default(60),
  requestsPerHour: integer("requests_per_hour").notNull().default(1000),
  requestsPerDay: integer("requests_per_day").notNull().default(10000),
  burstLimit: integer("burst_limit").notNull().default(100),
  throttleAction: text("throttle_action").notNull().default("reject"),
  isActive: boolean("is_active").notNull().default(true),
  createdBy: varchar("created_by"),
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
  updatedAt: timestamp("updated_at").notNull().default(sql`NOW()`),
}).enableRLS();

export const rateLimitEvents = pgTable("rate_limit_events", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  policyId: varchar("policy_id").references(() => rateLimitPolicies.id),
  endpoint: text("endpoint").notNull(),
  ipAddress: text("ip_address"),
  apiKeyId: varchar("api_key_id"),
  action: text("action").notNull(),
  currentCount: integer("current_count").notNull(),
  limitValue: integer("limit_value").notNull(),
  windowType: text("window_type").notNull(),
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
});

// DLP & PII Scanner
export const dlpFindings = pgTable("dlp_findings", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  findingType: text("finding_type").notNull(),
  severity: text("severity").notNull().default("medium"),
  source: text("source").notNull(),
  endpoint: text("endpoint"),
  dataPattern: text("data_pattern").notNull(),
  matchCount: integer("match_count").notNull().default(1),
  sampleContext: text("sample_context"),
  status: text("status").notNull().default("open"),
  remediation: text("remediation"),
  tenantId: text("tenant_id"),
  detectedBy: text("detected_by").notNull().default("automated"),
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
  resolvedAt: timestamp("resolved_at"),
}).enableRLS();

export const dlpPolicies = pgTable("dlp_policies", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  name: text("name").notNull(),
  description: text("description"),
  patternType: text("pattern_type").notNull(),
  regex: text("regex").notNull(),
  severity: text("severity").notNull().default("high"),
  action: text("action").notNull().default("alert"),
  isActive: boolean("is_active").notNull().default(true),
  scanScope: text("scan_scope").notNull().default("all"),
  // AS/PLATFORM/2026/008 Tenant-Sep Chunk C — nullable by design: NULL = a GLOBAL
  // built-in pattern inherited by every tenant; a set value = a per-tenant override.
  // RLS (rls-init.ts dedicated block) enforces USING own+globals / WITH CHECK own-only.
  tenantId: text("tenant_id"),
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
}).enableRLS();

// Vulnerability & SBOM Management
export const sbomComponents = pgTable("sbom_components", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  name: text("name").notNull(),
  version: text("version").notNull(),
  componentType: text("component_type").notNull(),
  license: text("license"),
  supplier: text("supplier"),
  hash: text("hash"),
  isDirectDep: boolean("is_direct_dep").notNull().default(true),
  lastScannedAt: timestamp("last_scanned_at"),
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
});

export const vulnerabilityFindings = pgTable("vulnerability_findings", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  componentId: varchar("component_id").references(() => sbomComponents.id),
  cveId: text("cve_id").notNull(),
  severity: text("severity").notNull(),
  cvssScore: numeric("cvss_score", { precision: 4, scale: 1 }),
  description: text("description"),
  affectedVersions: text("affected_versions"),
  fixedVersion: text("fixed_version"),
  status: text("status").notNull().default("open"),
  assignedTo: text("assigned_to"),
  slaDeadline: timestamp("sla_deadline"),
  patchedAt: timestamp("patched_at"),
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
});

// Change Management & Approval Workflow
export const changeRequests = pgTable("change_requests", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  changeId: text("change_id").notNull(),
  title: text("title").notNull(),
  description: text("description"),
  changeType: text("change_type").notNull(),
  riskLevel: text("risk_level").notNull().default("low"),
  status: text("status").notNull().default("draft"),
  requestedBy: varchar("requested_by"),
  approvedBy: varchar("approved_by"),
  implementedBy: varchar("implemented_by"),
  rollbackPlan: text("rollback_plan"),
  impactAssessment: text("impact_assessment"),
  scheduledAt: timestamp("scheduled_at"),
  implementedAt: timestamp("implemented_at"),
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
  updatedAt: timestamp("updated_at").notNull().default(sql`NOW()`),
});

export const changeApprovals = pgTable("change_approvals", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  changeRequestId: varchar("change_request_id").references(() => changeRequests.id),
  approverRole: text("approver_role").notNull(),
  decision: text("decision").notNull(),
  comments: text("comments"),
  decidedBy: varchar("decided_by"),
  decidedAt: timestamp("decided_at").notNull().default(sql`NOW()`),
});

// Geo-Fencing & Data Residency
export const geoPolicies = pgTable("geo_policies", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  name: text("name").notNull(),
  policyType: text("policy_type").notNull(),
  allowedRegions: text("allowed_regions").array().notNull(),
  blockedRegions: text("blocked_regions").array(),
  dataClassification: text("data_classification").notNull().default("standard"),
  enforcementMode: text("enforcement_mode").notNull().default("monitor"),
  tenantId: text("tenant_id"),
  isActive: boolean("is_active").notNull().default(true),
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
}).enableRLS();

export const geoViolations = pgTable("geo_violations", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  policyId: varchar("policy_id").references(() => geoPolicies.id),
  violationType: text("violation_type").notNull(),
  sourceIp: text("source_ip"),
  sourceRegion: text("source_region").notNull(),
  targetRegion: text("target_region"),
  endpoint: text("endpoint"),
  userId: varchar("user_id"),
  action: text("action").notNull(),
  severity: text("severity").notNull().default("medium"),
  tenantId: text("tenant_id"), // AS/PLATFORM/2026/008 Tenant-Sep Chunk A — RLS-enrolled (nullable in Drizzle; DB NOT NULL via boot-DDL precheck-guarded)
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
}).enableRLS();

// Security Posture Scorecard
export const postureScores = pgTable("posture_scores", {
  id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
  overallScore: numeric("overall_score", { precision: 5, scale: 2 }).notNull(),
  categoryScores: text("category_scores").notNull(),
  riskLevel: text("risk_level").notNull(),
  complianceScore: numeric("compliance_score", { precision: 5, scale: 2 }),
  vulnerabilityScore: numeric("vulnerability_score", { precision: 5, scale: 2 }),
  incidentScore: numeric("incident_score", { precision: 5, scale: 2 }),
  accessControlScore: numeric("access_control_score", { precision: 5, scale: 2 }),
  dataProtectionScore: numeric("data_protection_score", { precision: 5, scale: 2 }),
  networkSecurityScore: numeric("network_security_score", { precision: 5, scale: 2 }),
  totalFindings: integer("total_findings").notNull().default(0),
  criticalFindings: integer("critical_findings").notNull().default(0),
  recommendations: text("recommendations"),
  assessedBy: text("assessed_by").notNull().default("automated"),
  tenantId: text("tenant_id"),
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
}).enableRLS();

export const insertRateLimitPolicySchema = createInsertSchema(rateLimitPolicies).omit({ id: true, createdAt: true, updatedAt: true });
export const insertRateLimitEventSchema = createInsertSchema(rateLimitEvents).omit({ id: true, createdAt: true });
export const insertDlpFindingSchema = createInsertSchema(dlpFindings).omit({ id: true, createdAt: true });
export const insertDlpPolicySchema = createInsertSchema(dlpPolicies).omit({ id: true, createdAt: true });
export const insertSbomComponentSchema = createInsertSchema(sbomComponents).omit({ id: true, createdAt: true });
export const insertVulnerabilityFindingSchema = createInsertSchema(vulnerabilityFindings).omit({ id: true, createdAt: true });
export const insertChangeRequestSchema = createInsertSchema(changeRequests).omit({ id: true, createdAt: true, updatedAt: true });
export const insertChangeApprovalSchema = createInsertSchema(changeApprovals).omit({ id: true, decidedAt: true });
export const insertGeoPolicySchema = createInsertSchema(geoPolicies).omit({ id: true, createdAt: true });
export const insertGeoViolationSchema = createInsertSchema(geoViolations).omit({ id: true, createdAt: true });
export const insertPostureScoreSchema = createInsertSchema(postureScores).omit({ id: true, createdAt: true });

export type RateLimitPolicy = typeof rateLimitPolicies.$inferSelect;
export type RateLimitEvent = typeof rateLimitEvents.$inferSelect;
export type DlpFinding = typeof dlpFindings.$inferSelect;
export type DlpPolicy = typeof dlpPolicies.$inferSelect;
export type SbomComponent = typeof sbomComponents.$inferSelect;
export type VulnerabilityFinding = typeof vulnerabilityFindings.$inferSelect;
export type ChangeRequest = typeof changeRequests.$inferSelect;
export type ChangeApproval = typeof changeApprovals.$inferSelect;
export type GeoPolicy = typeof geoPolicies.$inferSelect;
export type GeoViolation = typeof geoViolations.$inferSelect;
export type PostureScore = typeof postureScores.$inferSelect;

// AI Chat tables
export const conversations = pgTable("conversations", {
  id: integer("id").primaryKey().generatedAlwaysAsIdentity(),
  title: text("title").notNull(),
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
});

export const messages = pgTable("messages", {
  id: integer("id").primaryKey().generatedAlwaysAsIdentity(),
  conversationId: integer("conversation_id").notNull().references(() => conversations.id, { onDelete: "cascade" }),
  role: text("role").notNull(),
  content: text("content").notNull(),
  createdAt: timestamp("created_at").notNull().default(sql`NOW()`),
});

export const insertConversationSchema = createInsertSchema(conversations).omit({ id: true, createdAt: true });
export const insertMessageSchema = createInsertSchema(messages).omit({ id: true, createdAt: true });
export type Conversation = typeof conversations.$inferSelect;
export type InsertConversation = z.infer<typeof insertConversationSchema>;
export type Message = typeof messages.$inferSelect;
export type InsertMessage = z.infer<typeof insertMessageSchema>;

export * from "./schema-persistence";
export * from "./schema-integrations";
export * from "./schema-wave5";
export * from "./schema-final";
export * from "./schema-threat-forecast";
export * from "./schema-rbac";
export * from "./schema-pilot-extras";
export * from "./schema-pilot-extras-2";
export * from "./schema-pilot-extras-3";
export * from "./schema-pilot-extras-4";
export * from "./schema-pilot-extras-5";
export * from "./schema-pilot-extras-6";
export * from "./schema-pilot-extras-7";
export * from "./schema-pilot-extras-8";
export * from "./schema-pilot-extras-9";
export * from "./schema-pilot-extras-10";
export * from "./schema-pilot-extras-11";
export * from "./schema-wave12";
export * from "./schema-wave13";
export * from "./schema-pilot-tier-a";
export * from "./schema-pilot-tier-b";
export * from "./schema-xai";
export * from "./schema-transaction-anomaly";
