/**
 * Communications (Harvest Reach).
 * Source: `db/migrations/0001_init.sql`.
 */
import {
  pgTable,
  uuid,
  text,
  integer,
  boolean,
  timestamp,
  jsonb,
  index,
  uniqueIndex,
} from "drizzle-orm/pg-core";
import { brands, adminUsers } from "./brands";

export const communicationSettings = pgTable(
  "communication_settings",
  {
    id: uuid("id").primaryKey().defaultRandom(),
    brandId: uuid("brand_id")
      .notNull()
      .unique()
      .references(() => brands.id, { onDelete: "cascade" }),
    defaultSenderEmail: text("default_sender_email"),
    defaultSenderName: text("default_sender_name"),
    replyToEmail: text("reply_to_email"),
    emailProvider: text("email_provider").notNull().default("resend"),
    emailFooterHtml: text("email_footer_html"),
    createdAt: timestamp("created_at", { withTimezone: true })
      .notNull()
      .defaultNow(),
    updatedAt: timestamp("updated_at", { withTimezone: true })
      .notNull()
      .defaultNow(),
  },
);

export const communicationTemplates = pgTable(
  "communication_templates",
  {
    id: uuid("id").primaryKey().defaultRandom(),
    brandId: uuid("brand_id")
      .notNull()
      .references(() => brands.id, { onDelete: "cascade" }),
    name: text("name").notNull(),
    subject: text("subject").notNull(),
    bodyText: text("body_text").notNull().default(""),
    bodyHtml: text("body_html"),
    templateType: text("template_type").notNull(),
    campaignType: text("campaign_type"),
    createdBy: uuid("created_by"),
    createdAt: timestamp("created_at", { withTimezone: true })
      .notNull()
      .defaultNow(),
    updatedAt: timestamp("updated_at", { withTimezone: true })
      .notNull()
      .defaultNow(),
  },
  (t) => ({
    brandIdx: index("communication_templates_brand_idx").on(t.brandId),
  }),
);

export const communicationSegments = pgTable(
  "communication_segments",
  {
    id: uuid("id").primaryKey().defaultRandom(),
    brandId: uuid("brand_id")
      .notNull()
      .references(() => brands.id, { onDelete: "cascade" }),
    name: text("name").notNull(),
    description: text("description"),
    rules: jsonb("rules").notNull().default({}),
    createdBy: uuid("created_by"),
    createdAt: timestamp("created_at", { withTimezone: true })
      .notNull()
      .defaultNow(),
    updatedAt: timestamp("updated_at", { withTimezone: true })
      .notNull()
      .defaultNow(),
  },
  (t) => ({
    brandIdx: index("communication_segments_brand_idx").on(t.brandId),
  }),
);

export const communicationCampaigns = pgTable(
  "communication_campaigns",
  {
    id: uuid("id").primaryKey().defaultRandom(),
    brandId: uuid("brand_id")
      .notNull()
      .references(() => brands.id, { onDelete: "cascade" }),
    name: text("name").notNull(),
    subject: text("subject"),
    bodyText: text("body_text"),
    bodyHtml: text("body_html"),
    templateId: uuid("template_id").references(
      () => communicationTemplates.id,
      { onDelete: "set null" },
    ),
    campaignType: text("campaign_type").notNull(),
    status: text("status", {
      enum: ["draft", "scheduled", "sending", "sent", "canceled"],
    }).notNull().default("draft"),
    audienceRules: jsonb("audience_rules").notNull().default({}),
    brandName: text("brand_name"),
    scheduledAt: timestamp("scheduled_at", { withTimezone: true }),
    sentAt: timestamp("sent_at", { withTimezone: true }),
    recipientCount: integer("recipient_count").notNull().default(0),
    createdBy: uuid("created_by"),
    createdAt: timestamp("created_at", { withTimezone: true })
      .notNull()
      .defaultNow(),
    updatedAt: timestamp("updated_at", { withTimezone: true })
      .notNull()
      .defaultNow(),
  },
  (t) => ({
    brandIdx: index("communication_campaigns_brand_idx").on(t.brandId),
    statusIdx: index("communication_campaigns_status_idx").on(
      t.brandId,
      t.status,
    ),
  }),
);

export const communicationContacts = pgTable(
  "communication_contacts",
  {
    id: uuid("id").primaryKey().defaultRandom(),
    brandId: uuid("brand_id")
      .notNull()
      .references(() => brands.id, { onDelete: "cascade" }),
    email: text("email"),
    phone: text("phone"),
    firstName: text("first_name"),
    lastName: text("last_name"),
    fullName: text("full_name"),
    source: text("source").notNull(),
    externalId: text("external_id"),
    customerId: uuid("customer_id"),
    emailOptIn: boolean("email_opt_in").notNull().default(true),
    smsOptIn: boolean("sms_opt_in").notNull().default(false),
    emailOptInAt: timestamp("email_opt_in_at", { withTimezone: true }),
    smsOptInAt: timestamp("sms_opt_in_at", { withTimezone: true }),
    unsubscribedAt: timestamp("unsubscribed_at", { withTimezone: true }),
    tags: text("tags").array().default([]),
    metadata: jsonb("metadata").default({}),
    createdAt: timestamp("created_at", { withTimezone: true })
      .notNull()
      .defaultNow(),
    updatedAt: timestamp("updated_at", { withTimezone: true })
      .notNull()
      .defaultNow(),
  },
  (t) => ({
    brandIdx: index("communication_contacts_brand_idx").on(t.brandId),
    emailIdx: index("communication_contacts_email_idx").on(
      t.brandId,
      t.email,
    ),
  }),
);

