import {
  boolean,
  doublePrecision,
  integer,
  jsonb,
  pgTable,
  text,
  timestamp,
  uniqueIndex
} from 'drizzle-orm/pg-core';

export const users = pgTable(
  'users',
  {
    id: text('id').primaryKey(),
    name: text('name').notNull(),
    email: text('email').notNull(),
    passwordHash: text('password_hash').notNull(),
    systemRole: text('system_role').default('user').notNull(),
    image: text('image'),
    activeOrganizationId: text('active_organization_id'),
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull()
  },
  (table) => ({
    emailIdx: uniqueIndex('users_email_idx').on(table.email)
  })
);

export const organizations = pgTable(
  'organizations',
  {
    id: text('id').primaryKey(),
    name: text('name').notNull(),
    slug: text('slug').notNull(),
    imageUrl: text('image_url'),
    plan: text('plan').default('free').notNull(),
    createdBy: text('created_by').notNull(),
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull()
  },
  (table) => ({
    slugIdx: uniqueIndex('organizations_slug_idx').on(table.slug)
  })
);

export const memberships = pgTable('memberships', {
  id: text('id').primaryKey(),
  userId: text('user_id').notNull(),
  organizationId: text('organization_id').notNull(),
  role: text('role').default('user').notNull(),
  businessRole: text('business_role').default('sales_support').notNull(),
  permissions: text('permissions').array().default([]).notNull(),
  branchScopeIds: text('branch_scope_ids').array().default([]).notNull(),
  productTypeScopeIds: text('product_type_scope_ids').array().default([]).notNull(),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull()
});

export const setupRuns = pgTable('setup_runs', {
  id: text('id').primaryKey(),
  status: text('status').default('not_started').notNull(),
  mode: text('mode').default('production').notNull(),
  targetOrganizationId: text('target_organization_id'),
  startedBy: text('started_by').notNull(),
  completedBy: text('completed_by'),
  startedAt: timestamp('started_at', { withTimezone: true }).defaultNow().notNull(),
  completedAt: timestamp('completed_at', { withTimezone: true }),
  lastError: text('last_error'),
  metadata: jsonb('metadata').$type<Record<string, unknown> | null>(),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull()
});

export const setupRunSteps = pgTable(
  'setup_run_steps',
  {
    id: text('id').primaryKey(),
    setupRunId: text('setup_run_id').notNull(),
    stepKey: text('step_key').notNull(),
    status: text('status').default('not_started').notNull(),
    inputHash: text('input_hash'),
    outputJson: jsonb('output_json').$type<Record<string, unknown> | null>(),
    errorsJson: jsonb('errors_json').$type<unknown[] | null>(),
    warningsJson: jsonb('warnings_json').$type<unknown[] | null>(),
    startedAt: timestamp('started_at', { withTimezone: true }),
    completedAt: timestamp('completed_at', { withTimezone: true }),
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull()
  },
  (table) => ({
    setupRunStepIdx: uniqueIndex('setup_run_steps_run_step_idx').on(
      table.setupRunId,
      table.stepKey
    )
  })
);

export const seedManifests = pgTable('seed_manifests', {
  id: text('id').primaryKey(),
  setupRunId: text('setup_run_id'),
  organizationId: text('organization_id'),
  name: text('name').notNull(),
  version: text('version').notNull(),
  type: text('type').notNull(),
  checksum: text('checksum').notNull(),
  status: text('status').default('pending').notNull(),
  source: text('source').notNull(),
  appliedBy: text('applied_by'),
  appliedAt: timestamp('applied_at', { withTimezone: true }),
  reportJson: jsonb('report_json').$type<Record<string, unknown> | null>(),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull()
});

export const seedManifestItems = pgTable(
  'seed_manifest_items',
  {
    id: text('id').primaryKey(),
    seedManifestId: text('seed_manifest_id').notNull(),
    itemKey: text('item_key').notNull(),
    sourceFile: text('source_file').notNull(),
    checksum: text('checksum').notNull(),
    status: text('status').default('pending').notNull(),
    importedCount: integer('imported_count').default(0).notNull(),
    updatedCount: integer('updated_count').default(0).notNull(),
    skippedCount: integer('skipped_count').default(0).notNull(),
    errorCount: integer('error_count').default(0).notNull(),
    warningCount: integer('warning_count').default(0).notNull(),
    reportJson: jsonb('report_json').$type<Record<string, unknown> | null>(),
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull()
  },
  (table) => ({
    seedManifestItemIdx: uniqueIndex('seed_manifest_items_manifest_item_idx').on(
      table.seedManifestId,
      table.itemKey
    )
  })
);

export const crmRoleProfiles = pgTable(
  'crm_role_profiles',
  {
    id: text('id').primaryKey(),
    organizationId: text('organization_id').notNull(),
    code: text('code').notNull(),
    name: text('name').notNull(),
    description: text('description'),
    permissions: text('permissions').array().default([]).notNull(),
    branchScopeMode: text('branch_scope_mode').default('assigned').notNull(),
    productScopeMode: text('product_scope_mode').default('assigned').notNull(),
    ownershipScope: text('ownership_scope').default('own').notNull(),
    approvalAuthority: text('approval_authority').default('none').notNull(),
    isSystem: boolean('is_system').default(false).notNull(),
    isActive: boolean('is_active').default(true).notNull(),
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
    deletedAt: timestamp('deleted_at', { withTimezone: true }),
    createdBy: text('created_by').notNull(),
    updatedBy: text('updated_by').notNull()
  },
  (table) => ({
    organizationRoleCodeIdx: uniqueIndex('crm_role_profiles_org_code_idx').on(
      table.organizationId,
      table.code
    )
  })
);

