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

export const tenantStatusEnum = pgEnum("tenant_status", [
  "pending",
  "active",
  "suspended",
  "archived",
]);

export const userStatusEnum = pgEnum("user_status", [
  "active",
  "disabled",
  "pending_verification",
]);

export const tenantRoleEnum = pgEnum("tenant_role", [
  "owner",
  "manager",
  "editor",
  "contributor",
]);

export const platformRoleEnum = pgEnum("platform_role", [
  "super_admin",
  "platform_admin",
  "support",
  "none",
]);

export const domainTypeEnum = pgEnum("domain_type", [
  "subdomain",
  "custom",
]);

export const domainVerificationStatusEnum = pgEnum(
  "domain_verification_status",
  ["pending", "verified", "failed", "revoked"],
);

export const sslStatusEnum = pgEnum("ssl_status", [
  "pending",
  "active",
  "failed",
  "expired",
]);

export const projectStatusEnum = pgEnum("project_status", [
  "draft",
  "published",
  "archived",
]);

export const inquiryStatusEnum = pgEnum("inquiry_status", [
  "new",
  "qualified",
  "consultation",
  "proposal",
  "won",
  "lost",
]);

export const subscriptionStatusEnum = pgEnum("subscription_status", [
  "trialing",
  "active",
  "past_due",
  "canceled",
  "incomplete",
]);

export const journalStatusEnum = pgEnum("journal_status", [
  "draft",
  "published",
  "archived",
]);

const timestamps = {
  createdAt: timestamp("created_at", { withTimezone: true })
    .notNull()
    .defaultNow(),
  updatedAt: timestamp("updated_at", { withTimezone: true })
    .notNull()
    .defaultNow(),
};

export const tenants = pgTable(
  "tenants",
  {
    id: uuid("id").defaultRandom().primaryKey(),
    studioName: text("studio_name").notNull(),
    slug: text("slug").notNull(),
    status: tenantStatusEnum("status").notNull().default("pending"),
    logoStorageKey: text("logo_storage_key"),
    description: text("description"),
    ...timestamps,
  },
  (table) => [
    uniqueIndex("tenants_slug_uidx").on(table.slug),
    index("tenants_status_idx").on(table.status),
  ],
);

export const users = pgTable(
  "users",
  {
    id: uuid("id").defaultRandom().primaryKey(),
    name: text("name").notNull(),
    email: text("email").notNull(),
    pendingEmail: text("pending_email"),
    phone: text("phone"),
    passwordHash: text("password_hash"),
    status: userStatusEnum("status").notNull().default("pending_verification"),
    platformRole: platformRoleEnum("platform_role").notNull().default("none"),
    emailVerifiedAt: timestamp("email_verified_at", { withTimezone: true }),
    lastLoginAt: timestamp("last_login_at", { withTimezone: true }),
    mfaEnabled: boolean("mfa_enabled").notNull().default(false),
    ...timestamps,
  },
  (table) => [
    uniqueIndex("users_email_uidx").on(table.email),
    index("users_status_idx").on(table.status),
    index("users_pending_email_idx").on(table.pendingEmail),
  ],
);

export const tenantUsers = pgTable(
  "tenant_users",
  {
    id: uuid("id").defaultRandom().primaryKey(),
    tenantId: uuid("tenant_id")
      .notNull()
      .references(() => tenants.id, { onDelete: "cascade" }),
    userId: uuid("user_id")
      .notNull()
      .references(() => users.id, { onDelete: "cascade" }),
    role: tenantRoleEnum("role").notNull().default("contributor"),
    permissions: jsonb("permissions").$type<string[]>().notNull().default([]),
    status: text("status").notNull().default("active"),
    ...timestamps,
  },
  (table) => [
    uniqueIndex("tenant_users_tenant_user_uidx").on(
      table.tenantId,
      table.userId,
    ),
    index("tenant_users_user_idx").on(table.userId),
    index("tenant_users_tenant_idx").on(table.tenantId),
  ],
);

