/**
 * The one dated thing that has no other home.
 *
 * Everything else on the quarterly calendar is a PROJECTION: a contract
 * expiry, an obligation due date, a commitment window, a hold expiring, an
 * export authorisation lapsing. Those dates already live on the records that
 * own them, and copying them into a calendar table would guarantee drift —
 * two answers to "when does this expire?", with nothing to say which is right.
 * PIG's whole argument is that one ledger answers the question.
 *
 * What genuinely has nowhere to live is a human-owned dated item: the QBR, the
 * renewal check-in, the campaign week. So exactly one table, for exactly that.
 *
 * **No recurrence in v1, deliberately.** A recurrence rule is worthless
 * without an expansion strategy — do you materialise occurrences, expand at
 * read time, and where does an edited single occurrence live? Every calendar
 * table that grew an `rrule` column before answering those questions ended up
 * with orphaned exceptions nobody could delete. When recurrence is needed it
 * should arrive with its expansion, not before it.
 */
import { boolean, index, pgTable, text, timestamp, uuid } from 'drizzle-orm/pg-core';
import { CALENDAR_ENTRY_KINDS } from '@pig/core';
import { accounts } from './crm';
import { demandDeals } from './demand';
import { supplyDeals } from './supply';
import { users } from './identity';

export const calendarEntries = pgTable(
  'calendar_entries',
  {
    id: uuid('id').primaryKey().defaultRandom(),

    title: text('title').notNull(),
    description: text('description'),
    kind: text('kind', { enum: CALENDAR_ENTRY_KINDS }).notNull().default('meeting'),

    startsAt: timestamp('starts_at', { withTimezone: true }).notNull(),
    /** Null for a point in time — a reminder is not a window. */
    endsAt: timestamp('ends_at', { withTimezone: true }),
    /**
     * An all-day entry still stores instants, because every temporal column in
     * PIG does and a mixed representation would need a special case in every
     * date predicate. The flag records the author's intent so the front end
     * can render "12 August" rather than "12 August, 00:00".
     */
    allDay: boolean('all_day').notNull().default(false),

    ownerUserId: uuid('owner_user_id').references(() => users.id, { onDelete: 'set null' }),

    /**
     * Polymorphic by nullable FK, the same idiom `activities` uses. A junction
     * table would be more general and would also make "what is on the calendar
     * for this account?" a three-way join for no benefit — an entry is about
     * at most one of these things in practice.
     */
    accountId: uuid('account_id').references(() => accounts.id, { onDelete: 'cascade' }),
    demandDealId: uuid('demand_deal_id').references(() => demandDeals.id, {
      onDelete: 'cascade',
    }),
    supplyDealId: uuid('supply_deal_id').references(() => supplyDeals.id, {
      onDelete: 'cascade',
    }),

    /** Completion is a timestamp, never a boolean: when matters as much as whether. */
    completedAt: timestamp('completed_at', { withTimezone: true }),

    createdByUserId: uuid('created_by_user_id').references(() => users.id, {
      onDelete: 'set null',
    }),

    createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
  },
  (t) => [
    /** The quarter query scans by date; the "my calendar" view scans by owner. */
    index('calendar_entries_starts_idx').on(t.startsAt),
    index('calendar_entries_owner_idx').on(t.ownerUserId),
    index('calendar_entries_account_idx').on(t.accountId),
  ],
);

export type CalendarEntry = typeof calendarEntries.$inferSelect;
export type NewCalendarEntry = typeof calendarEntries.$inferInsert;
