import { pgTable, text, integer, jsonb, uuid, index } from 'drizzle-orm/pg-core';
import { id, createdAt, ts } from './_common';
import { actorTypeEnum } from './enums';

/** Who did what, with before/after state. tenantId null = platform-level action. */
export const auditLogs = pgTable(
  'audit_logs',
  {
    id: id(),
    tenantId: uuid('tenant_id'),
    actorType: actorTypeEnum('actor_type').notNull(),
    actorId: text('actor_id'),
    actorName: text('actor_name'),
    action: text('action').notNull(),
    entityType: text('entity_type'),
    entityId: text('entity_id'),
    before: jsonb('before').$type<unknown>(),
    after: jsonb('after').$type<unknown>(),
    ip: text('ip'),
    userAgent: text('user_agent'),
    requestId: text('request_id'),
    createdAt: createdAt(),
  },
  (t) => [index('audit_logs_entity_idx').on(t.tenantId, t.entityType, t.entityId), index('audit_logs_time_idx').on(t.tenantId, t.createdAt)],
);

/** Generated documents (PDF/ZPL) stored in object storage. */
export const documents = pgTable(
  'documents',
  {
    id: id(),
    tenantId: uuid('tenant_id').notNull(),
    type: text('type').notNull(),
    number: text('number').notNull(),
    refType: text('ref_type').notNull(),
    refId: uuid('ref_id').notNull(),
    mimeType: text('mime_type').notNull().default('application/pdf'),
    storageKey: text('storage_key').notNull(),
    sizeBytes: integer('size_bytes'),
    generatedAt: ts('generated_at').notNull().defaultNow(),
    generatedById: uuid('generated_by_id'),
    sentAt: ts('sent_at'),
    sentTo: text('sent_to').array().notNull().default([]),
  },
  (t) => [index('documents_ref_idx').on(t.tenantId, t.refType, t.refId)],
);

/** Uploaded files: damage photos, PODs, signatures, source documents for AI intake. */
export const attachments = pgTable(
  'attachments',
  {
    id: id(),
    tenantId: uuid('tenant_id').notNull(),
    refType: text('ref_type').notNull(),
    refId: uuid('ref_id').notNull(),
    fileName: text('file_name').notNull(),
    mimeType: text('mime_type').notNull(),
    sizeBytes: integer('size_bytes').notNull(),
    storageKey: text('storage_key').notNull(),
    kind: text('kind').notNull().default('PHOTO'),
    uploadedById: uuid('uploaded_by_id'),
    createdAt: createdAt(),
  },
  (t) => [index('attachments_ref_idx').on(t.tenantId, t.refType, t.refId)],
);

export const notifications = pgTable(
  'notifications',
  {
    id: id(),
    tenantId: uuid('tenant_id').notNull(),
    userId: uuid('user_id').notNull(),
    type: text('type').notNull(),
    title: text('title').notNull(),
    body: text('body'),
    data: jsonb('data').notNull().default({}).$type<Record<string, unknown>>(),
    readAt: ts('read_at'),
    createdAt: createdAt(),
  },
  (t) => [index('notifications_user_idx').on(t.tenantId, t.userId, t.readAt)],
);

export const emailOutbox = pgTable(
  'email_outbox',
  {
    id: id(),
    tenantId: uuid('tenant_id').notNull(),
    to: text('to').array().notNull(),
    cc: text('cc').array().notNull().default([]),
    subject: text('subject').notNull(),
    bodyHtml: text('body_html').notNull(),
    attachments: jsonb('attachments').notNull().default([]).$type<{ documentId?: string; storageKey?: string; fileName?: string }[]>(),
    refType: text('ref_type'),
    refId: uuid('ref_id'),
    status: text('status').notNull().default('PENDING'),
    attempts: integer('attempts').notNull().default(0),
    lastError: text('last_error'),
    sentAt: ts('sent_at'),
    createdAt: createdAt(),
  },
  (t) => [index('email_outbox_status_idx').on(t.tenantId, t.status)],
);

/** Transactional outbox for domain events (webhooks, async jobs). Written in the same transaction as the business change. */
export const outboxEvents = pgTable(
  'outbox_events',
  {
    id: id(),
    tenantId: uuid('tenant_id').notNull(),
    type: text('type').notNull(),
    warehouseId: uuid('warehouse_id'),
    storerId: uuid('storer_id'),
    actorId: uuid('actor_id'),
    payload: jsonb('payload').notNull().$type<Record<string, unknown>>(),
    status: text('status').notNull().default('PENDING'),
    attempts: integer('attempts').notNull().default(0),
    lastError: text('last_error'),
    claimedAt: ts('claimed_at'),
    processedAt: ts('processed_at'),
    createdAt: createdAt(),
  },
  (t) => [index('outbox_events_status_idx').on(t.status, t.createdAt)],
);