export const crmUserRoleAssignments = pgTable(
  'crm_user_role_assignments',
  {
    id: text('id').primaryKey(),
    organizationId: text('organization_id').notNull(),
    userId: text('user_id').notNull(),
    roleProfileId: text('role_profile_id').notNull(),
    branchScopeMode: text('branch_scope_mode').default('inherit').notNull(),
    branchScopeIds: text('branch_scope_ids').array().default([]).notNull(),
    productTypeScopeMode: text('product_type_scope_mode').default('inherit').notNull(),
    productTypeScopeIds: text('product_type_scope_ids').array().default([]).notNull(),
    isPrimary: boolean('is_primary').default(false).notNull(),
    isActive: boolean('is_active').default(true).notNull(),
    assignedBy: text('assigned_by').notNull(),
    assignedAt: timestamp('assigned_at', { withTimezone: true }).defaultNow().notNull(),
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
    deletedAt: timestamp('deleted_at', { withTimezone: true })
  },
  (table) => ({
    organizationUserRoleProfileIdx: uniqueIndex('crm_user_role_assignments_org_user_role_idx').on(
      table.organizationId,
      table.userId,
      table.roleProfileId
    )
  })
);

export const products = pgTable('products', {
  id: integer('id').primaryKey().generatedAlwaysAsIdentity(),
  organizationId: text('organization_id').notNull(),
  name: text('name').notNull(),
  category: text('category').notNull(),
  description: text('description').notNull(),
  photoUrl: text('photo_url').notNull(),
  price: doublePrecision('price').notNull(),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull()
});

export const msOptions = pgTable(
  'ms_options',
  {
    id: text('id').primaryKey(),
    organizationId: text('organization_id').notNull(),
    category: text('category').notNull(),
    code: text('code').notNull(),
    label: text('label').notNull(),
    value: text('value'),
    parentId: text('parent_id'),
    sortOrder: integer('sort_order').default(0).notNull(),
    isActive: boolean('is_active').default(true).notNull(),
    metadata: jsonb('metadata'),
    deletedAt: timestamp('deleted_at', { withTimezone: true }),
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull()
  },
  (table) => ({
    organizationCategoryCodeIdx: uniqueIndex('ms_options_org_category_code_idx').on(
      table.organizationId,
      table.category,
      table.code
    )
  })
);

export const documentSequences = pgTable(
  'document_sequences',
  {
    id: text('id').primaryKey(),
    organizationId: text('organization_id').notNull(),
    branchId: text('branch_id').default('').notNull(),
    productType: text('product_type').default('all').notNull(),
    documentType: text('document_type').notNull(),
    prefix: text('prefix').notNull(),
    period: text('period').notNull(),
    currentNumber: integer('current_number').default(0).notNull(),
    paddingLength: integer('padding_length').default(3).notNull(),
    format: text('format').default('{prefix}{period}-{running}').notNull(),
    resetPolicy: text('reset_policy').default('period').notNull(),
    isActive: boolean('is_active').default(true).notNull(),
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull()
  },
  (table) => ({
    organizationBranchProductDocumentPeriodIdx: uniqueIndex(
      'document_sequences_org_branch_product_doc_period_idx'
    ).on(
      table.organizationId,
      table.branchId,
      table.productType,
      table.documentType,
      table.period
    )
  })
);

export const emailConfigurations = pgTable(
  'email_configurations',
  {
    id: text('id').primaryKey(),
    organizationId: text('organization_id').notNull(),
    providerType: text('provider_type').default('smtp').notNull(),
    name: text('name').notNull(),
    host: text('host').notNull(),
    port: integer('port').default(587).notNull(),
    secure: boolean('secure').default(false).notNull(),
    username: text('username'),
    passwordEncrypted: text('password_encrypted'),
    fromEmail: text('from_email').notNull(),
    fromName: text('from_name'),
    replyToEmail: text('reply_to_email'),
    isDefault: boolean('is_default').default(false).notNull(),
    isActive: boolean('is_active').default(true).notNull(),
    lastTestStatus: text('last_test_status').default('not_tested').notNull(),
    lastTestedAt: timestamp('last_tested_at', { withTimezone: true }),
    lastTestError: text('last_test_error'),
    createdBy: text('created_by').notNull(),
    updatedBy: text('updated_by').notNull(),
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull()
  },
  (table) => ({
    organizationNameIdx: uniqueIndex('email_configurations_org_name_idx').on(
      table.organizationId,
      table.name
    )
  })
);

export const trAuditLogs = pgTable('tr_audit_logs', {
  id: text('id').primaryKey(),
  organizationId: text('organization_id').notNull(),
  branchId: text('branch_id'),
  userId: text('user_id').notNull(),
  entityType: text('entity_type').notNull(),
  entityId: text('entity_id').notNull(),
  action: text('action').notNull(),
  beforeData: jsonb('before_data'),
  afterData: jsonb('after_data'),
  requestId: text('request_id'),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull()
});

export const appNotificationEvents = pgTable(
  'app_notification_events',
  {
    id: text('id').primaryKey(),
    organizationId: text('organization_id').notNull(),
    eventType: text('event_type').notNull(),
    entityType: text('entity_type').notNull(),
    entityId: text('entity_id').notNull(),
    actorUserId: text('actor_user_id'),
    payload: jsonb('payload'),
    dedupeKey: text('dedupe_key'),
    status: text('status').default('pending').notNull(),
    lastError: text('last_error'),
    publishedAt: timestamp('published_at', { withTimezone: true }).defaultNow().notNull(),
    processedAt: timestamp('processed_at', { withTimezone: true }),
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull()
  },
  (table) => ({
    organizationDedupeIdx: uniqueIndex('app_notification_events_org_dedupe_idx').on(
      table.organizationId,
      table.dedupeKey
    )
  })
);

