import { sqliteTable, text, integer, real } from 'drizzle-orm/sqlite-core';
import { pgTable, uuid, varchar, text as pgText, timestamp, decimal, integer as pgInteger, boolean as pgBoolean } from 'drizzle-orm/pg-core';

// Type to determine which schema to use
const dbType = process.env.DB_TYPE || 'sqlite';

// ==================== SQLite Schema ====================
export const sqliteUsers = sqliteTable('users', {
  id: text('id').primaryKey(),
  email: text('email').notNull().unique(),
  password: text('password'), // Nullable for unclaimed accounts
  name: text('name').notNull(),
  phone: text('phone'),
  role: text('role', { enum: ['admin', 'organizer', 'staff', 'marketing', 'user'] }).notNull().default('user'),
  languagePreference: text('language_preference'),
  // New fields for progressive accounts and OAuth
  isClaimed: integer('is_claimed', { mode: 'boolean' }).notNull().default(true),
  googleId: text('google_id'),
  rucNumber: text('ruc_number'),
  accountStatus: text('account_status', { enum: ['active', 'unclaimed', 'suspended'] }).notNull().default('active'),
  // Incremented to invalidate previously issued JWTs (logout-everywhere, password change/reset)
  tokenVersion: integer('token_version').notNull().default(0),
  // Better Auth core + admin plugin fields (auth-schema.ts maps the same columns)
  emailVerified: integer('email_verified', { mode: 'boolean' }).notNull().default(false),
  image: text('image'),
  banned: integer('banned', { mode: 'boolean' }).notNull().default(false),
  banReason: text('ban_reason'),
  banExpires: integer('ban_expires', { mode: 'timestamp_ms' }),
  createdAt: text('created_at').notNull(),
  updatedAt: text('updated_at').notNull(),
});

// Magic link tokens for passwordless login
export const sqliteMagicLinkTokens = sqliteTable('magic_link_tokens', {
  id: text('id').primaryKey(),
  userId: text('user_id').notNull().references(() => sqliteUsers.id),
  token: text('token').notNull().unique(),
  type: text('type', { enum: ['login', 'reset_password', 'claim_account', 'email_verification'] }).notNull(),
  expiresAt: text('expires_at').notNull(),
  usedAt: text('used_at'),
  createdAt: text('created_at').notNull(),
});

// User sessions for session management
export const sqliteUserSessions = sqliteTable('user_sessions', {
  id: text('id').primaryKey(),
  userId: text('user_id').notNull().references(() => sqliteUsers.id),
  token: text('token').notNull().unique(),
  userAgent: text('user_agent'),
  ipAddress: text('ip_address'),
  lastActiveAt: text('last_active_at').notNull(),
  expiresAt: text('expires_at').notNull(),
  createdAt: text('created_at').notNull(),
});

// Invoices table
export const sqliteInvoices = sqliteTable('invoices', {
  id: text('id').primaryKey(),
  paymentId: text('payment_id').notNull().references(() => sqlitePayments.id),
  userId: text('user_id').notNull().references(() => sqliteUsers.id),
  invoiceNumber: text('invoice_number').notNull().unique(),
  rucNumber: text('ruc_number'),
  legalName: text('legal_name'),
  amount: real('amount').notNull(),
  currency: text('currency').notNull().default('PYG'),
  pdfUrl: text('pdf_url'),
  status: text('status', { enum: ['generated', 'voided'] }).notNull().default('generated'),
  createdAt: text('created_at').notNull(),
});

export const sqliteEvents = sqliteTable('events', {
  id: text('id').primaryKey(),
  slug: text('slug').unique(),
  title: text('title').notNull(),
  titleEs: text('title_es'),
  description: text('description').notNull(),
  descriptionEs: text('description_es'),
  shortDescription: text('short_description'),
  shortDescriptionEs: text('short_description_es'),
  startDatetime: text('start_datetime').notNull(),
  endDatetime: text('end_datetime'),
  location: text('location').notNull(),
  locationUrl: text('location_url'),
  price: real('price').notNull().default(0),
  currency: text('currency').notNull().default('PYG'),
  capacity: integer('capacity').notNull().default(50),
  status: text('status', { enum: ['draft', 'published', 'unlisted', 'cancelled', 'completed', 'archived'] }).notNull().default('draft'),
  bannerUrl: text('banner_url'),
  externalBookingEnabled: integer('external_booking_enabled', { mode: 'boolean' }).notNull().default(false),
  externalBookingUrl: text('external_booking_url'),
  createdAt: text('created_at').notNull(),
  updatedAt: text('updated_at').notNull(),
});

// Historical slugs that still resolve (and redirect) to an event's canonical slug
export const sqliteEventSlugAliases = sqliteTable('event_slug_aliases', {
  slug: text('slug').primaryKey(),
  eventId: text('event_id').notNull().references(() => sqliteEvents.id),
  createdAt: text('created_at').notNull(),
});

