import { int, mysqlEnum, mysqlTable, text, timestamp, varchar, boolean } from "drizzle-orm/mysql-core";
import { associationGeoPrecisions, associationGeoSources } from "@shared/associationGeo";
import { associationThematicValues } from "@shared/associationThematics";

/**
 * Core user table backing auth flow.
 */
export const users = mysqlTable("users", {
  id: int("id").autoincrement().primaryKey(),
  openId: varchar("openId", { length: 64 }).notNull().unique(),
  name: text("name"),
  email: varchar("email", { length: 320 }),
  passwordHash: varchar("passwordHash", { length: 255 }),
  loginMethod: varchar("loginMethod", { length: 64 }),
  role: mysqlEnum("role", ["user", "accueil", "service_terrain", "logistique_controle", "admin", "directrice", "super_admin"]).default("user").notNull(),
  canManageLogistics: boolean("canManageLogistics").default(false).notNull(),
  delegatedSalleSignerUserId: int("delegatedSalleSignerUserId"),
  isActive: boolean("isActive").default(true).notNull(),
  failedLoginAttempts: int("failedLoginAttempts").default(0).notNull(),
  lockedUntil: timestamp("lockedUntil"),
  mfaEnabled: boolean("mfaEnabled").default(false).notNull(),
  mfaMethod: varchar("mfaMethod", { length: 32 }),
  mfaChallengeToken: varchar("mfaChallengeToken", { length: 96 }),
  mfaCodeHash: varchar("mfaCodeHash", { length: 255 }),
  mfaCodeExpiresAt: timestamp("mfaCodeExpiresAt"),
  mfaCodeAttempts: int("mfaCodeAttempts").default(0).notNull(),
  mfaTotpSecretEncrypted: varchar("mfaTotpSecretEncrypted", { length: 512 }),
  mfaTotpPendingSecretEncrypted: varchar("mfaTotpPendingSecretEncrypted", { length: 512 }),
  deletionRequestedAt: timestamp("deletionRequestedAt"),
  purgeScheduledAt: timestamp("purgeScheduledAt"),
  purgedAt: timestamp("purgedAt"),
  legalHold: boolean("legalHold").default(false).notNull(),
  legalHoldReason: text("legalHoldReason"),
  privacyConsentVersion: varchar("privacyConsentVersion", { length: 32 }),
  privacyConsentAcceptedAt: timestamp("privacyConsentAcceptedAt"),
  privacyConsentContext: varchar("privacyConsentContext", { length: 64 }),
  createdAt: timestamp("createdAt").defaultNow().notNull(),
  updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
  lastSignedIn: timestamp("lastSignedIn").defaultNow().notNull(),
});

export type User = typeof users.$inferSelect;
export type InsertUser = typeof users.$inferInsert;

/**
 * Association profile table - stores complete association information
 */
export const associations = mysqlTable("associations", {
  id: int("id").autoincrement().primaryKey(),
  userId: int("userId").notNull().unique(),
  sourceDirectoryEntryId: int("sourceDirectoryEntryId"),
  
  // Basic information
  nomAssociation: varchar("nomAssociation", { length: 255 }).notNull(),
  siret: varchar("siret", { length: 14 }),
  rna: varchar("rna", { length: 10 }), // Numéro RNA (W + 9 chiffres)
  thematique: text("thematique"),
  
  // Address
  adresse: text("adresse"),
  codePostal: varchar("codePostal", { length: 10 }),
  ville: varchar("ville", { length: 100 }),
  
  // Contact
  telephone: varchar("telephone", { length: 20 }),
  emailContact: varchar("emailContact", { length: 320 }),
  siteWeb: varchar("siteWeb", { length: 255 }),
  facebookUrl: varchar("facebookUrl", { length: 255 }),
  instagramUrl: varchar("instagramUrl", { length: 255 }),
  
  // Legal information
  dateCreation: timestamp("dateCreation"),
  objetAssociation: text("objetAssociation"),
  statutJuridique: mysqlEnum("statutJuridique", [
    "association_loi_1901",
    "association_reconnue_utilite_publique",
    "fondation",
    "autre"
  ]).default("association_loi_1901"),
  
  // Representative
  nomRepresentant: varchar("nomRepresentant", { length: 255 }),
  fonctionRepresentant: varchar("fonctionRepresentant", { length: 100 }),
  gouvernance: text("gouvernance"),
  
  // Profile completion and status
  profileComplete: boolean("profileComplete").default(false),
  isActive: boolean("isActive").default(true).notNull(),
  
  createdAt: timestamp("createdAt").defaultNow().notNull(),
  updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
});

