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

/**
 * Drizzle schema — the single source of truth for the database, replacing the
 * old Prisma schema (see docs). The database is Postgres; migrations are
 * generated with `drizzle-kit generate`. IDs are app-generated opaque strings
 * (was Prisma `cuid()`), timestamps default in the DB and bump on update.
 */

// `crypto.randomUUID()` is a global in Node 20+ and browsers (no node: import),
// so the schema stays safe to pull into a client bundle via lib/db/enums.
const id = () =>
  text("id")
    .primaryKey()
    .$defaultFn(() => crypto.randomUUID());

const createdAt = timestamp("created_at", { withTimezone: true }).notNull().defaultNow();
const updatedAt = timestamp("updated_at", { withTimezone: true })
  .notNull()
  .defaultNow()
  .$onUpdate(() => new Date());

// --- Enums ------------------------------------------------------------------

export const portfolioSectionType = pgEnum("portfolio_section_type", [
  "RICH_TEXT",
  "GALLERY",
  "STATS",
  "DELIVERABLES",
  "LINK",
]);

export const portfolioAssetKind = pgEnum("portfolio_asset_kind", ["IMAGE", "DOCUMENT"]);

export const portfolioProjectViewMode = pgEnum("portfolio_project_view_mode", [
  "GRID",
  "STORY",
  "CASE_STUDY",
]);

export const mediaSource = pgEnum("media_source", ["UPLOAD", "EXTERNAL"]);

export const mediaKind = pgEnum("media_kind", ["IMAGE", "DOCUMENT"]);

export const mediaUsageType = pgEnum("media_usage_type", [
  "PORTFOLIO_COVER",
  "PORTFOLIO_SECTION",
  "PORTFOLIO_ASSET",
  "GENERIC",
]);

// --- Tables -----------------------------------------------------------------

export const appConfig = pgTable("app_config", {
  id: id(),
  key: text("key").notNull().unique(),
  value: text("value").notNull(),
  createdAt,
  updatedAt,
});

export const category = pgTable("category", {
  id: id(),
  slug: text("slug").notNull().unique(),
  nameAr: text("name_ar").notNull(),
  nameEn: text("name_en").notNull(),
  nameDe: text("name_de").notNull(),
  descriptionAr: text("description_ar").notNull(),
  descriptionEn: text("description_en").notNull(),
  descriptionDe: text("description_de").notNull(),
  sortOrder: integer("sort_order").notNull().default(0),
  isActive: boolean("is_active").notNull().default(true),
  createdAt,
  updatedAt,
});

export const portfolioProject = pgTable(
  "portfolio_project",
  {
    id: id(),
    categoryId: text("category_id")
      .notNull()
      .references(() => category.id, { onDelete: "restrict" }),
    slug: text("slug").notNull().unique(),
    viewMode: portfolioProjectViewMode("view_mode").notNull().default("GRID"),
    titleAr: text("title_ar").notNull(),
    titleEn: text("title_en").notNull(),
    titleDe: text("title_de").notNull(),
    summaryAr: text("summary_ar").notNull(),
    summaryEn: text("summary_en").notNull(),
    summaryDe: text("summary_de").notNull(),
    clientName: text("client_name").notNull(),
    projectYear: integer("project_year").notNull(),
    serviceLabelAr: text("service_label_ar").notNull(),
    serviceLabelEn: text("service_label_en").notNull(),
    serviceLabelDe: text("service_label_de").notNull(),
    previewUrl: text("preview_url"),
    coverImagePath: text("cover_image_path"),
    isFeatured: boolean("is_featured").notNull().default(false),
    isPublished: boolean("is_published").notNull().default(false),
    publishedAt: timestamp("published_at", { withTimezone: true }),
    sortOrder: integer("sort_order").notNull().default(0),
    createdAt,
    updatedAt,
  },
  (t) => [
    index("portfolio_project_category_published_sort_idx").on(t.categoryId, t.isPublished, t.sortOrder),
    index("portfolio_project_published_sort_idx").on(t.isPublished, t.sortOrder),
  ],
);