export const sqliteTickets = sqliteTable('tickets', {
  id: text('id').primaryKey(),
  bookingId: text('booking_id'), // Groups multiple tickets from same booking
  userId: text('user_id').notNull().references(() => sqliteUsers.id),
  eventId: text('event_id').notNull().references(() => sqliteEvents.id),
  attendeeFirstName: text('attendee_first_name').notNull(),
  attendeeLastName: text('attendee_last_name'),
  attendeeEmail: text('attendee_email'),
  attendeePhone: text('attendee_phone'),
  attendeeRuc: text('attendee_ruc'), // Paraguayan tax ID for invoicing
  preferredLanguage: text('preferred_language'),
  status: text('status', { enum: ['pending', 'confirmed', 'cancelled', 'checked_in', 'on_hold'] }).notNull().default('pending'),
  checkinAt: text('checkin_at'),
  checkedInByAdminId: text('checked_in_by_admin_id').references(() => sqliteUsers.id), // Who performed the check-in
  qrCode: text('qr_code'),
  adminNote: text('admin_note'),
  isGuest: integer('is_guest', { mode: 'boolean' }).notNull().default(false),
  // Paid: revenue counted; Unpaid: balance due (collect at door); Comp: free guest, no revenue
  paymentStatus: text('payment_status', { enum: ['paid', 'unpaid', 'comp'] }).notNull().default('unpaid'),
  createdAt: text('created_at').notNull(),
});

export const sqlitePayments = sqliteTable('payments', {
  id: text('id').primaryKey(),
  ticketId: text('ticket_id').notNull().references(() => sqliteTickets.id),
  provider: text('provider', { enum: ['bancard', 'lightning', 'cash', 'bank_transfer', 'tpago'] }).notNull(),
  amount: real('amount').notNull(),
  currency: text('currency').notNull().default('PYG'),
  status: text('status', { enum: ['pending', 'pending_approval', 'paid', 'refunded', 'failed', 'cancelled', 'on_hold'] }).notNull().default('pending'),
  reference: text('reference'),
  lnbitsInvoice: text('lnbits_invoice'), // BOLT11 string, stored so an unpaid invoice can be redisplayed without a new LNbits call
  lnbitsExpiresAt: text('lnbits_expires_at'), // When lnbitsInvoice expires
  lnbitsAmountSats: integer('lnbits_amount_sats'), // Sats amount for display (from LNbits' fiat conversion)
  userMarkedPaidAt: text('user_marked_paid_at'), // When user clicked "I Have Paid"
  payerName: text('payer_name'), // Name of payer if different from attendee
  paidAt: text('paid_at'),
  paidByAdminId: text('paid_by_admin_id'),
  adminNote: text('admin_note'), // Internal admin notes
  reminderSentAt: text('reminder_sent_at'), // When payment reminder email was sent
  // Where the money was taken: 'presale' (online/admin, the default) or 'door'
  // (recorded by staff on the door check-in screen). Splits pre-sale vs door revenue.
  source: text('source', { enum: ['presale', 'door'] }).notNull().default('presale'),
  // Door tender used, for the end-of-night cash-up. Null for pre-sale payments.
  // 'guest' is a zero-amount comp entry and carries no revenue.
  method: text('method', { enum: ['cash', 'bitcoin', 'transfer', 'guest'] }),
  createdAt: text('created_at').notNull(),
  updatedAt: text('updated_at').notNull(),
});

// Idempotency records for door check-in actions.
//
// The door screen fires check-ins / walk-in creations optimistically and retries
// on flaky venue wifi, so every action carries a client-generated key. The first
// request stores its response here; replays return that stored response instead
// of creating a second ticket, payment or check-in. `undoState` holds exactly
// what the action changed so the 10-second Undo can reverse it precisely.
export const sqliteIdempotencyKeys = sqliteTable('idempotency_keys', {
  key: text('key').primaryKey(),
  scope: text('scope').notNull(),
  result: text('result').notNull(),      // JSON response body of the original request
  undoState: text('undo_state'),          // JSON describing how to reverse the action
  undoneAt: text('undone_at'),
  createdAt: text('created_at').notNull(),
});

// Payment Options Configuration Table (global settings)
export const sqlitePaymentOptions = sqliteTable('payment_options', {
  id: text('id').primaryKey(),
  // TPago configuration
  tpagoEnabled: integer('tpago_enabled', { mode: 'boolean' }).notNull().default(false),
  tpagoLink: text('tpago_link'),
  tpagoLink2: text('tpago_link_2'),
  tpagoLink3: text('tpago_link_3'),
  tpagoLink4: text('tpago_link_4'),
  tpagoLink5: text('tpago_link_5'),
  tpagoInstructions: text('tpago_instructions'),
  tpagoInstructionsEs: text('tpago_instructions_es'),
  // Bank Transfer configuration
  bankTransferEnabled: integer('bank_transfer_enabled', { mode: 'boolean' }).notNull().default(false),
  bankName: text('bank_name'),
  bankAccountHolder: text('bank_account_holder'),
  bankAccountNumber: text('bank_account_number'),
  bankAlias: text('bank_alias'),
  bankPhone: text('bank_phone'),
  bankNotes: text('bank_notes'),
  bankNotesEs: text('bank_notes_es'),
  // Lightning configuration
  lightningEnabled: integer('lightning_enabled', { mode: 'boolean' }).notNull().default(true),
  // Cash configuration
  cashEnabled: integer('cash_enabled', { mode: 'boolean' }).notNull().default(true),
  cashInstructions: text('cash_instructions'),
  cashInstructionsEs: text('cash_instructions_es'),
  // Booking settings
  allowDuplicateBookings: integer('allow_duplicate_bookings', { mode: 'boolean' }).notNull().default(false),
  // Metadata
  updatedAt: text('updated_at').notNull(),
  updatedBy: text('updated_by').references(() => sqliteUsers.id),
});