export type Association = typeof associations.$inferSelect;
export type InsertAssociation = typeof associations.$inferInsert;

/**
 * Imported association directory - source of truth from the Savanes registry.
 */
export const associationDirectoryEntries = mysqlTable("associationDirectoryEntries", {
  id: int("id").autoincrement().primaryKey(),

  nomAssociation: varchar("nomAssociation", { length: 255 }).notNull(),
  emailOfficiel: varchar("emailOfficiel", { length: 320 }),
  emailOfficielNormalise: varchar("emailOfficielNormalise", { length: 320 }).unique(),
  siret: varchar("siret", { length: 14 }),
  rna: varchar("rna", { length: 10 }),
  thematique: text("thematique"),
  adresse: text("adresse"),
  codePostal: varchar("codePostal", { length: 10 }),
  ville: varchar("ville", { length: 100 }),
  telephone: varchar("telephone", { length: 20 }),
  siteWeb: varchar("siteWeb", { length: 255 }),
  facebookUrl: varchar("facebookUrl", { length: 255 }),
  instagramUrl: varchar("instagramUrl", { length: 255 }),
  dateCreation: timestamp("dateCreation"),
  objetAssociation: text("objetAssociation"),
  statutJuridique: mysqlEnum("statutJuridique", [
    "association_loi_1901",
    "association_reconnue_utilite_publique",
    "fondation",
    "autre"
  ]).default("association_loi_1901"),
  nomRepresentant: varchar("nomRepresentant", { length: 255 }),
  fonctionRepresentant: varchar("fonctionRepresentant", { length: 100 }),
  gouvernance: text("gouvernance"),

  latitude: varchar("latitude", { length: 32 }),
  longitude: varchar("longitude", { length: 32 }),
  geoSource: mysqlEnum("geoSource", associationGeoSources),
  geoPrecision: mysqlEnum("geoPrecision", associationGeoPrecisions).default("commune_center").notNull(),
  geoLastSyncedAt: timestamp("geoLastSyncedAt"),
  externalSourceStatus: varchar("externalSourceStatus", { length: 100 }),
  externalSourceLabel: varchar("externalSourceLabel", { length: 255 }),
  associationStatus: varchar("associationStatus", { length: 40 }),
  registryLastUpdatedAt: timestamp("registryLastUpdatedAt"),
  referenceLastCheckedAt: timestamp("referenceLastCheckedAt"),
  referenceStatus: varchar("referenceStatus", { length: 100 }),
  referenceSourceLabel: varchar("referenceSourceLabel", { length: 255 }),

  sourceFileName: varchar("sourceFileName", { length: 255 }),
  sourceRowNumber: int("sourceRowNumber"),
  sourceFingerprint: varchar("sourceFingerprint", { length: 64 }),
  isActive: boolean("isActive").default(true).notNull(),
  importedAt: timestamp("importedAt").defaultNow().notNull(),
  updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
});

export type AssociationDirectoryEntry = typeof associationDirectoryEntries.$inferSelect;
export type InsertAssociationDirectoryEntry = typeof associationDirectoryEntries.$inferInsert;

export const associationDirectoryReviewSourceTypes = ["portal_signup", "helloasso"] as const;
export const associationDirectoryReviewStatuses = ["pending", "linked", "created", "ignored"] as const;

export const associationDirectoryReviews = mysqlTable("associationDirectoryReviews", {
  id: int("id").autoincrement().primaryKey(),
  sourceType: mysqlEnum("sourceType", associationDirectoryReviewSourceTypes).notNull(),
  sourceLabel: varchar("sourceLabel", { length: 255 }),
  userId: int("userId"),
  resolvedDirectoryEntryId: int("resolvedDirectoryEntryId"),

  proposedNomAssociation: varchar("proposedNomAssociation", { length: 255 }).notNull(),
  proposedEmail: varchar("proposedEmail", { length: 320 }),
  proposedEmailNormalise: varchar("proposedEmailNormalise", { length: 320 }),
  proposedSiret: varchar("proposedSiret", { length: 14 }),
  proposedRna: varchar("proposedRna", { length: 10 }),
  proposedVille: varchar("proposedVille", { length: 100 }),

  matchStatus: varchar("matchStatus", { length: 40 }),
  payload: text("payload"),
  status: mysqlEnum("status", associationDirectoryReviewStatuses).default("pending").notNull(),
  resolutionNote: text("resolutionNote"),

  createdAt: timestamp("createdAt").defaultNow().notNull(),
  updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
});