export const portfolioSection = pgTable(
  "portfolio_section",
  {
    id: id(),
    projectId: text("project_id")
      .notNull()
      .references(() => portfolioProject.id, { onDelete: "cascade" }),
    type: portfolioSectionType("type").notNull(),
    titleAr: text("title_ar").notNull(),
    titleEn: text("title_en").notNull(),
    titleDe: text("title_de").notNull(),
    bodyAr: text("body_ar").notNull(),
    bodyEn: text("body_en").notNull(),
    bodyDe: text("body_de").notNull(),
    imagePath: text("image_path"),
    linkUrl: text("link_url"),
    sortOrder: integer("sort_order").notNull().default(0),
    createdAt,
    updatedAt,
  },
  (t) => [index("portfolio_section_project_sort_idx").on(t.projectId, t.sortOrder)],
);

export const portfolioAsset = pgTable(
  "portfolio_asset",
  {
    id: id(),
    projectId: text("project_id")
      .notNull()
      .references(() => portfolioProject.id, { onDelete: "cascade" }),
    kind: portfolioAssetKind("kind").notNull(),
    filePath: text("file_path").notNull(),
    altAr: text("alt_ar").notNull(),
    altEn: text("alt_en").notNull(),
    altDe: text("alt_de").notNull(),
    sortOrder: integer("sort_order").notNull().default(0),
    createdAt,
    updatedAt,
  },
  (t) => [index("portfolio_asset_project_sort_idx").on(t.projectId, t.sortOrder)],
);

export const mediaAsset = pgTable(
  "media_asset",
  {
    id: id(),
    source: mediaSource("source").notNull(),
    kind: mediaKind("kind").notNull(),
    url: text("url").notNull(),
    fileName: text("file_name").notNull(),
    label: text("label").notNull(),
    altText: text("alt_text"),
    mimeType: text("mime_type"),
    size: integer("size"),
    createdAt,
    updatedAt,
  },
  (t) => [index("media_asset_kind_created_idx").on(t.kind, t.createdAt)],
);

export const mediaUsage = pgTable(
  "media_usage",
  {
    id: id(),
    assetId: text("asset_id")
      .notNull()
      .references(() => mediaAsset.id, { onDelete: "cascade" }),
    usageType: mediaUsageType("usage_type").notNull(),
    entityType: text("entity_type").notNull(),
    entityId: text("entity_id").notNull(),
    fieldKey: text("field_key").notNull(),
    createdAt,
    updatedAt,
  },
  (t) => [
    uniqueIndex("media_usage_unique_slot").on(t.usageType, t.entityType, t.entityId, t.fieldKey),
    index("media_usage_asset_idx").on(t.assetId),
    index("media_usage_entity_idx").on(t.entityType, t.entityId),
  ],
);

// --- Relations (for the relational query API: db.query.*.findMany({ with })) --

export const categoryRelations = relations(category, ({ many }) => ({
  projects: many(portfolioProject),
}));

export const portfolioProjectRelations = relations(portfolioProject, ({ one, many }) => ({
  category: one(category, {
    fields: [portfolioProject.categoryId],
    references: [category.id],
  }),
  sections: many(portfolioSection),
  assets: many(portfolioAsset),
}));

export const portfolioSectionRelations = relations(portfolioSection, ({ one }) => ({
  project: one(portfolioProject, {
    fields: [portfolioSection.projectId],
    references: [portfolioProject.id],
  }),
}));

export const portfolioAssetRelations = relations(portfolioAsset, ({ one }) => ({
  project: one(portfolioProject, {
    fields: [portfolioAsset.projectId],
    references: [portfolioProject.id],
  }),
}));

export const mediaAssetRelations = relations(mediaAsset, ({ many }) => ({
  usages: many(mediaUsage),
}));

export const mediaUsageRelations = relations(mediaUsage, ({ one }) => ({
  asset: one(mediaAsset, {
    fields: [mediaUsage.assetId],
    references: [mediaAsset.id],
  }),
}));