// Event-specific payment overrides
export const sqliteEventPaymentOverrides = sqliteTable('event_payment_overrides', {
  id: text('id').primaryKey(),
  eventId: text('event_id').notNull().references(() => sqliteEvents.id),
  // Override flags (null means use global)
  tpagoEnabled: integer('tpago_enabled', { mode: 'boolean' }),
  tpagoLink: text('tpago_link'),
  tpagoLink2: text('tpago_link_2'),
  tpagoLink3: text('tpago_link_3'),
  tpagoLink4: text('tpago_link_4'),
  tpagoLink5: text('tpago_link_5'),
  tpagoInstructions: text('tpago_instructions'),
  tpagoInstructionsEs: text('tpago_instructions_es'),
  bankTransferEnabled: integer('bank_transfer_enabled', { mode: 'boolean' }),
  bankName: text('bank_name'),
  bankAccountHolder: text('bank_account_holder'),
  bankAccountNumber: text('bank_account_number'),
  bankAlias: text('bank_alias'),
  bankPhone: text('bank_phone'),
  bankNotes: text('bank_notes'),
  bankNotesEs: text('bank_notes_es'),
  lightningEnabled: integer('lightning_enabled', { mode: 'boolean' }),
  cashEnabled: integer('cash_enabled', { mode: 'boolean' }),
  cashInstructions: text('cash_instructions'),
  cashInstructionsEs: text('cash_instructions_es'),
  // Metadata
  createdAt: text('created_at').notNull(),
  updatedAt: text('updated_at').notNull(),
});

export const sqliteContacts = sqliteTable('contacts', {
  id: text('id').primaryKey(),
  name: text('name').notNull(),
  email: text('email').notNull(),
  message: text('message').notNull(),
  status: text('status', { enum: ['new', 'read', 'replied'] }).notNull().default('new'),
  createdAt: text('created_at').notNull(),
});

export const sqliteEmailSubscribers = sqliteTable('email_subscribers', {
  id: text('id').primaryKey(),
  email: text('email').notNull().unique(),
  name: text('name'),
  status: text('status', { enum: ['active', 'unsubscribed'] }).notNull().default('active'),
  createdAt: text('created_at').notNull(),
});

export const sqliteMedia = sqliteTable('media', {
  id: text('id').primaryKey(),
  fileUrl: text('file_url').notNull(),
  type: text('type', { enum: ['image', 'video', 'document'] }).notNull(),
  relatedId: text('related_id'),
  relatedType: text('related_type'),
  createdAt: text('created_at').notNull(),
});

export const sqliteAuditLogs = sqliteTable('audit_logs', {
  id: text('id').primaryKey(),
  userId: text('user_id').references(() => sqliteUsers.id),
  action: text('action').notNull(),
  target: text('target'),
  targetId: text('target_id'),
  details: text('details'),
  timestamp: text('timestamp').notNull(),
});

export const sqliteEmailTemplates = sqliteTable('email_templates', {
  id: text('id').primaryKey(),
  name: text('name').notNull().unique(),
  slug: text('slug').notNull().unique(),
  subject: text('subject').notNull(),
  subjectEs: text('subject_es'),
  bodyHtml: text('body_html').notNull(),
  bodyHtmlEs: text('body_html_es'),
  bodyText: text('body_text'),
  bodyTextEs: text('body_text_es'),
  description: text('description'),
  variables: text('variables'), // JSON array of available variables
  isSystem: integer('is_system', { mode: 'boolean' }).notNull().default(false),
  isActive: integer('is_active', { mode: 'boolean' }).notNull().default(true),
  createdAt: text('created_at').notNull(),
  updatedAt: text('updated_at').notNull(),
});

export const sqliteEmailLogs = sqliteTable('email_logs', {
  id: text('id').primaryKey(),
  templateId: text('template_id').references(() => sqliteEmailTemplates.id),
  eventId: text('event_id').references(() => sqliteEvents.id),
  recipientEmail: text('recipient_email').notNull(),
  recipientName: text('recipient_name'),
  subject: text('subject').notNull(),
  bodyHtml: text('body_html'),
  status: text('status', { enum: ['pending', 'sent', 'failed', 'bounced'] }).notNull().default('pending'),
  errorMessage: text('error_message'),
  sentAt: text('sent_at'),
  sentBy: text('sent_by').references(() => sqliteUsers.id),
  createdAt: text('created_at').notNull(),
  resendAttempts: integer('resend_attempts').notNull().default(0),
  lastResentAt: text('last_resent_at'),
});

export const sqliteEmailSettings = sqliteTable('email_settings', {
  id: text('id').primaryKey(),
  key: text('key').notNull().unique(),
  value: text('value').notNull(),
  updatedAt: text('updated_at').notNull(),
});

// Durable email queue. Jobs survive process restarts; a startup recovery step
// resets any 'processing' rows back to 'pending'.
export const sqliteEmailQueue = sqliteTable('email_queue', {
  id: text('id').primaryKey(),
  params: text('params').notNull(), // JSON-encoded TemplateEmailJobParams
  status: text('status', { enum: ['pending', 'processing', 'sent', 'failed'] }).notNull().default('pending'),
  attempts: integer('attempts').notNull().default(0),
  lastError: text('last_error'),
  createdAt: text('created_at').notNull(),
  processedAt: text('processed_at'),
});

// Legal Pages table for admin-editable legal content
export const sqliteLegalPages = sqliteTable('legal_pages', {
  id: text('id').primaryKey(),
  slug: text('slug').notNull().unique(),
  title: text('title').notNull(), // English title
  titleEs: text('title_es'), // Spanish title
  contentText: text('content_text').notNull(), // Plain text edited by admin (English)
  contentTextEs: text('content_text_es'), // Plain text edited by admin (Spanish)
  contentMarkdown: text('content_markdown').notNull(), // Generated markdown for public display (English)
  contentMarkdownEs: text('content_markdown_es'), // Generated markdown for public display (Spanish)
  updatedAt: text('updated_at').notNull(),
  updatedBy: text('updated_by').references(() => sqliteUsers.id),
  createdAt: text('created_at').notNull(),
});