export const appNotifications = pgTable(
  'app_notifications',
  {
    id: text('id').primaryKey(),
    organizationId: text('organization_id').notNull(),
    recipientUserId: text('recipient_user_id').notNull(),
    eventId: text('event_id').notNull(),
    title: text('title').notNull(),
    body: text('body').notNull(),
    linkUrl: text('link_url'),
    severity: text('severity').default('info').notNull(),
    status: text('status').default('unread').notNull(),
    readAt: timestamp('read_at', { withTimezone: true }),
    archivedAt: timestamp('archived_at', { withTimezone: true }),
    metadata: jsonb('metadata'),
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull()
  },
  (table) => ({
    recipientEventIdx: uniqueIndex('app_notifications_recipient_event_idx').on(
      table.recipientUserId,
      table.eventId
    )
  })
);

export const appNotificationTemplates = pgTable(
  'app_notification_templates',
  {
    id: text('id').primaryKey(),
    organizationId: text('organization_id').notNull(),
    eventType: text('event_type').notNull(),
    code: text('code').default('').notNull(),
    name: text('name').default('').notNull(),
    channel: text('channel').notNull(),
    subjectTemplate: text('subject_template'),
    titleTemplate: text('title_template').notNull(),
    bodyTemplate: text('body_template').notNull(),
    bodyFormat: text('body_format').default('plain').notNull(),
    linkTemplate: text('link_template'),
    language: text('language').default('th').notNull(),
    variables: jsonb('variables'),
    version: integer('version').default(1).notNull(),
    isActive: boolean('is_active').default(true).notNull(),
    metadata: jsonb('metadata'),
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
    deletedAt: timestamp('deleted_at', { withTimezone: true }),
    createdBy: text('created_by').notNull(),
    updatedBy: text('updated_by').notNull()
  },
  (table) => ({
    organizationEventChannelIdx: uniqueIndex('app_notification_templates_org_event_channel_idx').on(
      table.organizationId,
      table.eventType,
      table.channel
    )
  })
);

export const appNotificationDispatches = pgTable(
  'app_notification_dispatches',
  {
    id: text('id').primaryKey(),
    organizationId: text('organization_id').notNull(),
    eventId: text('event_id').notNull(),
    templateId: text('template_id'),
    entityType: text('entity_type').notNull(),
    entityId: text('entity_id').notNull(),
    channel: text('channel').notNull(),
    providerKey: text('provider_key').notNull(),
    status: text('status').default('pending').notNull(),
    recipientTo: jsonb('recipient_to').notNull(),
    recipientCc: jsonb('recipient_cc'),
    recipientBcc: jsonb('recipient_bcc'),
    replyTo: text('reply_to'),
    subject: text('subject').notNull(),
    bodyText: text('body_text').notNull(),
    bodyHtml: text('body_html'),
    attachments: jsonb('attachments'),
    recipientUserId: text('recipient_user_id'),
    recipientAddress: text('recipient_address'),
    requestedBy: text('requested_by').notNull(),
    metadata: jsonb('metadata'),
    lastError: text('last_error'),
    retryCount: integer('retry_count').default(0).notNull(),
    maxRetryCount: integer('max_retry_count').default(3).notNull(),
    lastAttemptAt: timestamp('last_attempt_at', { withTimezone: true }),
    sentAt: timestamp('sent_at', { withTimezone: true }),
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull()
  },
  (table) => ({
    organizationEventChannelRecipientIdx: uniqueIndex(
      'app_notification_dispatches_org_event_channel_recipient_idx'
    ).on(table.organizationId, table.eventId, table.channel, table.recipientAddress)
  })
);

export const appNotificationDeliveries = pgTable('app_notification_deliveries', {
  id: text('id').primaryKey(),
  organizationId: text('organization_id').notNull(),
  notificationId: text('notification_id').notNull(),
  channel: text('channel').notNull(),
  recipientAddress: text('recipient_address'),
  status: text('status').default('pending').notNull(),
  attemptCount: integer('attempt_count').default(0).notNull(),
  lastError: text('last_error'),
  sentAt: timestamp('sent_at', { withTimezone: true }),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull()
});

export const crmCustomers = pgTable(
  'crm_customers',
  {
    id: text('id').primaryKey(),
    organizationId: text('organization_id').notNull(),
    branchId: text('branch_id'),
    code: text('code').notNull(),
    name: text('name').notNull(),
    abbr: text('abbr'),
    taxId: text('tax_id'),
    customerType: text('customer_type').notNull(),
    customerStatus: text('customer_status').notNull(),
    address: text('address'),
    province: text('province'),
    district: text('district'),
    subDistrict: text('sub_district'),
    postalCode: text('postal_code'),
    country: text('country'),
    phone: text('phone'),
    fax: text('fax'),
    email: text('email'),
    website: text('website'),
    leadChannel: text('lead_channel'),
    customerGroup: text('customer_group'),
    customerSubGroup: text('customer_sub_group'),
    ownerUserId: text('owner_user_id'),
    ownerAssignedAt: timestamp('owner_assigned_at', { withTimezone: true }),
    ownerAssignedBy: text('owner_assigned_by'),
    notes: text('notes'),
    isActive: boolean('is_active').default(true).notNull(),
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
    deletedAt: timestamp('deleted_at', { withTimezone: true }),
    createdBy: text('created_by').notNull(),
    updatedBy: text('updated_by').notNull()
  },
  (table) => ({
    organizationCodeIdx: uniqueIndex('crm_customers_org_code_idx').on(
      table.organizationId,
      table.code
    )
  })
);