export type AssociationDirectoryReview = typeof associationDirectoryReviews.$inferSelect;
export type InsertAssociationDirectoryReview = typeof associationDirectoryReviews.$inferInsert;

export const associationDirectoryUpdateProposalSourceTypes = ["official_registry", "helloasso"] as const;
export const associationDirectoryUpdateProposalStatuses = ["pending", "applied", "dismissed"] as const;

export const associationDirectoryUpdateProposals = mysqlTable("associationDirectoryUpdateProposals", {
  id: int("id").autoincrement().primaryKey(),
  directoryEntryId: int("directoryEntryId").notNull(),
  sourceType: mysqlEnum("sourceType", associationDirectoryUpdateProposalSourceTypes).notNull(),
  sourceLabel: varchar("sourceLabel", { length: 255 }),
  summary: varchar("summary", { length: 255 }),
  payload: text("payload").notNull(),
  status: mysqlEnum("status", associationDirectoryUpdateProposalStatuses).default("pending").notNull(),
  appliedAt: timestamp("appliedAt"),
  dismissedAt: timestamp("dismissedAt"),
  createdAt: timestamp("createdAt").defaultNow().notNull(),
  updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
});

export type AssociationDirectoryUpdateProposal = typeof associationDirectoryUpdateProposals.$inferSelect;
export type InsertAssociationDirectoryUpdateProposal = typeof associationDirectoryUpdateProposals.$inferInsert;

/**
 * Document types for associations
 */
export const documentTypes = [
  "statuts",
  "recepisse_declaration",
  "rib",
  "rapport_activite",
  "rapport_financier",
  "pv_assemblee",
  "liste_dirigeants",
  "attestation_assurance",
  "autre"
] as const;

/**
 * Documents table - stores document metadata (files in S3)
 */
export const documents = mysqlTable("documents", {
  id: int("id").autoincrement().primaryKey(),
  associationId: int("associationId").notNull(),
  
  nom: varchar("nom", { length: 255 }).notNull(),
  type: mysqlEnum("type", documentTypes).notNull(),
  description: text("description"),
  
  // S3 storage
  fileKey: varchar("fileKey", { length: 512 }).notNull(),
  fileUrl: varchar("fileUrl", { length: 1024 }).notNull(),
  mimeType: varchar("mimeType", { length: 100 }),
  fileSize: int("fileSize"), // in bytes
  
  uploadedAt: timestamp("uploadedAt").defaultNow().notNull(),
  updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
});

export type Document = typeof documents.$inferSelect;
export type InsertDocument = typeof documents.$inferInsert;

/**
 * Request types available
 */
export const requestTypes = [
  "subvention_fonctionnement",
  "subvention_projet",
  "agrement_jeunesse_education",
  "agrement_sport",
  "autorisation_occupation",
  "demande_salle",
  "demande_materiel_evenementiel",
  "autre"
] as const;

/**
 * Request status
 */
export const requestStatuses = [
  "brouillon",
  "soumise",
  "en_cours_traitement",
  "information_complementaire",
  "validee",
  "refusee",
  "annulee"
] as const;

/**
 * Request priority levels
 */
export const requestPriorities = [
  "basse",
  "normale",
  "haute",
  "urgente"
] as const;

/**
 * Requests table - stores all requests from associations
 */
export const requests = mysqlTable("requests", {
  id: int("id").autoincrement().primaryKey(),
  associationId: int("associationId").notNull(),
  
  // Request info
  type: mysqlEnum("type", requestTypes).notNull(),
  titre: varchar("titre", { length: 255 }).notNull(),
  description: text("description"),
  
  // Form data stored as JSON
  formData: text("formData"), // JSON string
  
  // Status tracking
  status: mysqlEnum("status", requestStatuses).default("brouillon").notNull(),
  priority: mysqlEnum("priority", requestPriorities).default("normale").notNull(),
  
  // Financial (for subventions)
  montantDemande: int("montantDemande"), // in cents
  montantAccorde: int("montantAccorde"), // in cents
  
  // Processing
  dateSubmission: timestamp("dateSubmission"),
  dateTraitement: timestamp("dateTraitement"),
  dateLimiteTraitement: timestamp("dateLimiteTraitement"),
  assigneA: int("assigneA"), // admin user id assigned to process
  traitePar: int("traitePar"), // admin user id who processed
  commentaireAdmin: text("commentaireAdmin"),
  
  // Attached documents (JSON array of document IDs)
  documentsJoints: text("documentsJoints"),
  
  createdAt: timestamp("createdAt").defaultNow().notNull(),
  updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
});

