/**
 * snake_case serializers — tenant-public-api (wave-11 leaf-D).
 * Maps internal camelCase Drizzle rows to snake_case API response objects.
 * Monetary NUMERIC columns serialize as decimal strings; timestamps as ISO 8601.
 */
import { extractPlainText } from './tiptap'

// ── Customer ──────────────────────────────────────────────────────────────────

export interface CustomerObject {
  id: string
  name: string
  company: string | null
  email: string | null
  phone: string | null
  address: {
    street: string | null
    city: string | null
    state: string | null
    zip: string | null
    country: string | null
  } | null
  status: 'active' | 'archived'
  created_at: string
  updated_at: string
}

export function serializeCustomer(row: {
  id: string
  name: string
  company: string | null
  email: string | null
  phone: string | null
  address: { street?: string | null; city?: string | null; state?: string | null; zip?: string | null; country?: string | null } | null
  status: string
  createdAt: Date | string
  updatedAt: Date | string
}): CustomerObject {
  return {
    id: row.id,
    name: row.name,
    company: row.company ?? null,
    email: row.email ?? null,
    phone: row.phone ?? null,
    address: row.address
      ? {
          street: row.address.street ?? null,
          city: row.address.city ?? null,
          state: row.address.state ?? null,
          zip: row.address.zip ?? null,
          country: row.address.country ?? null,
        }
      : null,
    status: row.status as 'active' | 'archived',
    created_at: typeof row.createdAt === 'string' ? row.createdAt : row.createdAt.toISOString(),
    updated_at: typeof row.updatedAt === 'string' ? row.updatedAt : row.updatedAt.toISOString(),
  }
}

// ── Invoice ───────────────────────────────────────────────────────────────────

export interface InvoiceLineObject {
  id: string
  description: string
  quantity: string
  unit_price: string
  discount_pct: string
  line_total: string
  taxable: boolean
  position: number
  expense_id?: string | null
}

export type InvoiceStatus = 'DRAFT' | 'SENT' | 'APPROVED' | 'REJECTED' | 'TAX_ISSUED' | 'PAID' | 'VOID'

export interface InvoiceObject {
  id: string
  customer_id: string | null
  project_id: string | null
  invoice_number: string | null
  proforma_number: string | null
  status: InvoiceStatus
  currency: string
  issue_date: string | null
  tax_issue_date: string | null
  due_date: string | null
  vat_rate: string | null
  subtotal: string
  vat_amount: string
  total: string
  notes: string | null
  source: string
  paid_at: string | null
  lines: InvoiceLineObject[]
  created_at: string
  updated_at: string
}

export function serializeInvoiceLine(row: {
  id: string
  description: string
  quantity: string | null
  unitPrice: string | null
  discountPct: string | null
  lineTotal: string | null
  taxable: boolean
  position: number
  expenseId?: string | null
}): InvoiceLineObject {
  return {
    id: row.id,
    description: row.description,
    quantity: row.quantity ?? '1',
    unit_price: row.unitPrice ?? '0',
    discount_pct: row.discountPct ?? '0',
    line_total: row.lineTotal ?? '0',
    taxable: row.taxable,
    position: row.position,
    expense_id: row.expenseId ?? null,
  }
}