export const crmCustomerOwnerHistory = pgTable('crm_customer_owner_history', {
  id: text('id').primaryKey(),
  organizationId: text('organization_id').notNull(),
  customerId: text('customer_id').notNull(),
  oldOwnerUserId: text('old_owner_user_id'),
  newOwnerUserId: text('new_owner_user_id'),
  changedBy: text('changed_by').notNull(),
  changedAt: timestamp('changed_at', { withTimezone: true }).defaultNow().notNull(),
  remark: text('remark'),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
  deletedAt: timestamp('deleted_at', { withTimezone: true })
});

export const crmCustomerContacts = pgTable('crm_customer_contacts', {
  id: text('id').primaryKey(),
  organizationId: text('organization_id').notNull(),
  customerId: text('customer_id').notNull(),
  name: text('name').notNull(),
  position: text('position'),
  department: text('department'),
  phone: text('phone'),
  mobile: text('mobile'),
  email: text('email'),
  isPrimary: boolean('is_primary').default(false).notNull(),
  notes: text('notes'),
  isActive: boolean('is_active').default(true).notNull(),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
  deletedAt: timestamp('deleted_at', { withTimezone: true }),
  createdBy: text('created_by').notNull(),
  updatedBy: text('updated_by').notNull()
});

export const crmLeads = pgTable(
  'crm_leads',
  {
    id: text('id').primaryKey(),
    organizationId: text('organization_id').notNull(),
    branchId: text('branch_id'),
    code: text('code').notNull(),
    customerId: text('customer_id'),
    contactId: text('contact_id'),
    description: text('description'),
    projectName: text('project_name'),
    projectLocation: text('project_location'),
    leadChannel: text('lead_channel'),
    productType: text('product_type'),
    priority: text('priority'),
    estimatedValue: doublePrecision('estimated_value'),
    awarenessId: text('awareness_id'),
    status: text('status').notNull(),
    followupStatus: text('followup_status'),
    lostReason: text('lost_reason'),
    outcome: text('outcome').default('open').notNull(),
    ownerMarketingUserId: text('owner_marketing_user_id'),
    assignedSalesOwnerId: text('assigned_sales_owner_id'),
    assignedAt: timestamp('assigned_at', { withTimezone: true }),
    assignedBy: text('assigned_by'),
    assignmentRemark: text('assignment_remark'),
    createdBy: text('created_by').notNull(),
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
    deletedAt: timestamp('deleted_at', { withTimezone: true })
  },
  (table) => ({
    organizationCodeIdx: uniqueIndex('crm_leads_org_code_idx').on(table.organizationId, table.code)
  })
);

export const crmContactShares = pgTable(
  'crm_contact_shares',
  {
    id: text('id').primaryKey(),
    organizationId: text('organization_id').notNull(),
    contactId: text('contact_id').notNull(),
    sharedToUserId: text('shared_to_user_id').notNull(),
    sharedByUserId: text('shared_by_user_id').notNull(),
    sharedAt: timestamp('shared_at', { withTimezone: true }).defaultNow().notNull(),
    isActive: boolean('is_active').default(true).notNull(),
    remark: text('remark'),
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
    deletedAt: timestamp('deleted_at', { withTimezone: true })
  },
  (table) => ({
    contactSharedUserIdx: uniqueIndex('crm_contact_shares_org_contact_shared_user_idx').on(
      table.organizationId,
      table.contactId,
      table.sharedToUserId
    )
  })
);

export const crmOpportunities = pgTable(
  'crm_opportunities',
  {
    id: text('id').primaryKey(),
    organizationId: text('organization_id').notNull(),
    branchId: text('branch_id'),
    leadId: text('lead_id'),
    code: text('code').notNull(),
    customerId: text('customer_id').notNull(),
    contactId: text('contact_id'),
    title: text('title').notNull(),
    description: text('description'),
    requirement: text('requirement'),
    projectName: text('project_name'),
    projectLocation: text('project_location'),
    productType: text('product_type').notNull(),
    status: text('status').notNull(),
    outcomeStatus: text('outcome_status').default('open').notNull(),
    priority: text('priority').notNull(),
    leadChannel: text('lead_channel'),
    estimatedValue: doublePrecision('estimated_value'),
    chancePercent: integer('chance_percent'),
    expectedCloseDate: timestamp('expected_close_date', { withTimezone: true }),
    projectCloseDate: timestamp('project_close_date', { withTimezone: true }),
    deliveryDate: timestamp('delivery_date', { withTimezone: true }),
    competitor: text('competitor'),
    source: text('source'),
    notes: text('notes'),
    isHotProject: boolean('is_hot_project').default(false).notNull(),
    hotProjectAutoSuggested: boolean('hot_project_auto_suggested').default(false).notNull(),
    hotProjectManuallyOverridden: boolean('hot_project_manually_overridden')
      .default(false)
      .notNull(),
    isActive: boolean('is_active').default(true).notNull(),
    pipelineStage: text('pipeline_stage').default('lead').notNull(),
    closedAt: timestamp('closed_at', { withTimezone: true }),
    closedWonAt: timestamp('closed_won_at', { withTimezone: true }),
    closedLostAt: timestamp('closed_lost_at', { withTimezone: true }),
    closedByUserId: text('closed_by_user_id'),
    poNumber: text('po_number'),
    poDate: timestamp('po_date', { withTimezone: true }),
    poAmount: doublePrecision('po_amount'),
    poCurrency: text('po_currency'),
    lostReason: text('lost_reason'),
    lostDetail: text('lost_detail'),
    lostCompetitor: text('lost_competitor'),
    lostRemark: text('lost_remark'),
    cancelReason: text('cancel_reason'),
    noQuotationReason: text('no_quotation_reason'),
    assignedToUserId: text('assigned_to_user_id'),
    assignedAt: timestamp('assigned_at', { withTimezone: true }),
    assignedBy: text('assigned_by'),
    assignmentRemark: text('assignment_remark'),
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
    deletedAt: timestamp('deleted_at', { withTimezone: true }),
    createdBy: text('created_by').notNull(),
    updatedBy: text('updated_by').notNull()
  },
  (table) => ({
    organizationCodeIdx: uniqueIndex('crm_opportunities_org_code_idx').on(
      table.organizationId,
      table.code
    )
  })
);