export type Request = typeof requests.$inferSelect;
export type InsertRequest = typeof requests.$inferInsert;

/**
 * Request history - tracks all actions on a request
 */
export const requestHistory = mysqlTable("requestHistory", {
  id: int("id").autoincrement().primaryKey(),
  requestId: int("requestId").notNull(),
  
  action: mysqlEnum("action", [
    "creation",
    "soumission",
    "assignation",
    "changement_statut",
    "ajout_commentaire",
    "modification",
    "validation",
    "refus",
    "changement_salle",
    "annulation"
  ]).notNull(),
  
  ancienStatut: mysqlEnum("ancienStatut", requestStatuses),
  nouveauStatut: mysqlEnum("nouveauStatut", requestStatuses),
  
  commentaire: text("commentaire"),
  userId: int("userId").notNull(), // who performed the action
  
  createdAt: timestamp("createdAt").defaultNow().notNull(),
});

export type RequestHistory = typeof requestHistory.$inferSelect;
export type InsertRequestHistory = typeof requestHistory.$inferInsert;

/**
 * Response templates - predefined responses for admins
 */
export const responseTemplates = mysqlTable("responseTemplates", {
  id: int("id").autoincrement().primaryKey(),
  
  nom: varchar("nom", { length: 255 }).notNull(),
  type: mysqlEnum("type", ["validation", "refus", "information_complementaire", "autre"]).notNull(),
  sujet: varchar("sujet", { length: 255 }),
  contenu: text("contenu").notNull(),
  
  actif: boolean("actif").default(true),
  
  createdAt: timestamp("createdAt").defaultNow().notNull(),
  updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
});

export type ResponseTemplate = typeof responseTemplates.$inferSelect;
export type InsertResponseTemplate = typeof responseTemplates.$inferInsert;

/**
 * Request templates - predefined form templates
 */
export const requestTemplates = mysqlTable("requestTemplates", {
  id: int("id").autoincrement().primaryKey(),
  
  type: mysqlEnum("type", requestTypes).notNull(),
  nom: varchar("nom", { length: 255 }).notNull(),
  description: text("description"),
  
  // Form schema as JSON
  formSchema: text("formSchema").notNull(),
  
  // Required documents
  documentsRequis: text("documentsRequis"), // JSON array
  
  // Service destinataire
  serviceDestinataire: varchar("serviceDestinataire", { length: 255 }),
  emailDestinataire: varchar("emailDestinataire", { length: 320 }),
  
  // Processing settings
  delaiTraitementJours: int("delaiTraitementJours").default(30),
  
  actif: boolean("actif").default(true),
  
  createdAt: timestamp("createdAt").defaultNow().notNull(),
  updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
});

export type RequestTemplate = typeof requestTemplates.$inferSelect;
export type InsertRequestTemplate = typeof requestTemplates.$inferInsert;

/**
 * Audit log - tracks all admin actions
 */
export const auditLog = mysqlTable("auditLog", {
  id: int("id").autoincrement().primaryKey(),
  
  userId: int("userId").notNull(),
  action: varchar("action", { length: 100 }).notNull(),
  entityType: varchar("entityType", { length: 50 }).notNull(), // association, request, user, etc.
  entityId: int("entityId"),
  
  details: text("details"), // JSON with action details
  ipAddress: varchar("ipAddress", { length: 45 }),
  
  createdAt: timestamp("createdAt").defaultNow().notNull(),
});

export type AuditLog = typeof auditLog.$inferSelect;
export type InsertAuditLog = typeof auditLog.$inferInsert;

/**
 * Admin notifications
 */
