import {
  pgTable,
  text,
  timestamp,
  uuid,
  pgEnum,
  integer,
  bigint,
  boolean,
  jsonb,
  uniqueIndex,
  index,
} from "drizzle-orm/pg-core";
import { families } from "./family";

// ---------------------------------------------------------------------------
// Billing schema — Razorpay subscriptions.
//
// Design:
//  - Mirror Razorpay's lifecycle states exactly (don't invent a vocabulary).
//  - razorpay_webhook_events is APPEND-ONLY; razorpay_event_id is the
//    idempotency key (webhooks WILL be redelivered).
//  - Entitlement is synced onto families.tier by the webhook — the existing
//    quota.ts guards (isPaidFamily) keep working unchanged. These tables are
//    the audit trail + Razorpay state mirror, not a second enforcement path.
// ---------------------------------------------------------------------------

// Mirror Razorpay's subscription lifecycle states exactly.
export const subscriptionStatusEnum = pgEnum("subscription_status_enum", [
  "created", // sub created, not yet authenticated
  "authenticated", // mandate set up (future-dated starts sit here)
  "active", // charged & live — THE entitled state
  "pending", // a charge failed; Razorpay is retrying (still entitled = grace)
  "halted", // retries exhausted — downgrade
  "cancelled", // user/we cancelled
  "completed", // all total_count cycles done
  "expired",
  "paused",
]);

// Maps a Razorpay plan_id -> what it grants. Source of grant values.
export const subscriptionPlans = pgTable("subscription_plans", {
  id: uuid("id").primaryKey().defaultRandom(),
  razorpayPlanId: text("razorpay_plan_id").notNull().unique(), // plan_xxx from RZP
  name: text("name").notNull(), // "Tia Premium"
  pricePaise: integer("price_paise").notNull(), // 19900 = ₹199
  storageBytes: bigint("storage_bytes", { mode: "number" }).notNull(), // the grant
  memberLimit: integer("member_limit").notNull(), // the grant
  childLimit: integer("child_limit").notNull().default(3), // the grant
  isActive: boolean("is_active").notNull().default(true),
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
});

// One non-terminal subscription per family (enforced by partial unique index).
export const familySubscriptions = pgTable(
  "family_subscriptions",
  {
    id: uuid("id").primaryKey().defaultRandom(),
    familyId: uuid("family_id")
      .notNull()
      .references(() => families.id, { onDelete: "cascade" }),
    planId: uuid("plan_id")
      .notNull()
      .references(() => subscriptionPlans.id),
    razorpaySubscriptionId: text("razorpay_subscription_id").notNull().unique(),
    razorpayCustomerId: text("razorpay_customer_id"), // captured from webhook
    status: subscriptionStatusEnum("status").notNull().default("created"),
    currentStart: timestamp("current_start", { withTimezone: true }),
    currentEnd: timestamp("current_end", { withTimezone: true }), // entitlement valid until
    cancelledAt: timestamp("cancelled_at", { withTimezone: true }),
    endedAt: timestamp("ended_at", { withTimezone: true }),
    createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
    updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
  },
  (table) => [index("family_subscriptions_family_idx").on(table.familyId)]
);

// Append-only. razorpay_event_id is the idempotency key.
export const razorpayWebhookEvents = pgTable("razorpay_webhook_events", {
  id: uuid("id").primaryKey().defaultRandom(),
  razorpayEventId: text("razorpay_event_id").notNull().unique(), // x-razorpay-event-id header
  eventType: text("event_type").notNull(),
  payload: jsonb("payload").notNull(),
  receivedAt: timestamp("received_at", { withTimezone: true }).notNull().defaultNow(),
});

// Type exports
export type SubscriptionPlan = typeof subscriptionPlans.$inferSelect;
export type FamilySubscription = typeof familySubscriptions.$inferSelect;
export type RazorpayWebhookEvent = typeof razorpayWebhookEvents.$inferSelect;