// FAQ questions table (admin-managed, shown on /faq and optionally on homepage)
export const sqliteFaqQuestions = sqliteTable('faq_questions', {
  id: text('id').primaryKey(),
  question: text('question').notNull(),
  questionEs: text('question_es'),
  answer: text('answer').notNull(),
  answerEs: text('answer_es'),
  enabled: integer('enabled', { mode: 'boolean' }).notNull().default(true),
  showOnHomepage: integer('show_on_homepage', { mode: 'boolean' }).notNull().default(false),
  rank: integer('rank').notNull().default(0),
  createdAt: text('created_at').notNull(),
  updatedAt: text('updated_at').notNull(),
});

// Legal Settings table for legal page placeholder values
export const sqliteLegalSettings = sqliteTable('legal_settings', {
  id: text('id').primaryKey(),
  companyName: text('company_name'),
  legalEntityName: text('legal_entity_name'),
  rucNumber: text('ruc_number'),
  companyAddress: text('company_address'),
  companyCity: text('company_city'),
  companyCountry: text('company_country'),
  supportEmail: text('support_email'),
  legalEmail: text('legal_email'),
  governingLaw: text('governing_law'),
  jurisdictionCity: text('jurisdiction_city'),
  updatedAt: text('updated_at').notNull(),
  updatedBy: text('updated_by').references(() => sqliteUsers.id),
});

// Site Settings table for global website configuration
export const sqliteSiteSettings = sqliteTable('site_settings', {
  id: text('id').primaryKey(),
  // Timezone configuration
  timezone: text('timezone').notNull().default('America/Asuncion'),
  // Site info
  siteName: text('site_name').notNull().default('Spanglish'),
  siteDescription: text('site_description'),
  siteDescriptionEs: text('site_description_es'),
  // Contact info
  contactEmail: text('contact_email'),
  contactPhone: text('contact_phone'),
  // Social links (can also be stored here as fallback)
  facebookUrl: text('facebook_url'),
  instagramUrl: text('instagram_url'),
  twitterUrl: text('twitter_url'),
  linkedinUrl: text('linkedin_url'),
  // Featured event - manually promoted event shown on homepage/linktree
  featuredEventId: text('featured_event_id').references(() => sqliteEvents.id),
  // Other settings
  maintenanceMode: integer('maintenance_mode', { mode: 'boolean' }).notNull().default(false),
  maintenanceMessage: text('maintenance_message'),
  maintenanceMessageEs: text('maintenance_message_es'),
  // Metadata
  updatedAt: text('updated_at').notNull(),
  updatedBy: text('updated_by').references(() => sqliteUsers.id),
});

// ==================== PostgreSQL Schema ====================
export const pgUsers = pgTable('users', {
  id: uuid('id').primaryKey(),
  email: varchar('email', { length: 255 }).notNull().unique(),
  password: varchar('password', { length: 255 }), // Nullable for unclaimed accounts
  name: varchar('name', { length: 255 }).notNull(),
  phone: varchar('phone', { length: 50 }),
  role: varchar('role', { length: 20 }).notNull().default('user'),
  languagePreference: varchar('language_preference', { length: 10 }),
  // New fields for progressive accounts and OAuth
  isClaimed: pgInteger('is_claimed').notNull().default(1),
  googleId: varchar('google_id', { length: 255 }),
  rucNumber: varchar('ruc_number', { length: 15 }),
  accountStatus: varchar('account_status', { length: 20 }).notNull().default('active'),
  // Incremented to invalidate previously issued JWTs (logout-everywhere, password change/reset)
  tokenVersion: pgInteger('token_version').notNull().default(0),
  // Better Auth core + admin plugin fields (auth-schema.ts maps the same columns)
  emailVerified: pgBoolean('email_verified').notNull().default(false),
  image: pgText('image'),
  banned: pgBoolean('banned').notNull().default(false),
  banReason: pgText('ban_reason'),
  banExpires: timestamp('ban_expires'),
  createdAt: timestamp('created_at').notNull(),
  updatedAt: timestamp('updated_at').notNull(),
});

// Magic link tokens for passwordless login
export const pgMagicLinkTokens = pgTable('magic_link_tokens', {
  id: uuid('id').primaryKey(),
  userId: uuid('user_id').notNull().references(() => pgUsers.id),
  token: varchar('token', { length: 255 }).notNull().unique(),
  type: varchar('type', { length: 30 }).notNull(),
  expiresAt: timestamp('expires_at').notNull(),
  usedAt: timestamp('used_at'),
  createdAt: timestamp('created_at').notNull(),
});

// User sessions for session management
export const pgUserSessions = pgTable('user_sessions', {
  id: uuid('id').primaryKey(),
  userId: uuid('user_id').notNull().references(() => pgUsers.id),
  token: varchar('token', { length: 500 }).notNull().unique(),
  userAgent: pgText('user_agent'),
  ipAddress: varchar('ip_address', { length: 45 }),
  lastActiveAt: timestamp('last_active_at').notNull(),
  expiresAt: timestamp('expires_at').notNull(),
  createdAt: timestamp('created_at').notNull(),
});

