import { sql } from 'drizzle-orm'
import {
  check,
  foreignKey,
  index,
  numeric,
  pgTable,
  primaryKey,
  text,
  timestamp,
  unique,
} from 'drizzle-orm/pg-core'
import { MAX_QUANTITY } from './internal/bigint.js'

const quantityBound = sql.raw(MAX_QUANTITY.toString())

const units = (name: string) => numeric(name, { mode: 'bigint' }).notNull()

export const meteringCounter = pgTable(
  'metering_counter',
  {
    tenantId: text('tenant_id').notNull(),
    account: text('account').notNull(),
    meter: text('meter').notNull(),
    periodId: text('period_id').notNull(),
    committed: units('committed'),
    reserved: units('reserved'),
  },
  (table) => [
    primaryKey({
      name: 'metering_counter_pkey',
      columns: [table.tenantId, table.account, table.meter, table.periodId],
    }),
    check('metering_counter_committed_nonnegative', sql`${table.committed} >= 0`),
    check('metering_counter_reserved_nonnegative', sql`${table.reserved} >= 0`),
    check('metering_counter_committed_integral', sql`${table.committed} = trunc(${table.committed})`),
    check('metering_counter_reserved_integral', sql`${table.reserved} = trunc(${table.reserved})`),
    check('metering_counter_committed_bounded', sql`${table.committed} < ${quantityBound}`),
    check('metering_counter_reserved_bounded', sql`${table.reserved} < ${quantityBound}`),
  ],
)

export const meteringReservation = pgTable(
  'metering_reservation',
  {
    id: text('id').primaryKey(),
    tenantId: text('tenant_id').notNull(),
    idempotencyKey: text('idempotency_key').notNull(),
    fingerprint: text('fingerprint').notNull(),
    account: text('account').notNull(),
    meter: text('meter').notNull(),
    periodId: text('period_id').notNull(),
    periodStartsAt: timestamp('period_starts_at', { withTimezone: true }).notNull(),
    periodEndsAt: timestamp('period_ends_at', { withTimezone: true }).notNull(),
    reservedUnits: units('reserved_units'),
    committedUnits: numeric('committed_units', { mode: 'bigint' }),
    status: text('status').notNull(),
    appliedIncludedUnits: units('applied_included_units'),
    appliedHardLimit: numeric('applied_hard_limit', { mode: 'bigint' }),
    appliedOverage: text('applied_overage').notNull(),
    policyVersion: text('policy_version').notNull(),
    expiresAt: timestamp('expires_at', { withTimezone: true }).notNull(),
    createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
  },
  (table) => [
    unique('metering_reservation_tenant_idempotency_key_key').on(table.tenantId, table.idempotencyKey),
    index('metering_reservation_status_expires_at_idx').on(table.status, table.expiresAt),
    foreignKey({
      name: 'metering_reservation_counter_fk',
      columns: [table.tenantId, table.account, table.meter, table.periodId],
      foreignColumns: [
        meteringCounter.tenantId,
        meteringCounter.account,
        meteringCounter.meter,
        meteringCounter.periodId,
      ],
    }),
    check('metering_reservation_reserved_units_nonnegative', sql`${table.reservedUnits} >= 0`),
    check('metering_reservation_reserved_units_integral', sql`${table.reservedUnits} = trunc(${table.reservedUnits})`),
    check('metering_reservation_reserved_units_bounded', sql`${table.reservedUnits} < ${quantityBound}`),
    check(
      'metering_reservation_committed_units_nonnegative',
      sql`${table.committedUnits} IS NULL OR ${table.committedUnits} >= 0`,
    ),
    check(
      'metering_reservation_committed_units_integral',
      sql`${table.committedUnits} IS NULL OR ${table.committedUnits} = trunc(${table.committedUnits})`,
    ),
    check(
      'metering_reservation_committed_units_bounded',
      sql`${table.committedUnits} IS NULL OR ${table.committedUnits} < ${quantityBound}`,
    ),
    check('metering_reservation_applied_included_units_nonnegative', sql`${table.appliedIncludedUnits} >= 0`),
    check(
      'metering_reservation_applied_included_units_integral',
      sql`${table.appliedIncludedUnits} = trunc(${table.appliedIncludedUnits})`,
    ),
    check(
      'metering_reservation_applied_included_units_bounded',
      sql`${table.appliedIncludedUnits} < ${quantityBound}`,
    ),
    check(
      'metering_reservation_applied_hard_limit',
      sql`${table.appliedHardLimit} IS NULL OR ${table.appliedHardLimit} >= ${table.appliedIncludedUnits}`,
    ),
    check(
      'metering_reservation_applied_hard_limit_integral',
      sql`${table.appliedHardLimit} IS NULL OR ${table.appliedHardLimit} = trunc(${table.appliedHardLimit})`,
    ),
    check(
      'metering_reservation_applied_hard_limit_bounded',
      sql`${table.appliedHardLimit} IS NULL OR ${table.appliedHardLimit} < ${quantityBound}`,
    ),
    check(
      'metering_reservation_status',
      sql`${table.status} IN ('reserved', 'committed', 'released', 'expired')`,
    ),
    check('metering_reservation_applied_overage', sql`${table.appliedOverage} IN ('deny', 'allow')`),
  ],
)

export const meteringUsageEvent = pgTable(
  'metering_usage_event',
  {
    id: text('id').primaryKey(),
    tenantId: text('tenant_id').notNull(),
    account: text('account').notNull(),
    meter: text('meter').notNull(),
    periodId: text('period_id').notNull(),
    units: units('units'),
    kind: text('kind').notNull(),
    reservationId: text('reservation_id').notNull(),
    ruleVersion: text('rule_version'),
    createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
  },
  (table) => [
    unique('metering_usage_event_reservation_id_key').on(table.reservationId),
    check('metering_usage_event_units_nonnegative', sql`${table.units} >= 0`),
    check('metering_usage_event_units_integral', sql`${table.units} = trunc(${table.units})`),
    check('metering_usage_event_units_bounded', sql`${table.units} < ${quantityBound}`),
    check('metering_usage_event_kind', sql`${table.kind} = 'commit'`),
  ],
)

export const meteringSchema = {
  meteringCounter,
  meteringReservation,
  meteringUsageEvent,
}

export type MeteringSchema = typeof meteringSchema
