import { boolean, date, index, pgEnum, pgTable, text, timestamp, uniqueIndex, type AnyPgColumn } from "drizzle-orm/pg-core";
import { intId, intPk } from "./columns";
import { users, workspaces } from "./identity";
import { channels } from "./channels";

export const attendeeStatusEnum = pgEnum("attendee_status", ["needs_action", "going", "maybe", "declined"]);

export const events = pgTable(
  "events",
  {
    id: intPk(),
    workspaceId: intId("workspace_id")
      .notNull()
      .references(() => workspaces.id),
    title: text("title").notNull(),
    description: text("description"),
    location: text("location"),
    startsAt: timestamp("starts_at", { withTimezone: true }).notNull(),
    endsAt: timestamp("ends_at", { withTimezone: true }).notNull(),
    allDay: boolean("all_day").notNull().default(false),
    // The IANA zone the event was authored in. Instants alone can't express
    // "weekly at 9am" — across a DST shift the next occurrence's UTC offset
    // changes, so expansion has to step in wall-clock terms in this zone
    // (see libs/core/src/recurrence.ts).
    timezone: text("timezone").notNull().default("UTC"),
    // RFC 5545 subset, null for a one-off: FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,WE
    // Occurrences are expanded on read rather than materialised, so a series
    // is exactly one row here however far out it repeats.
    recurrenceRule: text("recurrence_rule"),
    // Optional context, not a scoping mechanism — same role channelId plays
    // on tasks. Events are workspace-wide.
    channelId: intId("channel_id").references(() => channels.id),
    createdBy: intId("created_by")
      .notNull()
      .references(() => users.id),
    // Detached-instance model (what Google Calendar's API calls an instance
    // override): a row with a parent represents ONE occurrence of that
    // series — either modified (its own title/times win) or cancelled.
    // occurrenceDate is the original start date it replaces, which is what
    // makes it addressable without materialising the whole series.
    parentEventId: intId("parent_event_id").references((): AnyPgColumn => events.id),
    occurrenceDate: date("occurrence_date"),
    isCancelled: boolean("is_cancelled").notNull().default(false),
    createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
    updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
  },
  (t) => [
    // Hot path for GET /workspaces/:id/events?from=&to=.
    index("events_workspace_starts_idx").on(t.workspaceId, t.startsAt),
    // Resolving a series' overrides/cancellations for a window.
    index("events_parent_occurrence_idx").on(t.parentEventId, t.occurrenceDate),
    index("events_channel_idx").on(t.channelId),
  ],
);

export const eventAttendees = pgTable(
  "event_attendees",
  {
    eventId: intId("event_id")
      .notNull()
      .references(() => events.id),
    userId: intId("user_id")
      .notNull()
      .references(() => users.id),
    status: attendeeStatusEnum("status").notNull().default("needs_action"),
    respondedAt: timestamp("responded_at", { withTimezone: true }),
    createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
  },
  (t) => [
    uniqueIndex("event_attendees_pk").on(t.eventId, t.userId),
    // "What am I invited to" — the reverse lookup.
    index("event_attendees_user_idx").on(t.userId),
  ],
);