export const adminNotifications = mysqlTable("adminNotifications", {
  id: int("id").autoincrement().primaryKey(),
  
  userId: int("userId"), // null = all admins
  
  type: mysqlEnum("type", [
    "nouvelle_demande",
    "demande_en_retard",
    "dossier_incomplet",
    "nouvelle_association",
    "systeme",
    "changement_salle",
    "annulation_demande",
    "modification_demande"
  ]).notNull(),
  
  titre: varchar("titre", { length: 255 }).notNull(),
  message: text("message").notNull(),
  lien: varchar("lien", { length: 512 }),
  
  lu: boolean("lu").default(false),
  
  createdAt: timestamp("createdAt").defaultNow().notNull(),
});

export type AdminNotification = typeof adminNotifications.$inferSelect;
export type InsertAdminNotification = typeof adminNotifications.$inferInsert;

/**
 * Portal settings - configurable settings
 */
export const portalSettings = mysqlTable("portalSettings", {
  id: int("id").autoincrement().primaryKey(),
  
  cle: varchar("cle", { length: 100 }).notNull().unique(),
  valeur: text("valeur").notNull(),
  description: text("description"),
  
  updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
});

export type PortalSetting = typeof portalSettings.$inferSelect;
export type InsertPortalSetting = typeof portalSettings.$inferInsert;

/**
 * Operational recap services - reusable internal distribution lists for processed requests.
 */
export const operationalRecapServices = mysqlTable("operationalRecapServices", {
  id: int("id").autoincrement().primaryKey(),

  label: varchar("label", { length: 255 }).notNull(),
  usage: mysqlEnum("usage", ["terrain", "controle"]).default("terrain").notNull(),
  description: text("description"),
  recipientEmails: text("recipientEmails").notNull(), // JSON array of emails
  actif: boolean("actif").default(true).notNull(),

  createdAt: timestamp("createdAt").defaultNow().notNull(),
  updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
});

export type OperationalRecapService = typeof operationalRecapServices.$inferSelect;
export type InsertOperationalRecapService = typeof operationalRecapServices.$inferInsert;

/**
 * Association invitations - secure one-time invitations for directory onboarding.
 */
export const associationInvitations = mysqlTable("associationInvitations", {
  id: int("id").autoincrement().primaryKey(),

  directoryEntryId: int("directoryEntryId").notNull(),
  emailOfficiel: varchar("emailOfficiel", { length: 320 }).notNull(),
  emailOfficielNormalise: varchar("emailOfficielNormalise", { length: 320 }).notNull(),
  token: varchar("token", { length: 128 }).notNull().unique(),
  deliveryMode: mysqlEnum("deliveryMode", ["email", "manual_link"]).notNull(),
  emailSent: boolean("emailSent").default(false).notNull(),

  sentByUserId: int("sentByUserId").notNull(),
  sentAt: timestamp("sentAt").defaultNow().notNull(),
  expiresAt: timestamp("expiresAt").notNull(),
  usedAt: timestamp("usedAt"),
  revokedAt: timestamp("revokedAt"),
  acceptedByUserId: int("acceptedByUserId"),

  createdAt: timestamp("createdAt").defaultNow().notNull(),
  updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
});

export type AssociationInvitation = typeof associationInvitations.$inferSelect;
export type InsertAssociationInvitation = typeof associationInvitations.$inferInsert;

/**
 * Email action tokens - secure one-time tokens for email-based actions (validate/refuse)
 */
export const emailActionTokens = mysqlTable("emailActionTokens", {
  id: int("id").autoincrement().primaryKey(),
  
  token: varchar("token", { length: 64 }).notNull().unique(),
  requestId: int("requestId").notNull(),
  action: mysqlEnum("action", ["validee", "refusee", "acceptation_devis_salle", "refus_devis_salle"]).notNull(),
  
  used: boolean("used").default(false).notNull(),
  expiresAt: timestamp("expiresAt").notNull(),
  usedAt: timestamp("usedAt"),
  usedBy: int("usedBy"), // admin user id
  
  createdAt: timestamp("createdAt").defaultNow().notNull(),
});

export type EmailActionToken = typeof emailActionTokens.$inferSelect;
export type InsertEmailActionToken = typeof emailActionTokens.$inferInsert;

export const materialReturnStatuses = [
  "planifie",
  "en_attente",
  "en_cours",
  "cloture",
] as const;

export const materialReturnComplianceValues = [
  "conforme",
  "non_conforme",
] as const;

export const materialReturnLitigationStatuses = [
  "none",
  "pending",
  "resolved",
] as const;

export const materialReturnArbitrationDecisions = [
  "partial_retention",
  "full_retention",
  "dismissed",
] as const;

