import { boolean, integer, jsonb, pgEnum, pgTable, text, timestamp, uniqueIndex } from "drizzle-orm/pg-core";
import { intId, intPk } from "./columns";

export const roleEnum = pgEnum("role", [
  "owner",
  "admin",
  "member",
  "multi_channel_guest",
  "single_channel_guest",
  "bot",
]);

export const organizations = pgTable("organizations", {
  id: intPk(),
  name: text("name").notNull(),
  plan: text("plan").notNull().default("free"),
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
});

export const workspaces = pgTable(
  "workspaces",
  {
    id: intPk(),
    orgId: intId("org_id")
      .notNull()
      .references(() => organizations.id),
    slug: text("slug").notNull(),
    name: text("name").notNull(),
    iconUrl: text("icon_url"),
    settings: jsonb("settings").notNull().default({}),
    retentionDays: integer("retention_days"),
    createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
  },
  (t) => [uniqueIndex("workspaces_slug_idx").on(t.slug)],
);

export const users = pgTable(
  "users",
  {
    id: intPk(),
    email: text("email").notNull(),
    emailVerifiedAt: timestamp("email_verified_at", { withTimezone: true }),
    passwordHash: text("password_hash").notNull(),
    name: text("name").notNull(),
    // Global, not per-workspace — a real per-workspace handle system is a
    // bigger feature (Slack's own handles are workspace-scoped); this is the
    // minimum needed to resolve @mentions to a user id (see libs/core/mentions
    // + libs/messaging/sendMessage). Auto-generated at signup from the email
    // local-part if not chosen; never null after that, so mention resolution
    // can always join on it.
    username: text("username").notNull(),
    avatarUrl: text("avatar_url"),
    tz: text("tz").notNull().default("UTC"),
    mfaSecret: text("mfa_secret"),
    createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
  },
  (t) => [uniqueIndex("users_email_idx").on(t.email), uniqueIndex("users_username_idx").on(t.username)],
);

export const workspaceMembers = pgTable(
  "workspace_members",
  {
    workspaceId: intId("workspace_id")
      .notNull()
      .references(() => workspaces.id),
    userId: intId("user_id")
      .notNull()
      .references(() => users.id),
    role: roleEnum("role").notNull().default("member"),
    displayName: text("display_name"),
    title: text("title"),
    statusText: text("status_text"),
    statusEmoji: text("status_emoji"),
    statusExpiresAt: timestamp("status_expires_at", { withTimezone: true }),
    availabilityMode: text("availability_mode").notNull().default("auto"),
    dndEnabled: boolean("dnd_enabled").notNull().default(false),
    dndUntil: timestamp("dnd_until", { withTimezone: true }),
    autoStatusConnect: boolean("auto_status_connect").notNull().default(true),
    autoStatusFocus: boolean("auto_status_focus").notNull().default(true),
    autoStatusOutsideHours: boolean("auto_status_outside_hours").notNull().default(true),
    focusModeEnabled: boolean("focus_mode_enabled").notNull().default(false),
    inConnect: boolean("in_connect").notNull().default(false),
    workHoursStart: text("work_hours_start").notNull().default("09:00"),
    workHoursEnd: text("work_hours_end").notNull().default("17:00"),
    workingDays: jsonb("working_days").notNull().default([1, 2, 3, 4, 5]),
    joinedAt: timestamp("joined_at", { withTimezone: true }).notNull().defaultNow(),
    deactivatedAt: timestamp("deactivated_at", { withTimezone: true }),
  },
  (t) => [uniqueIndex("workspace_members_pk").on(t.workspaceId, t.userId)],
);

/**
 * Account-synced notification choices for one workspace. Channel-specific
 * overrides continue to live on channel_members; these are the global defaults
 * consumed by the browser/desktop notification router on every device.
 */
export const notificationPreferences = pgTable(
  "notification_preferences",
  {
    id: intPk(),
    workspaceId: intId("workspace_id")
      .notNull()
      .references(() => workspaces.id, { onDelete: "cascade" }),
    userId: intId("user_id")
      .notNull()
      .references(() => users.id, { onDelete: "cascade" }),
    messages: text("messages").notNull().default("all"),
    calls: boolean("calls").notNull().default(true),
    tasks: boolean("tasks").notNull().default(true),
    calendar: boolean("calendar").notNull().default(true),
    sound: boolean("sound").notNull().default(true),
    /** Right-side in-app flash toasts (independent of OS desktop notifications). */
    inAppFlash: boolean("in_app_flash").notNull().default(true),
    updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
  },
  (t) => [uniqueIndex("notification_preferences_user_workspace_idx").on(t.userId, t.workspaceId)],
);

export const scheduledStatuses = pgTable(
  "scheduled_statuses",
  {
    id: intPk(),
    workspaceId: intId("workspace_id")
      .notNull()
      .references(() => workspaces.id),
    userId: intId("user_id")
      .notNull()
      .references(() => users.id),
    text: text("text").notNull(),
    emoji: text("emoji").notNull().default("💬"),
    startsAt: timestamp("starts_at", { withTimezone: true }).notNull(),
    endsAt: timestamp("ends_at", { withTimezone: true }).notNull(),
    pauseNotifications: boolean("pause_notifications").notNull().default(false),
    createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
  },
  (t) => [uniqueIndex("scheduled_statuses_user_start_idx").on(t.workspaceId, t.userId, t.startsAt)],
);

export const sessions = pgTable("sessions", {
  id: intPk(),
  userId: intId("user_id")
    .notNull()
    .references(() => users.id),
  refreshTokenHash: text("refresh_token_hash").notNull(),
  deviceLabel: text("device_label"),
  ip: text("ip"),
  userAgent: text("user_agent"),
  rotatedFrom: intId("rotated_from"),
  revokedAt: timestamp("revoked_at", { withTimezone: true }),
  expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(),
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
});

export const invites = pgTable("invites", {
  id: intPk(),
  workspaceId: intId("workspace_id")
    .notNull()
    .references(() => workspaces.id),
  email: text("email"),
  invitedByUserId: intId("invited_by_user_id").references(() => users.id),
  tokenHash: text("token_hash").notNull(),
  role: roleEnum("role").notNull().default("member"),
  expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(),
  usedAt: timestamp("used_at", { withTimezone: true }),
  maxUses: integer("max_uses").notNull().default(1),
  useCount: integer("use_count").notNull().default(0),
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
});

export const notifications = pgTable("notifications", {
  id: intPk(),
  userId: intId("user_id")
    .notNull()
    .references(() => users.id),
  type: text("type").notNull(),
  title: text("title").notNull(),
  body: text("body").notNull(),
  payload: jsonb("payload").notNull().default({}),
  readAt: timestamp("read_at", { withTimezone: true }),
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
});