// Invoices table
export const pgInvoices = pgTable('invoices', {
  id: uuid('id').primaryKey(),
  paymentId: uuid('payment_id').notNull().references(() => pgPayments.id),
  userId: uuid('user_id').notNull().references(() => pgUsers.id),
  invoiceNumber: varchar('invoice_number', { length: 50 }).notNull().unique(),
  rucNumber: varchar('ruc_number', { length: 15 }),
  legalName: varchar('legal_name', { length: 255 }),
  amount: decimal('amount', { precision: 10, scale: 2 }).notNull(),
  currency: varchar('currency', { length: 10 }).notNull().default('PYG'),
  pdfUrl: varchar('pdf_url', { length: 500 }),
  status: varchar('status', { length: 20 }).notNull().default('generated'),
  createdAt: timestamp('created_at').notNull(),
});

export const pgEvents = pgTable('events', {
  id: uuid('id').primaryKey(),
  slug: varchar('slug', { length: 255 }).unique(),
  title: varchar('title', { length: 255 }).notNull(),
  titleEs: varchar('title_es', { length: 255 }),
  description: pgText('description').notNull(),
  descriptionEs: pgText('description_es'),
  shortDescription: varchar('short_description', { length: 300 }),
  shortDescriptionEs: varchar('short_description_es', { length: 300 }),
  startDatetime: timestamp('start_datetime', { withTimezone: true }).notNull(),
  endDatetime: timestamp('end_datetime', { withTimezone: true }),
  location: varchar('location', { length: 500 }).notNull(),
  locationUrl: varchar('location_url', { length: 500 }),
  price: decimal('price', { precision: 10, scale: 2 }).notNull().default('0'),
  currency: varchar('currency', { length: 10 }).notNull().default('PYG'),
  capacity: pgInteger('capacity').notNull().default(50),
  status: varchar('status', { length: 20 }).notNull().default('draft'),
  bannerUrl: varchar('banner_url', { length: 500 }),
  externalBookingEnabled: pgInteger('external_booking_enabled').notNull().default(0),
  externalBookingUrl: varchar('external_booking_url', { length: 500 }),
  createdAt: timestamp('created_at').notNull(),
  updatedAt: timestamp('updated_at').notNull(),
});

// Historical slugs that still resolve (and redirect) to an event's canonical slug
export const pgEventSlugAliases = pgTable('event_slug_aliases', {
  slug: varchar('slug', { length: 255 }).primaryKey(),
  eventId: uuid('event_id').notNull().references(() => pgEvents.id),
  createdAt: timestamp('created_at').notNull(),
});

export const pgTickets = pgTable('tickets', {
  id: uuid('id').primaryKey(),
  bookingId: uuid('booking_id'), // Groups multiple tickets from same booking
  userId: uuid('user_id').notNull().references(() => pgUsers.id),
  eventId: uuid('event_id').notNull().references(() => pgEvents.id),
  attendeeFirstName: varchar('attendee_first_name', { length: 255 }).notNull(),
  attendeeLastName: varchar('attendee_last_name', { length: 255 }),
  attendeeEmail: varchar('attendee_email', { length: 255 }),
  attendeePhone: varchar('attendee_phone', { length: 50 }),
  attendeeRuc: varchar('attendee_ruc', { length: 15 }), // Paraguayan tax ID for invoicing
  preferredLanguage: varchar('preferred_language', { length: 10 }),
  status: varchar('status', { length: 20 }).notNull().default('pending'),
  checkinAt: timestamp('checkin_at'),
  checkedInByAdminId: uuid('checked_in_by_admin_id').references(() => pgUsers.id), // Who performed the check-in
  qrCode: varchar('qr_code', { length: 255 }),
  adminNote: pgText('admin_note'),
  isGuest: pgInteger('is_guest').notNull().default(0),
  // Paid: revenue counted; Unpaid: balance due (collect at door); Comp: free guest, no revenue
  paymentStatus: varchar('payment_status', { length: 10 }).notNull().default('unpaid'),
  createdAt: timestamp('created_at').notNull(),
});

export const pgPayments = pgTable('payments', {
  id: uuid('id').primaryKey(),
  ticketId: uuid('ticket_id').notNull().references(() => pgTickets.id),
  provider: varchar('provider', { length: 50 }).notNull(),
  amount: decimal('amount', { precision: 10, scale: 2 }).notNull(),
  currency: varchar('currency', { length: 10 }).notNull().default('PYG'),
  status: varchar('status', { length: 20 }).notNull().default('pending'),
  reference: varchar('reference', { length: 255 }),
  lnbitsInvoice: pgText('lnbits_invoice'), // BOLT11 string, stored so an unpaid invoice can be redisplayed without a new LNbits call
  lnbitsExpiresAt: timestamp('lnbits_expires_at'), // When lnbitsInvoice expires
  lnbitsAmountSats: pgInteger('lnbits_amount_sats'), // Sats amount for display (from LNbits' fiat conversion)
  userMarkedPaidAt: timestamp('user_marked_paid_at'),
  payerName: varchar('payer_name', { length: 255 }), // Name of payer if different from attendee
  paidAt: timestamp('paid_at'),
  paidByAdminId: uuid('paid_by_admin_id'),
  adminNote: pgText('admin_note'),
  reminderSentAt: timestamp('reminder_sent_at'), // When payment reminder email was sent
  // Where the money was taken: 'presale' (online/admin, the default) or 'door'
  // (recorded by staff on the door check-in screen). Splits pre-sale vs door revenue.
  source: varchar('source', { length: 20 }).notNull().default('presale'),
  // Door tender used, for the end-of-night cash-up. Null for pre-sale payments.
  // 'guest' is a zero-amount comp entry and carries no revenue.
  method: varchar('method', { length: 20 }),
  createdAt: timestamp('created_at').notNull(),
  updatedAt: timestamp('updated_at').notNull(),
});