export function serializeInvoice(
  row: {
    id: string
    customerId: string | null
    projectId: string | null
    invoiceNumber: string | null
    proformaNumber: string | null
    status: string
    currency: string
    issueDate: string | null
    taxIssueDate: string | null
    dueDate: string | null
    vatRate: string | null
    subtotal: string
    vatAmount: string
    total: string
    notes: string | null
    source: string
    paidAt: Date | string | null
    createdAt: Date | string
    updatedAt: Date | string
  },
  lines: InvoiceLineObject[],
): InvoiceObject {
  return {
    id: row.id,
    customer_id: row.customerId ?? null,
    project_id: row.projectId ?? null,
    invoice_number: row.invoiceNumber ?? null,
    proforma_number: row.proformaNumber ?? null,
    status: row.status as InvoiceStatus,
    currency: row.currency,
    issue_date: row.issueDate ?? null,
    tax_issue_date: row.taxIssueDate ?? null,
    due_date: row.dueDate ?? null,
    vat_rate: row.vatRate ?? null,
    subtotal: row.subtotal,
    vat_amount: row.vatAmount,
    total: row.total,
    notes: row.notes ?? null,
    source: row.source,
    paid_at: row.paidAt ? (typeof row.paidAt === 'string' ? row.paidAt : row.paidAt.toISOString()) : null,
    lines,
    created_at: typeof row.createdAt === 'string' ? row.createdAt : row.createdAt.toISOString(),
    updated_at: typeof row.updatedAt === 'string' ? row.updatedAt : row.updatedAt.toISOString(),
  }
}

// ── Task ──────────────────────────────────────────────────────────────────────

export interface TaskObject {
  id: string
  status_id: string
  status_name: string
  title: string
  description_text: string | null
  priority: 'low' | 'medium' | 'high' | 'urgent'
  due_date: string | null
  source: string
  created_at: string
  updated_at: string
}

export function serializeTask(
  row: {
    id: string
    project_id?: string | null
    projectId?: string | null
    status_id?: string
    statusId?: string
    title: string
    description: unknown
    priority: string
    assignee_id?: string | null
    assigneeId?: string | null
    due_date?: string | null
    dueDate?: string | null
    source: string
    created_at?: string
    createdAt?: Date | string
    updated_at?: string
    updatedAt?: Date | string
  },
  statusName: string,
): TaskObject {
  const statusId = row.status_id ?? row.statusId ?? ''
  const dueDate = row.due_date ?? row.dueDate ?? null
  const createdRaw = row.created_at ?? row.createdAt ?? ''
  const updatedRaw = row.updated_at ?? row.updatedAt ?? ''
  const createdAt = typeof createdRaw === 'string' ? createdRaw : createdRaw.toISOString()
  const updatedAt = typeof updatedRaw === 'string' ? updatedRaw : updatedRaw.toISOString()
  return {
    id: row.id,
    status_id: statusId,
    status_name: statusName,
    title: row.title,
    description_text: extractPlainText(row.description),
    priority: row.priority as TaskObject['priority'],
    due_date: dueDate ?? null,
    source: row.source,
    created_at: createdAt,
    updated_at: updatedAt,
  }
}

// ── Lead ─────────────────────────────────────────────────────────────────────

export interface LeadObject {
  id: string
  name: string
  email: string | null
  phone: string | null
  company: string | null
  stage: string
  source: string
  estimated_value: string | null
  customer_id: string | null
  assigned_to: string | null
  created_at: string
}

export function serializeLead(row: {
  id: string
  name: string
  email: string | null | undefined
  phone: string | null | undefined
  company: string | null | undefined
  stage: string
  source: string
  estimatedValue?: string | null
  estimated_value?: string | null
  customerId?: string | null
  customer_id?: string | null
  assignedTo?: string | null
  assigned_to?: string | null
  createdAt?: Date | string
  created_at?: Date | string
}): LeadObject {
  const estimatedValue = row.estimatedValue ?? row.estimated_value ?? null
  const customerId = row.customerId ?? row.customer_id ?? null
  const assignedTo = row.assignedTo ?? row.assigned_to ?? null
  const createdRaw = row.createdAt ?? row.created_at ?? ''
  const createdAt = typeof createdRaw === 'string' ? createdRaw : (createdRaw as Date).toISOString()
  return {
    id: row.id,
    name: row.name,
    email: row.email ?? null,
    phone: row.phone ?? null,
    company: row.company ?? null,
    stage: row.stage,
    source: row.source,
    estimated_value: estimatedValue,
    customer_id: customerId ?? null,
    assigned_to: assignedTo ?? null,
    created_at: createdAt,
  }
}