export const architectProfiles = pgTable(
  "architect_profiles",
  {
    id: uuid("id").defaultRandom().primaryKey(),
    tenantId: uuid("tenant_id")
      .notNull()
      .references(() => tenants.id, { onDelete: "cascade" }),
    tagline: text("tagline"),
    about: text("about"),
    architectName: text("architect_name"),
    architectTitle: text("architect_title"),
    architectPhotoStorageKey: text("architect_photo_storage_key"),
    philosophy: text("philosophy"),
    vision: text("vision"),
    mission: text("mission"),
    approach: text("approach"),
    designPrinciples: text("design_principles"),
    experience: text("experience"),
    studioCulture: text("studio_culture"),
    workspace: text("workspace"),
    methodology: text("methodology"),
    collaborations: text("collaborations"),
    location: text("location"),
    foundedYear: integer("founded_year"),
    websiteUrl: text("website_url"),
    publicEmail: text("public_email"),
    phone: text("phone"),
    whatsapp: text("whatsapp"),
    businessHours: text("business_hours"),
    mapEmbedUrl: text("map_embed_url"),
    socialLinks: jsonb("social_links").$type<Record<string, string>>().default({}),
    branding: jsonb("branding")
      .$type<{
        primaryColor?: string;
        secondaryColor?: string;
        accentColor?: string;
        fontDisplay?: string;
        fontBody?: string;
      }>()
      .default({}),
    seoTitle: text("seo_title"),
    seoDescription: text("seo_description"),
    ...timestamps,
  },
  (table) => [
    uniqueIndex("architect_profiles_tenant_uidx").on(table.tenantId),
  ],
);

export const domains = pgTable(
  "domains",
  {
    id: uuid("id").defaultRandom().primaryKey(),
    tenantId: uuid("tenant_id")
      .notNull()
      .references(() => tenants.id, { onDelete: "cascade" }),
    domain: text("domain").notNull(),
    normalizedDomain: text("normalized_domain").notNull(),
    type: domainTypeEnum("type").notNull(),
    verificationStatus: domainVerificationStatusEnum("verification_status")
      .notNull()
      .default("pending"),
    verificationToken: text("verification_token"),
    sslStatus: sslStatusEnum("ssl_status").notNull().default("pending"),
    isPrimary: boolean("is_primary").notNull().default(false),
    verifiedAt: timestamp("verified_at", { withTimezone: true }),
    ...timestamps,
  },
  (table) => [
    uniqueIndex("domains_normalized_uidx").on(table.normalizedDomain),
    index("domains_tenant_idx").on(table.tenantId),
    index("domains_verification_idx").on(table.verificationStatus),
  ],
);

export const projectCategories = pgTable(
  "project_categories",
  {
    id: uuid("id").defaultRandom().primaryKey(),
    tenantId: uuid("tenant_id")
      .notNull()
      .references(() => tenants.id, { onDelete: "cascade" }),
    name: text("name").notNull(),
    slug: text("slug").notNull(),
    description: text("description"),
    sortOrder: integer("sort_order").notNull().default(0),
    ...timestamps,
  },
  (table) => [
    uniqueIndex("project_categories_tenant_slug_uidx").on(
      table.tenantId,
      table.slug,
    ),
    index("project_categories_tenant_idx").on(table.tenantId),
  ],
);

export const projects = pgTable(
  "projects",
  {
    id: uuid("id").defaultRandom().primaryKey(),
    tenantId: uuid("tenant_id")
      .notNull()
      .references(() => tenants.id, { onDelete: "cascade" }),
    categoryId: uuid("category_id").references(() => projectCategories.id, {
      onDelete: "set null",
    }),
    title: text("title").notNull(),
    slug: text("slug").notNull(),
    description: text("description"),
    concept: text("concept"),
    designProcess: text("design_process"),
    materials: text("materials"),
    location: text("location"),
    year: integer("year"),
    area: text("area"),
    clientName: text("client_name"),
    architectCredit: text("architect_credit"),
    projectType: text("project_type"),
    status: projectStatusEnum("status").notNull().default("draft"),
    heroStorageKey: text("hero_storage_key"),
    modelStorageKey: text("model_storage_key"),
    videoUrl: text("video_url"),
    isFeatured3d: boolean("is_featured_3d").notNull().default(false),
    seoTitle: text("seo_title"),
    seoDescription: text("seo_description"),
    publishedAt: timestamp("published_at", { withTimezone: true }),
    deletedAt: timestamp("deleted_at", { withTimezone: true }),
    ...timestamps,
  },
  (table) => [
    uniqueIndex("projects_tenant_slug_uidx").on(table.tenantId, table.slug),
    index("projects_tenant_status_idx").on(table.tenantId, table.status),
    index("projects_tenant_created_idx").on(table.tenantId, table.createdAt),
    index("projects_published_idx").on(table.publishedAt),
  ],
);