// Idempotency records for door check-in actions (see sqliteIdempotencyKeys).
export const pgIdempotencyKeys = pgTable('idempotency_keys', {
  key: varchar('key', { length: 128 }).primaryKey(),
  scope: varchar('scope', { length: 64 }).notNull(),
  result: pgText('result').notNull(),
  undoState: pgText('undo_state'),
  undoneAt: timestamp('undone_at'),
  createdAt: timestamp('created_at').notNull(),
});

// Payment Options Configuration Table (global settings)
export const pgPaymentOptions = pgTable('payment_options', {
  id: uuid('id').primaryKey(),
  tpagoEnabled: pgInteger('tpago_enabled').notNull().default(0),
  tpagoLink: varchar('tpago_link', { length: 500 }),
  tpagoLink2: varchar('tpago_link_2', { length: 500 }),
  tpagoLink3: varchar('tpago_link_3', { length: 500 }),
  tpagoLink4: varchar('tpago_link_4', { length: 500 }),
  tpagoLink5: varchar('tpago_link_5', { length: 500 }),
  tpagoInstructions: pgText('tpago_instructions'),
  tpagoInstructionsEs: pgText('tpago_instructions_es'),
  bankTransferEnabled: pgInteger('bank_transfer_enabled').notNull().default(0),
  bankName: varchar('bank_name', { length: 255 }),
  bankAccountHolder: varchar('bank_account_holder', { length: 255 }),
  bankAccountNumber: varchar('bank_account_number', { length: 100 }),
  bankAlias: varchar('bank_alias', { length: 100 }),
  bankPhone: varchar('bank_phone', { length: 50 }),
  bankNotes: pgText('bank_notes'),
  bankNotesEs: pgText('bank_notes_es'),
  lightningEnabled: pgInteger('lightning_enabled').notNull().default(1),
  cashEnabled: pgInteger('cash_enabled').notNull().default(1),
  cashInstructions: pgText('cash_instructions'),
  cashInstructionsEs: pgText('cash_instructions_es'),
  allowDuplicateBookings: pgInteger('allow_duplicate_bookings').notNull().default(0),
  updatedAt: timestamp('updated_at').notNull(),
  updatedBy: uuid('updated_by').references(() => pgUsers.id),
});

// Event-specific payment overrides
export const pgEventPaymentOverrides = pgTable('event_payment_overrides', {
  id: uuid('id').primaryKey(),
  eventId: uuid('event_id').notNull().references(() => pgEvents.id),
  tpagoEnabled: pgInteger('tpago_enabled'),
  tpagoLink: varchar('tpago_link', { length: 500 }),
  tpagoLink2: varchar('tpago_link_2', { length: 500 }),
  tpagoLink3: varchar('tpago_link_3', { length: 500 }),
  tpagoLink4: varchar('tpago_link_4', { length: 500 }),
  tpagoLink5: varchar('tpago_link_5', { length: 500 }),
  tpagoInstructions: pgText('tpago_instructions'),
  tpagoInstructionsEs: pgText('tpago_instructions_es'),
  bankTransferEnabled: pgInteger('bank_transfer_enabled'),
  bankName: varchar('bank_name', { length: 255 }),
  bankAccountHolder: varchar('bank_account_holder', { length: 255 }),
  bankAccountNumber: varchar('bank_account_number', { length: 100 }),
  bankAlias: varchar('bank_alias', { length: 100 }),
  bankPhone: varchar('bank_phone', { length: 50 }),
  bankNotes: pgText('bank_notes'),
  bankNotesEs: pgText('bank_notes_es'),
  lightningEnabled: pgInteger('lightning_enabled'),
  cashEnabled: pgInteger('cash_enabled'),
  cashInstructions: pgText('cash_instructions'),
  cashInstructionsEs: pgText('cash_instructions_es'),
  createdAt: timestamp('created_at').notNull(),
  updatedAt: timestamp('updated_at').notNull(),
});

export const pgContacts = pgTable('contacts', {
  id: uuid('id').primaryKey(),
  name: varchar('name', { length: 255 }).notNull(),
  email: varchar('email', { length: 255 }).notNull(),
  message: pgText('message').notNull(),
  status: varchar('status', { length: 20 }).notNull().default('new'),
  createdAt: timestamp('created_at').notNull(),
});

export const pgEmailSubscribers = pgTable('email_subscribers', {
  id: uuid('id').primaryKey(),
  email: varchar('email', { length: 255 }).notNull().unique(),
  name: varchar('name', { length: 255 }),
  status: varchar('status', { length: 20 }).notNull().default('active'),
  createdAt: timestamp('created_at').notNull(),
});

export const pgMedia = pgTable('media', {
  id: uuid('id').primaryKey(),
  fileUrl: varchar('file_url', { length: 500 }).notNull(),
  type: varchar('type', { length: 20 }).notNull(),
  relatedId: uuid('related_id'),
  relatedType: varchar('related_type', { length: 50 }),
  createdAt: timestamp('created_at').notNull(),
});

export const pgAuditLogs = pgTable('audit_logs', {
  id: uuid('id').primaryKey(),
  userId: uuid('user_id').references(() => pgUsers.id),
  action: varchar('action', { length: 100 }).notNull(),
  target: varchar('target', { length: 100 }),
  targetId: uuid('target_id'),
  details: pgText('details'),
  timestamp: timestamp('timestamp').notNull(),
});