export const materialReturnFollowups = mysqlTable("materialReturnFollowups", {
  id: int("id").autoincrement().primaryKey(),

  requestId: int("requestId").notNull().unique(),
  associationId: int("associationId").notNull(),
  serviceLabel: varchar("serviceLabel", { length: 255 }),
  recipientEmails: text("recipientEmails"), // JSON array
  supervisionServiceLabel: varchar("supervisionServiceLabel", { length: 255 }),
  supervisionRecipientEmails: text("supervisionRecipientEmails"), // JSON array

  restitutionDate: timestamp("restitutionDate").notNull(),
  plannedSendAt: timestamp("plannedSendAt").notNull(),
  sentAt: timestamp("sentAt"),
  status: mysqlEnum("status", materialReturnStatuses).default("planifie").notNull(),
  uploadToken: varchar("uploadToken", { length: 96 }).notNull().unique(),
  uploadTokenExpiresAt: timestamp("uploadTokenExpiresAt").notNull(),

  signedFileKey: varchar("signedFileKey", { length: 512 }),
  signedFileUrl: varchar("signedFileUrl", { length: 1024 }),
  signedFileName: varchar("signedFileName", { length: 255 }),
  signedMimeType: varchar("signedMimeType", { length: 100 }),
  uploadedByName: varchar("uploadedByName", { length: 255 }),
  uploadedByEmail: varchar("uploadedByEmail", { length: 320 }),
  agentUserId: int("agentUserId"),
  agentRole: varchar("agentRole", { length: 100 }),
  borrowerName: varchar("borrowerName", { length: 255 }),
  borrowerRole: varchar("borrowerRole", { length: 120 }),
  compliance: mysqlEnum("compliance", materialReturnComplianceValues),
  discrepancyCategories: text("discrepancyCategories"),
  discrepancyDetails: text("discrepancyDetails"),
  issueFlag: boolean("issueFlag").default(false).notNull(),
  litigationStatus: mysqlEnum("litigationStatus", materialReturnLitigationStatuses).default("none").notNull(),
  blockedItems: text("blockedItems"),
  estimatedDamageAmount: int("estimatedDamageAmount"),
  estimatedDamageSource: varchar("estimatedDamageSource", { length: 32 }),
  arbitrationDecision: mysqlEnum("arbitrationDecision", materialReturnArbitrationDecisions),
  arbitrationAmount: int("arbitrationAmount"),
  arbitrationNotes: text("arbitrationNotes"),
  arbitratedByUserId: int("arbitratedByUserId"),
  arbitratedAt: timestamp("arbitratedAt"),
  litigationLetterKey: varchar("litigationLetterKey", { length: 512 }),
  litigationLetterUrl: varchar("litigationLetterUrl", { length: 1024 }),
  litigationLetterName: varchar("litigationLetterName", { length: 255 }),
  agentSignatureKey: varchar("agentSignatureKey", { length: 512 }),
  agentSignatureUrl: varchar("agentSignatureUrl", { length: 1024 }),
  borrowerSignatureKey: varchar("borrowerSignatureKey", { length: 512 }),
  borrowerSignatureUrl: varchar("borrowerSignatureUrl", { length: 1024 }),
  finalPdfKey: varchar("finalPdfKey", { length: 512 }),
  finalPdfUrl: varchar("finalPdfUrl", { length: 1024 }),
  finalPdfName: varchar("finalPdfName", { length: 255 }),
  geoLatitude: varchar("geoLatitude", { length: 64 }),
  geoLongitude: varchar("geoLongitude", { length: 64 }),
  geoStatus: varchar("geoStatus", { length: 32 }),
  geoFailureReason: text("geoFailureReason"),
  uploadedAt: timestamp("uploadedAt"),
  validatedAt: timestamp("validatedAt"),
  closedAt: timestamp("closedAt"),
  lastReminderSentAt: timestamp("lastReminderSentAt"),
  reactivatedByUserId: int("reactivatedByUserId"),
  reactivatedAt: timestamp("reactivatedAt"),
  reactivationReason: text("reactivationReason"),

  createdAt: timestamp("createdAt").defaultNow().notNull(),
  updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
});

export type MaterialReturnFollowup = typeof materialReturnFollowups.$inferSelect;
export type InsertMaterialReturnFollowup = typeof materialReturnFollowups.$inferInsert;