export const projectMedia = pgTable(
  "project_media",
  {
    id: uuid("id").defaultRandom().primaryKey(),
    tenantId: uuid("tenant_id")
      .notNull()
      .references(() => tenants.id, { onDelete: "cascade" }),
    projectId: uuid("project_id")
      .notNull()
      .references(() => projects.id, { onDelete: "cascade" }),
    storageKey: text("storage_key").notNull(),
    fileType: text("file_type").notNull(),
    mimeType: text("mime_type").notNull(),
    fileSize: integer("file_size").notNull(),
    altText: text("alt_text"),
    sortOrder: integer("sort_order").notNull().default(0),
    ...timestamps,
  },
  (table) => [
    index("project_media_tenant_project_idx").on(
      table.tenantId,
      table.projectId,
    ),
    index("project_media_tenant_idx").on(table.tenantId),
  ],
);

export const services = pgTable(
  "services",
  {
    id: uuid("id").defaultRandom().primaryKey(),
    tenantId: uuid("tenant_id")
      .notNull()
      .references(() => tenants.id, { onDelete: "cascade" }),
    title: text("title").notNull(),
    slug: text("slug").notNull(),
    description: text("description"),
    sortOrder: integer("sort_order").notNull().default(0),
    isPublished: boolean("is_published").notNull().default(true),
    ...timestamps,
  },
  (table) => [
    uniqueIndex("services_tenant_slug_uidx").on(table.tenantId, table.slug),
    index("services_tenant_idx").on(table.tenantId),
  ],
);

export const journalPosts = pgTable(
  "journal_posts",
  {
    id: uuid("id").defaultRandom().primaryKey(),
    tenantId: uuid("tenant_id")
      .notNull()
      .references(() => tenants.id, { onDelete: "cascade" }),
    title: text("title").notNull(),
    slug: text("slug").notNull(),
    excerpt: text("excerpt"),
    content: text("content"),
    coverStorageKey: text("cover_storage_key"),
    status: journalStatusEnum("status").notNull().default("draft"),
    seoTitle: text("seo_title"),
    seoDescription: text("seo_description"),
    publishedAt: timestamp("published_at", { withTimezone: true }),
    deletedAt: timestamp("deleted_at", { withTimezone: true }),
    ...timestamps,
  },
  (table) => [
    uniqueIndex("journal_posts_tenant_slug_uidx").on(
      table.tenantId,
      table.slug,
    ),
    index("journal_posts_tenant_status_idx").on(table.tenantId, table.status),
  ],
);

export const awards = pgTable(
  "awards",
  {
    id: uuid("id").defaultRandom().primaryKey(),
    tenantId: uuid("tenant_id")
      .notNull()
      .references(() => tenants.id, { onDelete: "cascade" }),
    title: text("title").notNull(),
    organization: text("organization"),
    year: integer("year"),
    category: text("category"),
    description: text("description"),
    imageStorageKey: text("image_storage_key"),
    sortOrder: integer("sort_order").notNull().default(0),
    isPublished: boolean("is_published").notNull().default(true),
    ...timestamps,
  },
  (table) => [
    index("awards_tenant_idx").on(table.tenantId),
    index("awards_tenant_published_idx").on(table.tenantId, table.isPublished),
  ],
);

export const teamMembers = pgTable(
  "team_members",
  {
    id: uuid("id").defaultRandom().primaryKey(),
    tenantId: uuid("tenant_id")
      .notNull()
      .references(() => tenants.id, { onDelete: "cascade" }),
    name: text("name").notNull(),
    slug: text("slug").notNull(),
    role: text("role"),
    bio: text("bio"),
    email: text("email"),
    photoStorageKey: text("photo_storage_key"),
    sortOrder: integer("sort_order").notNull().default(0),
    isPublished: boolean("is_published").notNull().default(true),
    ...timestamps,
  },
  (table) => [
    uniqueIndex("team_members_tenant_slug_uidx").on(table.tenantId, table.slug),
    index("team_members_tenant_idx").on(table.tenantId),
  ],
);