export const pgEmailTemplates = pgTable('email_templates', {
  id: uuid('id').primaryKey(),
  name: varchar('name', { length: 255 }).notNull().unique(),
  slug: varchar('slug', { length: 100 }).notNull().unique(),
  subject: varchar('subject', { length: 500 }).notNull(),
  subjectEs: varchar('subject_es', { length: 500 }),
  bodyHtml: pgText('body_html').notNull(),
  bodyHtmlEs: pgText('body_html_es'),
  bodyText: pgText('body_text'),
  bodyTextEs: pgText('body_text_es'),
  description: pgText('description'),
  variables: pgText('variables'), // JSON array of available variables
  isSystem: pgInteger('is_system').notNull().default(0),
  isActive: pgInteger('is_active').notNull().default(1),
  createdAt: timestamp('created_at').notNull(),
  updatedAt: timestamp('updated_at').notNull(),
});

export const pgEmailLogs = pgTable('email_logs', {
  id: uuid('id').primaryKey(),
  templateId: uuid('template_id').references(() => pgEmailTemplates.id),
  eventId: uuid('event_id').references(() => pgEvents.id),
  recipientEmail: varchar('recipient_email', { length: 255 }).notNull(),
  recipientName: varchar('recipient_name', { length: 255 }),
  subject: varchar('subject', { length: 500 }).notNull(),
  bodyHtml: pgText('body_html'),
  status: varchar('status', { length: 20 }).notNull().default('pending'),
  errorMessage: pgText('error_message'),
  sentAt: timestamp('sent_at'),
  sentBy: uuid('sent_by').references(() => pgUsers.id),
  createdAt: timestamp('created_at').notNull(),
  resendAttempts: pgInteger('resend_attempts').notNull().default(0),
  lastResentAt: timestamp('last_resent_at'),
});

export const pgEmailSettings = pgTable('email_settings', {
  id: uuid('id').primaryKey(),
  key: varchar('key', { length: 100 }).notNull().unique(),
  value: pgText('value').notNull(),
  updatedAt: timestamp('updated_at').notNull(),
});

// Durable email queue. Jobs survive process restarts; a startup recovery step
// resets any 'processing' rows back to 'pending'.
export const pgEmailQueue = pgTable('email_queue', {
  id: uuid('id').primaryKey(),
  params: pgText('params').notNull(), // JSON-encoded TemplateEmailJobParams
  status: varchar('status', { length: 20 }).notNull().default('pending'),
  attempts: pgInteger('attempts').notNull().default(0),
  lastError: pgText('last_error'),
  createdAt: timestamp('created_at').notNull(),
  processedAt: timestamp('processed_at'),
});

// Legal Pages table for admin-editable legal content
export const pgLegalPages = pgTable('legal_pages', {
  id: uuid('id').primaryKey(),
  slug: varchar('slug', { length: 100 }).notNull().unique(),
  title: varchar('title', { length: 255 }).notNull(), // English title
  titleEs: varchar('title_es', { length: 255 }), // Spanish title
  contentText: pgText('content_text').notNull(), // Plain text edited by admin (English)
  contentTextEs: pgText('content_text_es'), // Plain text edited by admin (Spanish)
  contentMarkdown: pgText('content_markdown').notNull(), // Generated markdown for public display (English)
  contentMarkdownEs: pgText('content_markdown_es'), // Generated markdown for public display (Spanish)
  updatedAt: timestamp('updated_at').notNull(),
  updatedBy: uuid('updated_by').references(() => pgUsers.id),
  createdAt: timestamp('created_at').notNull(),
});

// FAQ questions table (admin-managed)
export const pgFaqQuestions = pgTable('faq_questions', {
  id: uuid('id').primaryKey(),
  question: pgText('question').notNull(),
  questionEs: pgText('question_es'),
  answer: pgText('answer').notNull(),
  answerEs: pgText('answer_es'),
  enabled: pgInteger('enabled').notNull().default(1),
  showOnHomepage: pgInteger('show_on_homepage').notNull().default(0),
  rank: pgInteger('rank').notNull().default(0),
  createdAt: timestamp('created_at').notNull(),
  updatedAt: timestamp('updated_at').notNull(),
});

// Legal Settings table for legal page placeholder values
export const pgLegalSettings = pgTable('legal_settings', {
  id: uuid('id').primaryKey(),
  companyName: varchar('company_name', { length: 255 }),
  legalEntityName: varchar('legal_entity_name', { length: 255 }),
  rucNumber: varchar('ruc_number', { length: 50 }),
  companyAddress: pgText('company_address'),
  companyCity: varchar('company_city', { length: 100 }),
  companyCountry: varchar('company_country', { length: 100 }),
  supportEmail: varchar('support_email', { length: 255 }),
  legalEmail: varchar('legal_email', { length: 255 }),
  governingLaw: varchar('governing_law', { length: 255 }),
  jurisdictionCity: varchar('jurisdiction_city', { length: 100 }),
  updatedAt: timestamp('updated_at').notNull(),
  updatedBy: uuid('updated_by').references(() => pgUsers.id),
});