export const crmOpportunityFollowups = pgTable('crm_opportunity_followups', {
  id: text('id').primaryKey(),
  organizationId: text('organization_id').notNull(),
  opportunityId: text('opportunity_id').notNull(),
  followupDate: timestamp('followup_date', { withTimezone: true }).notNull(),
  followupType: text('followup_type').notNull(),
  contactId: text('contact_id'),
  outcome: text('outcome'),
  notes: text('notes'),
  nextFollowupDate: timestamp('next_followup_date', { withTimezone: true }),
  nextAction: text('next_action'),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
  deletedAt: timestamp('deleted_at', { withTimezone: true }),
  createdBy: text('created_by').notNull(),
  updatedBy: text('updated_by').notNull()
});

export const crmOpportunityCustomers = pgTable('crm_opportunity_customers', {
  id: text('id').primaryKey(),
  organizationId: text('organization_id').notNull(),
  opportunityId: text('opportunity_id').notNull(),
  customerId: text('customer_id').notNull(),
  role: text('role').notNull(),
  remark: text('remark'),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
  deletedAt: timestamp('deleted_at', { withTimezone: true })
});

export const crmOpportunityAttachments = pgTable('crm_opportunity_attachments', {
  id: text('id').primaryKey(),
  organizationId: text('organization_id').notNull(),
  opportunityId: text('opportunity_id').notNull(),
  category: text('category').notNull(),
  fileName: text('file_name').notNull(),
  originalFileName: text('original_file_name').notNull(),
  storageProvider: text('storage_provider').notNull(),
  storageKey: text('storage_key').notNull(),
  fileSize: integer('file_size'),
  fileType: text('file_type'),
  description: text('description'),
  uploadedAt: timestamp('uploaded_at', { withTimezone: true }).defaultNow().notNull(),
  uploadedBy: text('uploaded_by').notNull(),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
  deletedAt: timestamp('deleted_at', { withTimezone: true })
});

export const crmReportDefinitions = pgTable(
  'crm_report_definitions',
  {
    id: text('id').primaryKey(),
    organizationId: text('organization_id').notNull(),
    code: text('code').notNull(),
    name: text('name').notNull(),
    description: text('description'),
    category: text('category').notNull(),
    isSystem: boolean('is_system').default(true).notNull(),
    isActive: boolean('is_active').default(true).notNull(),
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull()
  },
  (table) => ({
    organizationCodeIdx: uniqueIndex('crm_report_definitions_org_code_idx').on(
      table.organizationId,
      table.code
    )
  })
);

export const crmQuotations = pgTable(
  'crm_quotations',
  {
    id: text('id').primaryKey(),
    organizationId: text('organization_id').notNull(),
    branchId: text('branch_id'),
    code: text('code').notNull(),
    opportunityId: text('opportunity_id'),
    customerId: text('customer_id').notNull(),
    contactId: text('contact_id'),
    quotationDate: timestamp('quotation_date', { withTimezone: true }).notNull(),
    validUntil: timestamp('valid_until', { withTimezone: true }),
    quotationType: text('quotation_type').notNull(),
    projectName: text('project_name'),
    projectLocation: text('project_location'),
    attention: text('attention'),
    reference: text('reference'),
    notes: text('notes'),
    status: text('status').notNull(),
    revision: integer('revision').default(0).notNull(),
    parentQuotationId: text('parent_quotation_id'),
    revisionRemark: text('revision_remark'),
    currency: text('currency').notNull(),
    exchangeRate: doublePrecision('exchange_rate').default(1).notNull(),
    subtotal: doublePrecision('subtotal').default(0).notNull(),
    discount: doublePrecision('discount').default(0).notNull(),
    discountType: text('discount_type'),
    taxRate: doublePrecision('tax_rate').default(0).notNull(),
    taxAmount: doublePrecision('tax_amount').default(0).notNull(),
    totalAmount: doublePrecision('total_amount').default(0).notNull(),
    chancePercent: integer('chance_percent'),
    projectCloseDate: timestamp('project_close_date', { withTimezone: true }),
    deliveryDate: timestamp('delivery_date', { withTimezone: true }),
    isHotProject: boolean('is_hot_project').default(false).notNull(),
    hotProjectAutoSuggested: boolean('hot_project_auto_suggested').default(false).notNull(),
    hotProjectManuallyOverridden: boolean('hot_project_manually_overridden')
      .default(false)
      .notNull(),
    competitor: text('competitor'),
    salesmanId: text('salesman_id'),
    isSent: boolean('is_sent').default(false).notNull(),
    sentAt: timestamp('sent_at', { withTimezone: true }),
    sentVia: text('sent_via'),
    approvedAt: timestamp('approved_at', { withTimezone: true }),
    approvedArtifactId: text('approved_artifact_id'),
    approvedPdfUrl: text('approved_pdf_url'),
    approvedSnapshot: jsonb('approved_snapshot'),
    approvedTemplateVersionId: text('approved_template_version_id'),
    acceptedAt: timestamp('accepted_at', { withTimezone: true }),
    rejectedAt: timestamp('rejected_at', { withTimezone: true }),
    rejectionReason: text('rejection_reason'),
    isActive: boolean('is_active').default(true).notNull(),
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
    deletedAt: timestamp('deleted_at', { withTimezone: true }),
    createdBy: text('created_by').notNull(),
    updatedBy: text('updated_by').notNull()
  },
  (table) => ({
    organizationCodeIdx: uniqueIndex('crm_quotations_org_code_idx').on(
      table.organizationId,
      table.code
    )
  })
);