export const publications = pgTable(
  "publications",
  {
    id: uuid("id").defaultRandom().primaryKey(),
    tenantId: uuid("tenant_id")
      .notNull()
      .references(() => tenants.id, { onDelete: "cascade" }),
    title: text("title").notNull(),
    publisher: text("publisher"),
    year: integer("year"),
    url: text("url"),
    kind: text("kind"),
    description: text("description"),
    coverStorageKey: text("cover_storage_key"),
    sortOrder: integer("sort_order").notNull().default(0),
    isPublished: boolean("is_published").notNull().default(true),
    ...timestamps,
  },
  (table) => [
    index("publications_tenant_idx").on(table.tenantId),
    index("publications_tenant_published_idx").on(
      table.tenantId,
      table.isPublished,
    ),
  ],
);

export const plans = pgTable("plans", {
  id: uuid("id").defaultRandom().primaryKey(),
  code: text("code").notNull().unique(),
  name: text("name").notNull(),
  description: text("description"),
  entitlements: jsonb("entitlements")
    .$type<Record<string, boolean | number>>()
    .notNull()
    .default({}),
  isActive: boolean("is_active").notNull().default(true),
  ...timestamps,
});

export const subscriptions = pgTable(
  "subscriptions",
  {
    id: uuid("id").defaultRandom().primaryKey(),
    tenantId: uuid("tenant_id")
      .notNull()
      .references(() => tenants.id, { onDelete: "cascade" }),
    planId: uuid("plan_id")
      .notNull()
      .references(() => plans.id),
    status: subscriptionStatusEnum("status").notNull().default("trialing"),
    currentPeriodStart: timestamp("current_period_start", {
      withTimezone: true,
    }),
    currentPeriodEnd: timestamp("current_period_end", { withTimezone: true }),
    cancelAtPeriodEnd: boolean("cancel_at_period_end").notNull().default(false),
    providerCustomerId: text("provider_customer_id"),
    providerSubscriptionId: text("provider_subscription_id"),
    ...timestamps,
  },
  (table) => [
    uniqueIndex("subscriptions_tenant_uidx").on(table.tenantId),
    index("subscriptions_status_idx").on(table.status),
  ],
);

export const payments = pgTable(
  "payments",
  {
    id: uuid("id").defaultRandom().primaryKey(),
    tenantId: uuid("tenant_id")
      .notNull()
      .references(() => tenants.id, { onDelete: "cascade" }),
    subscriptionId: uuid("subscription_id").references(() => subscriptions.id, {
      onDelete: "set null",
    }),
    amountCents: integer("amount_cents").notNull(),
    currency: text("currency").notNull().default("usd"),
    status: text("status").notNull(),
    providerPaymentId: text("provider_payment_id"),
    idempotencyKey: text("idempotency_key"),
    metadata: jsonb("metadata").$type<Record<string, unknown>>().default({}),
    ...timestamps,
  },
  (table) => [
    index("payments_tenant_idx").on(table.tenantId),
    uniqueIndex("payments_idempotency_uidx").on(table.idempotencyKey),
  ],
);

export const inquiries = pgTable(
  "inquiries",
  {
    id: uuid("id").defaultRandom().primaryKey(),
    tenantId: uuid("tenant_id")
      .notNull()
      .references(() => tenants.id, { onDelete: "cascade" }),
    name: text("name").notNull(),
    email: text("email").notNull(),
    phone: text("phone"),
    projectType: text("project_type"),
    budget: text("budget"),
    location: text("location"),
    timeline: text("timeline"),
    projectSize: text("project_size"),
    message: text("message").notNull(),
    attachmentStorageKey: text("attachment_storage_key"),
    status: inquiryStatusEnum("status").notNull().default("new"),
    ...timestamps,
  },
  (table) => [
    index("inquiries_tenant_status_idx").on(table.tenantId, table.status),
    index("inquiries_tenant_created_idx").on(table.tenantId, table.createdAt),
  ],
);