// Site Settings table for global website configuration
export const pgSiteSettings = pgTable('site_settings', {
  id: uuid('id').primaryKey(),
  // Timezone configuration
  timezone: varchar('timezone', { length: 100 }).notNull().default('America/Asuncion'),
  // Site info
  siteName: varchar('site_name', { length: 255 }).notNull().default('Spanglish'),
  siteDescription: pgText('site_description'),
  siteDescriptionEs: pgText('site_description_es'),
  // Contact info
  contactEmail: varchar('contact_email', { length: 255 }),
  contactPhone: varchar('contact_phone', { length: 50 }),
  // Social links
  facebookUrl: varchar('facebook_url', { length: 500 }),
  instagramUrl: varchar('instagram_url', { length: 500 }),
  twitterUrl: varchar('twitter_url', { length: 500 }),
  linkedinUrl: varchar('linkedin_url', { length: 500 }),
  // Featured event - manually promoted event shown on homepage/linktree
  featuredEventId: uuid('featured_event_id').references(() => pgEvents.id),
  // Other settings
  maintenanceMode: pgInteger('maintenance_mode').notNull().default(0),
  maintenanceMessage: pgText('maintenance_message'),
  maintenanceMessageEs: pgText('maintenance_message_es'),
  // Metadata
  updatedAt: timestamp('updated_at').notNull(),
  updatedBy: uuid('updated_by').references(() => pgUsers.id),
});

// Export the appropriate schema based on DB_TYPE
export const users = dbType === 'postgres' ? pgUsers : sqliteUsers;
export const events = dbType === 'postgres' ? pgEvents : sqliteEvents;
export const eventSlugAliases = dbType === 'postgres' ? pgEventSlugAliases : sqliteEventSlugAliases;
export const tickets = dbType === 'postgres' ? pgTickets : sqliteTickets;
export const payments = dbType === 'postgres' ? pgPayments : sqlitePayments;
export const idempotencyKeys = dbType === 'postgres' ? pgIdempotencyKeys : sqliteIdempotencyKeys;
export const contacts = dbType === 'postgres' ? pgContacts : sqliteContacts;
export const emailSubscribers = dbType === 'postgres' ? pgEmailSubscribers : sqliteEmailSubscribers;
export const media = dbType === 'postgres' ? pgMedia : sqliteMedia;
export const auditLogs = dbType === 'postgres' ? pgAuditLogs : sqliteAuditLogs;
export const emailTemplates = dbType === 'postgres' ? pgEmailTemplates : sqliteEmailTemplates;
export const emailLogs = dbType === 'postgres' ? pgEmailLogs : sqliteEmailLogs;
export const emailSettings = dbType === 'postgres' ? pgEmailSettings : sqliteEmailSettings;
export const emailQueue = dbType === 'postgres' ? pgEmailQueue : sqliteEmailQueue;
export const paymentOptions = dbType === 'postgres' ? pgPaymentOptions : sqlitePaymentOptions;
export const eventPaymentOverrides = dbType === 'postgres' ? pgEventPaymentOverrides : sqliteEventPaymentOverrides;
export const magicLinkTokens = dbType === 'postgres' ? pgMagicLinkTokens : sqliteMagicLinkTokens;
export const userSessions = dbType === 'postgres' ? pgUserSessions : sqliteUserSessions;
export const invoices = dbType === 'postgres' ? pgInvoices : sqliteInvoices;
export const legalSettings = dbType === 'postgres' ? pgLegalSettings : sqliteLegalSettings;
export const siteSettings = dbType === 'postgres' ? pgSiteSettings : sqliteSiteSettings;
export const legalPages = dbType === 'postgres' ? pgLegalPages : sqliteLegalPages;
export const faqQuestions = dbType === 'postgres' ? pgFaqQuestions : sqliteFaqQuestions;

// Type exports
export type User = typeof sqliteUsers.$inferSelect;
export type NewUser = typeof sqliteUsers.$inferInsert;
export type Event = typeof sqliteEvents.$inferSelect;
export type NewEvent = typeof sqliteEvents.$inferInsert;
export type Ticket = typeof sqliteTickets.$inferSelect;
export type NewTicket = typeof sqliteTickets.$inferInsert;
export type Payment = typeof sqlitePayments.$inferSelect;
export type NewPayment = typeof sqlitePayments.$inferInsert;
export type Contact = typeof sqliteContacts.$inferSelect;
export type NewContact = typeof sqliteContacts.$inferInsert;
export type EmailTemplate = typeof sqliteEmailTemplates.$inferSelect;
export type NewEmailTemplate = typeof sqliteEmailTemplates.$inferInsert;
export type EmailLog = typeof sqliteEmailLogs.$inferSelect;
export type NewEmailLog = typeof sqliteEmailLogs.$inferInsert;
export type PaymentOptions = typeof sqlitePaymentOptions.$inferSelect;
export type NewPaymentOptions = typeof sqlitePaymentOptions.$inferInsert;
export type EventPaymentOverride = typeof sqliteEventPaymentOverrides.$inferSelect;
export type NewEventPaymentOverride = typeof sqliteEventPaymentOverrides.$inferInsert;
export type MagicLinkToken = typeof sqliteMagicLinkTokens.$inferSelect;
export type NewMagicLinkToken = typeof sqliteMagicLinkTokens.$inferInsert;
export type UserSession = typeof sqliteUserSessions.$inferSelect;
export type NewUserSession = typeof sqliteUserSessions.$inferInsert;
export type Invoice = typeof sqliteInvoices.$inferSelect;
export type NewInvoice = typeof sqliteInvoices.$inferInsert;
export type SiteSettings = typeof sqliteSiteSettings.$inferSelect;
export type NewSiteSettings = typeof sqliteSiteSettings.$inferInsert;
export type LegalPage = typeof sqliteLegalPages.$inferSelect;
export type NewLegalPage = typeof sqliteLegalPages.$inferInsert;
export type FaqQuestion = typeof sqliteFaqQuestions.$inferSelect;
export type NewFaqQuestion = typeof sqliteFaqQuestions.$inferInsert;
export type LegalSettings = typeof sqliteLegalSettings.$inferSelect;
export type NewLegalSettings = typeof sqliteLegalSettings.$inferInsert;