// ── TimeEntry ─────────────────────────────────────────────────────────────────

export interface TimeEntryObject {
  id: string
  project_id: string
  task_id: string | null
  description: string | null
  started_at: string
  stopped_at: string | null
  duration_minutes: number | null
  billable: boolean
  source: string
  created_at: string
}

export function serializeTimeEntry(row: {
  id: string
  projectId?: string
  project_id?: string
  taskId?: string | null
  task_id?: string | null
  description: string | null | undefined
  startedAt?: Date | string
  started_at?: Date | string
  stoppedAt?: Date | string | null
  stopped_at?: Date | string | null
  durationSeconds?: number | null
  duration_seconds?: number | null
  billable: boolean
  source: string
  createdAt?: Date | string
  created_at?: Date | string
}): TimeEntryObject {
  const projectId = row.projectId ?? row.project_id ?? ''
  const taskId = row.taskId ?? row.task_id ?? null
  const durationSeconds = row.durationSeconds ?? row.duration_seconds ?? null
  const startedRaw = row.startedAt ?? row.started_at ?? ''
  const stoppedRaw = row.stoppedAt ?? row.stopped_at ?? null
  const createdRaw = row.createdAt ?? row.created_at ?? ''
  return {
    id: row.id,
    project_id: projectId,
    task_id: taskId ?? null,
    description: row.description ?? null,
    started_at: typeof startedRaw === 'string' ? startedRaw : (startedRaw as Date).toISOString(),
    stopped_at: stoppedRaw
      ? (typeof stoppedRaw === 'string' ? stoppedRaw : (stoppedRaw as Date).toISOString())
      : null,
    duration_minutes: durationSeconds != null ? Math.round(durationSeconds / 60) : null,
    billable: row.billable,
    source: row.source,
    created_at: typeof createdRaw === 'string' ? createdRaw : (createdRaw as Date).toISOString(),
  }
}

// ── Project ───────────────────────────────────────────────────────────────────

export interface ProjectObject {
  id: string
  name: string
  customer_id: string | null
  status: string
  created_at: string
}

export function serializeProject(row: {
  id: string
  name: string
  customerId?: string | null
  customer_id?: string | null
  status: string
  createdAt?: Date | string
  created_at?: Date | string
}): ProjectObject {
  const customerId = row.customerId ?? row.customer_id ?? null
  const createdRaw = row.createdAt ?? row.created_at ?? ''
  return {
    id: row.id,
    name: row.name,
    customer_id: customerId ?? null,
    status: row.status,
    created_at: typeof createdRaw === 'string' ? createdRaw : (createdRaw as Date).toISOString(),
  }
}

// ── Event (webhook delivery) ──────────────────────────────────────────────────

export interface EventObject {
  id: string
  endpoint_url: string
  event_type: string
  status: string
  response_status: number | null
  latency_ms: number | null
  attempt: number
  created_at: string
}

function truncateEndpointUrl(url: string): string {
  try {
    const parsed = new URL(url)
    const parts = parsed.pathname.split('/').filter(Boolean)
    const truncatedPath = parts.length > 0 ? `/${parts[0]}/...` : '/...'
    return `${parsed.protocol}//${parsed.host}${truncatedPath}`
  } catch {
    return '...'
  }
}

export function serializeEvent(row: {
  id: string
  endpointId: string | null
  eventType: string | null
  status: string
  responseStatus: number | null
  latencyMs: number | null
  attempt: number
  createdAt: Date
  endpointUrl?: string | null
}): EventObject {
  return {
    id: row.id,
    endpoint_url: row.endpointUrl ? truncateEndpointUrl(row.endpointUrl) : '...',
    event_type: row.eventType ?? '',
    status: row.status,
    response_status: row.responseStatus ?? null,
    latency_ms: row.latencyMs ?? null,
    attempt: row.attempt,
    created_at: row.createdAt.toISOString(),
  }
}
