import {
  pgTable,
  uuid,
  varchar,
  text,
  timestamp,
  boolean,
  integer,
  numeric,
  pgEnum,
  jsonb,
} from 'drizzle-orm/pg-core'
import { locations } from './stores.js'
import { accounts } from './accounts.js'
import { products, inventoryUnits } from './inventory.js'
import { users } from './users.js'
import { repairTickets, repairBatches } from './repairs.js'

// --- Enums ---

export const transactionTypeEnum = pgEnum('transaction_type', [
  'sale',
  'repair_payment',
  'rental_deposit',
  'account_payment',
  'refund',
])

export const transactionStatusEnum = pgEnum('transaction_status', [
  'pending',
  'completed',
  'voided',
  'refunded',
])

export const paymentMethodEnum = pgEnum('payment_method', [
  'cash',
  'card_present',
  'card_keyed',
  'check',
  'account_charge',
])

export const discountTypeEnum = pgEnum('discount_type', ['percent', 'fixed'])

export const discountAppliesToEnum = pgEnum('discount_applies_to', [
  'order',
  'line_item',
  'category',
])

export const drawerStatusEnum = pgEnum('drawer_status', ['open', 'closed'])

// --- Tables ---

export const discounts = pgTable('discount', {
  id: uuid('id').primaryKey().defaultRandom(),
  locationId: uuid('location_id').references(() => locations.id),
  name: varchar('name', { length: 255 }).notNull(),
  discountType: discountTypeEnum('discount_type').notNull(),
  discountValue: numeric('discount_value', { precision: 10, scale: 2 }).notNull(),
  appliesTo: discountAppliesToEnum('applies_to').notNull().default('line_item'),
  requiresApprovalAbove: numeric('requires_approval_above', { precision: 10, scale: 2 }),
  isActive: boolean('is_active').notNull().default(true),
  validFrom: timestamp('valid_from', { withTimezone: true }),
  validUntil: timestamp('valid_until', { withTimezone: true }),
  createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
})

export const adjustmentTypeEnum = pgEnum('adjustment_type', ['cash_in', 'cash_out'])

export const registers = pgTable('register', {
  id: uuid('id').primaryKey().defaultRandom(),
  locationId: uuid('location_id')
    .notNull()
    .references(() => locations.id),
  name: varchar('name', { length: 100 }).notNull(),
  isActive: boolean('is_active').notNull().default(true),
  createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
})

export const drawerSessions = pgTable('drawer_session', {
  id: uuid('id').primaryKey().defaultRandom(),
  locationId: uuid('location_id').references(() => locations.id),
  registerId: uuid('register_id').references(() => registers.id),
  openedBy: uuid('opened_by')
    .notNull()
    .references(() => users.id),
  closedBy: uuid('closed_by').references(() => users.id),
  openingBalance: numeric('opening_balance', { precision: 10, scale: 2 }).notNull(),
  closingBalance: numeric('closing_balance', { precision: 10, scale: 2 }),
  expectedBalance: numeric('expected_balance', { precision: 10, scale: 2 }),
  overShort: numeric('over_short', { precision: 10, scale: 2 }),
  denominations: jsonb('denominations').$type<Record<string, number>>(),
  status: drawerStatusEnum('status').notNull().default('open'),
  notes: text('notes'),
  openedAt: timestamp('opened_at', { withTimezone: true }).notNull().defaultNow(),
  closedAt: timestamp('closed_at', { withTimezone: true }),
})

export const drawerAdjustments = pgTable('drawer_adjustment', {
  id: uuid('id').primaryKey().defaultRandom(),
  drawerSessionId: uuid('drawer_session_id')
    .notNull()
    .references(() => drawerSessions.id),
  type: adjustmentTypeEnum('type').notNull(),
  amount: numeric('amount', { precision: 10, scale: 2 }).notNull(),
  reason: text('reason').notNull(),
  createdBy: uuid('created_by')
    .notNull()
    .references(() => users.id),
  createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
})