export const crmQuotationItems = pgTable('crm_quotation_items', {
  id: text('id').primaryKey(),
  organizationId: text('organization_id').notNull(),
  quotationId: text('quotation_id').notNull(),
  itemNumber: integer('item_number').notNull(),
  productType: text('product_type').notNull(),
  description: text('description').notNull(),
  quantity: doublePrecision('quantity').default(0).notNull(),
  unit: text('unit'),
  unitPrice: doublePrecision('unit_price').default(0).notNull(),
  discount: doublePrecision('discount').default(0).notNull(),
  discountType: text('discount_type'),
  taxRate: doublePrecision('tax_rate').default(0).notNull(),
  totalPrice: doublePrecision('total_price').default(0).notNull(),
  notes: text('notes'),
  sortOrder: integer('sort_order').default(0).notNull(),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
  deletedAt: timestamp('deleted_at', { withTimezone: true })
});

export const crmQuotationCustomers = pgTable('crm_quotation_customers', {
  id: text('id').primaryKey(),
  organizationId: text('organization_id').notNull(),
  quotationId: text('quotation_id').notNull(),
  customerId: text('customer_id').notNull(),
  role: text('role').notNull(),
  isPrimary: boolean('is_primary').default(false).notNull(),
  remark: text('remark'),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
  deletedAt: timestamp('deleted_at', { withTimezone: true })
});

export const crmQuotationTopics = pgTable('crm_quotation_topics', {
  id: text('id').primaryKey(),
  organizationId: text('organization_id').notNull(),
  quotationId: text('quotation_id').notNull(),
  topicType: text('topic_type').notNull(),
  title: text('title').notNull(),
  sortOrder: integer('sort_order').default(0).notNull(),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
  deletedAt: timestamp('deleted_at', { withTimezone: true })
});

export const crmQuotationTopicItems = pgTable('crm_quotation_topic_items', {
  id: text('id').primaryKey(),
  organizationId: text('organization_id').notNull(),
  topicId: text('topic_id').notNull(),
  content: text('content').notNull(),
  sortOrder: integer('sort_order').default(0).notNull(),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
  deletedAt: timestamp('deleted_at', { withTimezone: true })
});

export const crmQuotationFollowups = pgTable('crm_quotation_followups', {
  id: text('id').primaryKey(),
  organizationId: text('organization_id').notNull(),
  quotationId: text('quotation_id').notNull(),
  followupDate: timestamp('followup_date', { withTimezone: true }).notNull(),
  followupType: text('followup_type').notNull(),
  contactId: text('contact_id'),
  outcome: text('outcome'),
  notes: text('notes'),
  nextFollowupDate: timestamp('next_followup_date', { withTimezone: true }),
  nextAction: text('next_action'),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
  deletedAt: timestamp('deleted_at', { withTimezone: true }),
  createdBy: text('created_by').notNull(),
  updatedBy: text('updated_by').notNull()
});

export const crmQuotationAttachments = pgTable('crm_quotation_attachments', {
  id: text('id').primaryKey(),
  organizationId: text('organization_id').notNull(),
  quotationId: text('quotation_id').notNull(),
  fileName: text('file_name').notNull(),
  originalFileName: text('original_file_name').notNull(),
  filePath: text('file_path').notNull(),
  fileSize: integer('file_size'),
  fileType: text('file_type'),
  description: text('description'),
  uploadedAt: timestamp('uploaded_at', { withTimezone: true }).defaultNow().notNull(),
  uploadedBy: text('uploaded_by').notNull(),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
  deletedAt: timestamp('deleted_at', { withTimezone: true })
});

export const crmDocumentArtifacts = pgTable('crm_document_artifacts', {
  id: text('id').primaryKey(),
  organizationId: text('organization_id').notNull(),
  entityType: text('entity_type').notNull(),
  entityId: text('entity_id').notNull(),
  documentType: text('document_type').notNull(),
  artifactType: text('artifact_type').notNull(),
  templateVersionId: text('template_version_id'),
  storageProvider: text('storage_provider').notNull(),
  storageKey: text('storage_key').notNull(),
  fileName: text('file_name').notNull(),
  contentType: text('content_type').notNull(),
  fileSize: integer('file_size'),
  checksum: text('checksum'),
  status: text('status').default('active').notNull(),
  generatedBy: text('generated_by').notNull(),
  generatedAt: timestamp('generated_at', { withTimezone: true }).defaultNow().notNull(),
  lockedAt: timestamp('locked_at', { withTimezone: true }),
  lockedBy: text('locked_by'),
  voidedAt: timestamp('voided_at', { withTimezone: true }),
  voidedBy: text('voided_by'),
  voidReason: text('void_reason'),
  metadata: jsonb('metadata'),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
  deletedAt: timestamp('deleted_at', { withTimezone: true })
});