export const analyticsEvents = pgTable(
  "analytics_events",
  {
    id: uuid("id").defaultRandom().primaryKey(),
    tenantId: uuid("tenant_id")
      .notNull()
      .references(() => tenants.id, { onDelete: "cascade" }),
    event: text("event").notNull(),
    path: text("path"),
    referrer: text("referrer"),
    deviceType: text("device_type"),
    countryCode: text("country_code"),
    sessionId: text("session_id"),
    metadata: jsonb("metadata").$type<Record<string, unknown>>().default({}),
    createdAt: timestamp("created_at", { withTimezone: true })
      .notNull()
      .defaultNow(),
  },
  (table) => [
    index("analytics_events_tenant_created_idx").on(
      table.tenantId,
      table.createdAt,
    ),
    index("analytics_events_tenant_event_idx").on(table.tenantId, table.event),
  ],
);

export const notifications = pgTable(
  "notifications",
  {
    id: uuid("id").defaultRandom().primaryKey(),
    tenantId: uuid("tenant_id").references(() => tenants.id, {
      onDelete: "cascade",
    }),
    userId: uuid("user_id").references(() => users.id, {
      onDelete: "cascade",
    }),
    type: text("type").notNull(),
    title: text("title").notNull(),
    body: text("body"),
    isRead: boolean("is_read").notNull().default(false),
    metadata: jsonb("metadata").$type<Record<string, unknown>>().default({}),
    ...timestamps,
  },
  (table) => [
    index("notifications_tenant_user_idx").on(table.tenantId, table.userId),
    index("notifications_user_read_idx").on(table.userId, table.isRead),
  ],
);

export const auditLogs = pgTable(
  "audit_logs",
  {
    id: uuid("id").defaultRandom().primaryKey(),
    actorUserId: uuid("actor_user_id").references(() => users.id, {
      onDelete: "set null",
    }),
    tenantId: uuid("tenant_id").references(() => tenants.id, {
      onDelete: "set null",
    }),
    action: text("action").notNull(),
    targetType: text("target_type"),
    targetId: text("target_id"),
    ipAddress: text("ip_address"),
    userAgent: text("user_agent"),
    metadata: jsonb("metadata").$type<Record<string, unknown>>().default({}),
    createdAt: timestamp("created_at", { withTimezone: true })
      .notNull()
      .defaultNow(),
  },
  (table) => [
    index("audit_logs_tenant_created_idx").on(table.tenantId, table.createdAt),
    index("audit_logs_actor_created_idx").on(
      table.actorUserId,
      table.createdAt,
    ),
    index("audit_logs_action_idx").on(table.action),
  ],
);

/** Auth.js / NextAuth adapter tables */
export const accounts = pgTable(
  "accounts",
  {
    id: uuid("id").defaultRandom().primaryKey(),
    userId: uuid("user_id")
      .notNull()
      .references(() => users.id, { onDelete: "cascade" }),
    type: text("type").notNull(),
    provider: text("provider").notNull(),
    providerAccountId: text("provider_account_id").notNull(),
    refresh_token: text("refresh_token"),
    access_token: text("access_token"),
    expires_at: integer("expires_at"),
    token_type: text("token_type"),
    scope: text("scope"),
    id_token: text("id_token"),
    session_state: text("session_state"),
  },
  (table) => [
    uniqueIndex("accounts_provider_uidx").on(
      table.provider,
      table.providerAccountId,
    ),
  ],
);

export const sessions = pgTable("sessions", {
  id: uuid("id").defaultRandom().primaryKey(),
  sessionToken: text("session_token").notNull().unique(),
  userId: uuid("user_id")
    .notNull()
    .references(() => users.id, { onDelete: "cascade" }),
  expires: timestamp("expires", { withTimezone: true }).notNull(),
});

export const verificationTokens = pgTable(
  "verification_tokens",
  {
    identifier: text("identifier").notNull(),
    token: text("token").notNull(),
    expires: timestamp("expires", { withTimezone: true }).notNull(),
  },
  (table) => [
    uniqueIndex("verification_tokens_uidx").on(table.identifier, table.token),
  ],
);