export const communicationMessageLogs = pgTable(
  "communication_message_logs",
  {
    id: uuid("id").primaryKey().defaultRandom(),
    brandId: uuid("brand_id")
      .notNull()
      .references(() => brands.id, { onDelete: "cascade" }),
    campaignId: uuid("campaign_id").references(
      () => communicationCampaigns.id,
      { onDelete: "set null" },
    ),
    contactId: uuid("contact_id").references(
      () => communicationContacts.id,
      { onDelete: "set null" },
    ),
    customerEmail: text("customer_email"),
    deliveryMethod: text("delivery_method").notNull(),
    subject: text("subject"),
    bodyPreview: text("body_preview"),
    status: text("status").notNull(),
    sentAt: timestamp("sent_at", { withTimezone: true }),
    errorMessage: text("error_message"),
    eventType: text("event_type"),
    eventId: uuid("event_id"),
    createdAt: timestamp("created_at", { withTimezone: true })
      .notNull()
      .defaultNow(),
  },
  (t) => ({
    brandIdx: index("communication_message_logs_brand_idx").on(t.brandId),
    campaignIdx: index(
      "communication_message_logs_campaign_idx",
    ).on(t.campaignId),
  }),
);

export const customerCommunicationPreferences = pgTable(
  "customer_communication_preferences",
  {
    id: uuid("id").primaryKey().defaultRandom(),
    customerId: uuid("customer_id").notNull(),
    brandId: uuid("brand_id")
      .notNull()
      .references(() => brands.id, { onDelete: "cascade" }),
    emailOptIn: boolean("email_opt_in").notNull().default(true),
    smsOptIn: boolean("sms_opt_in").notNull().default(false),
    emailOptInAt: timestamp("email_opt_in_at", { withTimezone: true }),
    smsOptInAt: timestamp("sms_opt_in_at", { withTimezone: true }),
    createdAt: timestamp("created_at", { withTimezone: true })
      .notNull()
      .defaultNow(),
    updatedAt: timestamp("updated_at", { withTimezone: true })
      .notNull()
      .defaultNow(),
  },
  (t) => ({
    customerBrandIdx: uniqueIndex(
      "customer_communication_prefs_customer_brand_idx",
    ).on(t.customerId, t.brandId),
  }),
);

// Email automation sequences
export const abandonedCartRecovery = pgTable(
  "abandoned_cart_recovery",
  {
    id: uuid("id").primaryKey().defaultRandom(),
    brandId: uuid("brand_id")
      .notNull()
      .references(() => brands.id, { onDelete: "cascade" }),
    customerId: uuid("customer_id"),
    contactEmail: text("contact_email").notNull(),
    contactName: text("contact_name"),
    cartSnapshot: jsonb("cart_snapshot").notNull(),
    brandName: text("brand_name"),
    locale: text("locale").default("en"),
    sequenceStep: integer("sequence_step").default(0),
    lastEmailSentAt: timestamp("last_email_sent_at", {
      withTimezone: true,
    }),
    nextEmailAt: timestamp("next_email_at", { withTimezone: true }),
    status: text("status", {
      enum: ["active", "recovered", "expired", "manually_closed"],
    }).default("active"),
    recoveredOrderId: uuid("recovered_order_id"),
    recoveredAt: timestamp("recovered_at", { withTimezone: true }),
    expiredAt: timestamp("expired_at", { withTimezone: true }),
    manuallyClosedAt: timestamp("manually_closed_at", {
      withTimezone: true,
    }),
    manuallyClosedBy: uuid("manually_closed_by").references(
      () => adminUsers.id,
    ),
    createdAt: timestamp("created_at", { withTimezone: true })
      .notNull()
      .defaultNow(),
    updatedAt: timestamp("updated_at", { withTimezone: true })
      .notNull()
      .defaultNow(),
  },
);

export const welcomeEmailSequence = pgTable(
  "welcome_email_sequence",
  {
    id: uuid("id").primaryKey().defaultRandom(),
    brandId: uuid("brand_id")
      .notNull()
      .references(() => brands.id, { onDelete: "cascade" }),
    contactId: uuid("contact_id").references(
      () => communicationContacts.id,
      { onDelete: "cascade" },
    ),
    contactEmail: text("contact_email").notNull(),
    contactName: text("contact_name"),
    brandName: text("brand_name"),
    locale: text("locale").default("en"),
    sequenceStep: integer("sequence_step").default(0),
    lastEmailSentAt: timestamp("last_email_sent_at", {
      withTimezone: true,
    }),
    nextEmailAt: timestamp("next_email_at", { withTimezone: true }),
    status: text("status", {
      enum: ["active", "completed", "unsubscribed", "bounced"],
    }).default("active"),
    completedAt: timestamp("completed_at", { withTimezone: true }),
    unsubscribedAt: timestamp("unsubscribed_at", { withTimezone: true }),
    bouncedAt: timestamp("bounced_at", { withTimezone: true }),
    createdAt: timestamp("created_at", { withTimezone: true })
      .notNull()
      .defaultNow(),
    updatedAt: timestamp("updated_at", { withTimezone: true })
      .notNull()
      .defaultNow(),
  },
);

export type CommunicationSettings =
  typeof communicationSettings.$inferSelect;
export type CommunicationTemplate = typeof communicationTemplates.$inferSelect;
export type CommunicationSegment = typeof communicationSegments.$inferSelect;
export type CommunicationCampaign = typeof communicationCampaigns.$inferSelect;
export type CommunicationContact = typeof communicationContacts.$inferSelect;
export type CommunicationMessageLog = typeof communicationMessageLogs.$inferSelect;
export type CustomerCommunicationPreference =
  typeof customerCommunicationPreferences.$inferSelect;
export type AbandonedCartRecovery = typeof abandonedCartRecovery.$inferSelect;
export type WelcomeEmailSequence = typeof welcomeEmailSequence.$inferSelect;