export const crmApprovalWorkflows = pgTable(
  'crm_approval_workflows',
  {
    id: text('id').primaryKey(),
    organizationId: text('organization_id').notNull(),
    code: text('code').notNull(),
    name: text('name').notNull(),
    entityType: text('entity_type').notNull(),
    description: text('description'),
    isSystem: boolean('is_system').default(false).notNull(),
    isActive: boolean('is_active').default(true).notNull(),
    createdBy: text('created_by').notNull(),
    updatedBy: text('updated_by').notNull(),
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
    deletedAt: timestamp('deleted_at', { withTimezone: true })
  },
  (table) => ({
    organizationCodeIdx: uniqueIndex('crm_approval_workflows_org_code_idx').on(
      table.organizationId,
      table.code
    )
  })
);

export const crmApprovalSteps = pgTable(
  'crm_approval_steps',
  {
    id: text('id').primaryKey(),
    organizationId: text('organization_id').notNull(),
    workflowId: text('workflow_id').notNull(),
    stepNumber: integer('step_number').notNull(),
    roleCode: text('role_code').notNull(),
    roleName: text('role_name').notNull(),
    approvalMode: text('approval_mode').default('sequential').notNull(),
    isRequired: boolean('is_required').default(true).notNull(),
    slaHours: integer('sla_hours').default(24).notNull(),
    calendarMode: text('calendar_mode').default('calendar_days').notNull(),
    timeoutAction: text('timeout_action').default('none').notNull(),
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
    deletedAt: timestamp('deleted_at', { withTimezone: true })
  },
  (table) => ({
    workflowStepIdx: uniqueIndex('crm_approval_steps_workflow_step_idx').on(
      table.workflowId,
      table.stepNumber
    )
  })
);

export const crmApprovalMatrices = pgTable('crm_approval_matrices', {
  id: text('id').primaryKey(),
  organizationId: text('organization_id').notNull(),
  entityType: text('entity_type').notNull(),
  workflowId: text('workflow_id').notNull(),
  branchId: text('branch_id'),
  productType: text('product_type'),
  minAmount: doublePrecision('min_amount'),
  maxAmount: doublePrecision('max_amount'),
  currency: text('currency'),
  priority: integer('priority').default(100).notNull(),
  isDefault: boolean('is_default').default(false).notNull(),
  isActive: boolean('is_active').default(true).notNull(),
  description: text('description'),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
  deletedAt: timestamp('deleted_at', { withTimezone: true }),
  createdBy: text('created_by').notNull(),
  updatedBy: text('updated_by').notNull()
});

export const crmApprovalRequests = pgTable('crm_approval_requests', {
  id: text('id').primaryKey(),
  organizationId: text('organization_id').notNull(),
  workflowId: text('workflow_id').notNull(),
  entityType: text('entity_type').notNull(),
  entityId: text('entity_id').notNull(),
  currentStep: integer('current_step').default(1).notNull(),
  currentStepStartedAt: timestamp('current_step_started_at', { withTimezone: true })
    .defaultNow()
    .notNull(),
  status: text('status').notNull(),
  requestedBy: text('requested_by').notNull(),
  requestedAt: timestamp('requested_at', { withTimezone: true }).defaultNow().notNull(),
  completedAt: timestamp('completed_at', { withTimezone: true }),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
  deletedAt: timestamp('deleted_at', { withTimezone: true })
});

export const crmApprovalReminderPolicies = pgTable(
  'crm_approval_reminder_policies',
  {
    id: text('id').primaryKey(),
    organizationId: text('organization_id').notNull(),
    workflowId: text('workflow_id').notNull(),
    stepNumber: integer('step_number').notNull(),
    slaHours: integer('sla_hours').default(24).notNull(),
    reminderOffsetsHours: integer('reminder_offsets_hours').array().default([]).notNull(),
    calendarMode: text('calendar_mode').default('calendar_days').notNull(),
    timeoutAction: text('timeout_action').default('none').notNull(),
    isActive: boolean('is_active').default(true).notNull(),
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
    deletedAt: timestamp('deleted_at', { withTimezone: true }),
    createdBy: text('created_by').notNull(),
    updatedBy: text('updated_by').notNull()
  },
  (table) => ({
    workflowStepIdx: uniqueIndex('crm_approval_reminder_policies_workflow_step_idx').on(
      table.workflowId,
      table.stepNumber
    )
  })
);

export const crmApprovalEscalationPolicies = pgTable('crm_approval_escalation_policies', {
  id: text('id').primaryKey(),
  organizationId: text('organization_id').notNull(),
  workflowId: text('workflow_id').notNull(),
  stepNumber: integer('step_number').notNull(),
  triggerAfterHours: integer('trigger_after_hours').notNull(),
  targetType: text('target_type').notNull(),
  targetValue: text('target_value'),
  isActive: boolean('is_active').default(true).notNull(),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
  deletedAt: timestamp('deleted_at', { withTimezone: true }),
  createdBy: text('created_by').notNull(),
  updatedBy: text('updated_by').notNull()
});

export const crmApprovalActions = pgTable('crm_approval_actions', {
  id: text('id').primaryKey(),
  organizationId: text('organization_id').notNull(),
  approvalRequestId: text('approval_request_id').notNull(),
  stepNumber: integer('step_number').notNull(),
  action: text('action').notNull(),
  remark: text('remark'),
  actedBy: text('acted_by').notNull(),
  actedAt: timestamp('acted_at', { withTimezone: true }).defaultNow().notNull(),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
  deletedAt: timestamp('deleted_at', { withTimezone: true })
});