export const transactions = pgTable('transaction', {
  id: uuid('id').primaryKey().defaultRandom(),
  locationId: uuid('location_id').references(() => locations.id),
  transactionNumber: varchar('transaction_number', { length: 50 }).notNull().unique(),
  accountId: uuid('account_id').references(() => accounts.id),
  repairTicketId: uuid('repair_ticket_id').references(() => repairTickets.id),
  repairBatchId: uuid('repair_batch_id').references(() => repairBatches.id),
  transactionType: transactionTypeEnum('transaction_type').notNull(),
  status: transactionStatusEnum('status').notNull().default('pending'),
  subtotal: numeric('subtotal', { precision: 10, scale: 2 }).notNull().default('0'),
  discountTotal: numeric('discount_total', { precision: 10, scale: 2 }).notNull().default('0'),
  taxTotal: numeric('tax_total', { precision: 10, scale: 2 }).notNull().default('0'),
  total: numeric('total', { precision: 10, scale: 2 }).notNull().default('0'),
  paymentMethod: paymentMethodEnum('payment_method'),
  amountTendered: numeric('amount_tendered', { precision: 10, scale: 2 }),
  changeGiven: numeric('change_given', { precision: 10, scale: 2 }),
  checkNumber: varchar('check_number', { length: 50 }),
  stripePaymentIntentId: varchar('stripe_payment_intent_id', { length: 255 }),
  roundingAdjustment: numeric('rounding_adjustment', { precision: 10, scale: 2 }).notNull().default('0'),
  taxExempt: boolean('tax_exempt').notNull().default(false),
  taxExemptReason: text('tax_exempt_reason'),
  processedBy: uuid('processed_by')
    .notNull()
    .references(() => users.id),
  drawerSessionId: uuid('drawer_session_id').references(() => drawerSessions.id),
  notes: text('notes'),
  completedAt: timestamp('completed_at', { withTimezone: true }),
  createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
})

export const transactionLineItems = pgTable('transaction_line_item', {
  id: uuid('id').primaryKey().defaultRandom(),
  transactionId: uuid('transaction_id')
    .notNull()
    .references(() => transactions.id),
  productId: uuid('product_id').references(() => products.id),
  inventoryUnitId: uuid('inventory_unit_id').references(() => inventoryUnits.id),
  description: varchar('description', { length: 255 }).notNull(),
  qty: integer('qty').notNull().default(1),
  unitPrice: numeric('unit_price', { precision: 10, scale: 2 }).notNull(),
  discountAmount: numeric('discount_amount', { precision: 10, scale: 2 }).notNull().default('0'),
  discountReason: text('discount_reason'),
  taxRate: numeric('tax_rate', { precision: 5, scale: 4 }).notNull().default('0'),
  taxAmount: numeric('tax_amount', { precision: 10, scale: 2 }).notNull().default('0'),
  lineTotal: numeric('line_total', { precision: 10, scale: 2 }).notNull().default('0'),
  createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
})

export const discountAudits = pgTable('discount_audit', {
  id: uuid('id').primaryKey().defaultRandom(),
  transactionId: uuid('transaction_id')
    .notNull()
    .references(() => transactions.id),
  transactionLineItemId: uuid('transaction_line_item_id').references(() => transactionLineItems.id),
  discountId: uuid('discount_id').references(() => discounts.id),
  appliedBy: uuid('applied_by')
    .notNull()
    .references(() => users.id),
  approvedBy: uuid('approved_by').references(() => users.id),
  originalAmount: numeric('original_amount', { precision: 10, scale: 2 }).notNull(),
  discountedAmount: numeric('discounted_amount', { precision: 10, scale: 2 }).notNull(),
  reason: text('reason').notNull(),
  createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
})

// --- Type exports ---

export type Discount = typeof discounts.$inferSelect
export type DiscountInsert = typeof discounts.$inferInsert
export type Transaction = typeof transactions.$inferSelect
export type TransactionInsert = typeof transactions.$inferInsert
export type TransactionLineItem = typeof transactionLineItems.$inferSelect
export type TransactionLineItemInsert = typeof transactionLineItems.$inferInsert
export type DiscountAudit = typeof discountAudits.$inferSelect
export type DiscountAuditInsert = typeof discountAudits.$inferInsert
export type DrawerSession = typeof drawerSessions.$inferSelect
export type DrawerSessionInsert = typeof drawerSessions.$inferInsert