export const crmDocumentTemplates = pgTable(
  'crm_document_templates',
  {
    id: text('id').primaryKey(),
    organizationId: text('organization_id').notNull(),
    documentType: text('document_type').notNull(),
    productType: text('product_type').notNull(),
    fileType: text('file_type').notNull(),
    templateName: text('template_name').notNull(),
    description: text('description'),
    isDefault: boolean('is_default').default(false).notNull(),
    isActive: boolean('is_active').default(true).notNull(),
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
    deletedAt: timestamp('deleted_at', { withTimezone: true }),
    createdBy: text('created_by').notNull(),
    updatedBy: text('updated_by').notNull()
  },
  (table) => ({
    organizationTemplateIdx: uniqueIndex('crm_document_templates_org_doc_product_file_name_idx').on(
      table.organizationId,
      table.documentType,
      table.productType,
      table.fileType,
      table.templateName
    )
  })
);

export const crmDocumentTemplateVersions = pgTable(
  'crm_document_template_versions',
  {
    id: text('id').primaryKey(),
    organizationId: text('organization_id').notNull(),
    templateId: text('template_id').notNull(),
    version: text('version').notNull(),
    filePath: text('file_path'),
    schemaJson: jsonb('schema_json').notNull(),
    metadataJson: jsonb('metadata_json'),
    previewImageUrl: text('preview_image_url'),
    isActive: boolean('is_active').default(true).notNull(),
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
    deletedAt: timestamp('deleted_at', { withTimezone: true }),
    createdBy: text('created_by').notNull()
  },
  (table) => ({
    templateVersionIdx: uniqueIndex('crm_document_template_versions_template_version_idx').on(
      table.templateId,
      table.version
    )
  })
);

export const crmDocumentLibraries = pgTable(
  'crm_document_libraries',
  {
    id: text('id').primaryKey(),
    organizationId: text('organization_id').notNull(),
    code: text('code').notNull(),
    name: text('name').notNull(),
    documentType: text('document_type').notNull(),
    description: text('description'),
    brand: text('brand').notNull(),
    language: text('language').notNull(),
    productType: text('product_type').notNull(),
    status: text('status').default('active').notNull(),
    isActive: boolean('is_active').default(true).notNull(),
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
    deletedAt: timestamp('deleted_at', { withTimezone: true }),
    createdBy: text('created_by').notNull(),
    updatedBy: text('updated_by').notNull()
  },
  (table) => ({
    organizationCodeIdx: uniqueIndex('crm_document_libraries_org_code_idx').on(
      table.organizationId,
      table.code
    )
  })
);

export const crmDocumentLibraryVersions = pgTable(
  'crm_document_library_versions',
  {
    id: text('id').primaryKey(),
    organizationId: text('organization_id').notNull(),
    libraryId: text('library_id').notNull(),
    version: text('version').notNull(),
    fileName: text('file_name').notNull(),
    storageProvider: text('storage_provider').notNull(),
    storageKey: text('storage_key').notNull(),
    mimeType: text('mime_type').notNull(),
    fileSize: integer('file_size').notNull(),
    checksum: text('checksum').notNull(),
    pageCount: integer('page_count').notNull(),
    status: text('status').default('draft').notNull(),
    isActive: boolean('is_active').default(false).notNull(),
    publishedAt: timestamp('published_at', { withTimezone: true }),
    publishedBy: text('published_by'),
    archivedAt: timestamp('archived_at', { withTimezone: true }),
    archivedBy: text('archived_by'),
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
    deletedAt: timestamp('deleted_at', { withTimezone: true }),
    createdBy: text('created_by').notNull()
  },
  (table) => ({
    libraryVersionIdx: uniqueIndex('crm_document_library_versions_library_version_idx').on(
      table.libraryId,
      table.version
    )
  })
);

export const crmDocumentTemplateMappings = pgTable(
  'crm_document_template_mappings',
  {
    id: text('id').primaryKey(),
    organizationId: text('organization_id').notNull(),
    templateVersionId: text('template_version_id').notNull(),
    placeholderKey: text('placeholder_key').notNull(),
    sourcePath: text('source_path').notNull(),
    dataType: text('data_type').notNull(),
    sheetName: text('sheet_name'),
    defaultValue: text('default_value'),
    formatMask: text('format_mask'),
    sortOrder: integer('sort_order').default(0).notNull(),
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
    deletedAt: timestamp('deleted_at', { withTimezone: true })
  },
  (table) => ({
    templatePlaceholderIdx: uniqueIndex(
      'crm_document_template_mappings_version_placeholder_idx'
    ).on(table.templateVersionId, table.placeholderKey)
  })
);

export const crmDocumentTemplateTableColumns = pgTable(
  'crm_document_template_table_columns',
  {
    id: text('id').primaryKey(),
    organizationId: text('organization_id').notNull(),
    mappingId: text('mapping_id').notNull(),
    columnName: text('column_name').notNull(),
    sourceField: text('source_field').notNull(),
    columnLetter: text('column_letter'),
    sortOrder: integer('sort_order').default(0).notNull(),
    formatMask: text('format_mask'),
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
    deletedAt: timestamp('deleted_at', { withTimezone: true })
  },
  (table) => ({
    mappingColumnIdx: uniqueIndex('crm_document_template_table_columns_mapping_name_idx').on(
      table.mappingId,
      table.columnName
    )
  })
);
