import type { SupportedEmbeddingDimension, SupportedProvider } from "@shared";
import {
  boolean,
  index,
  integer,
  jsonb,
  numeric,
  pgTable,
  text,
  timestamp,
  unique,
  uuid,
} from "drizzle-orm/pg-core";

import type { ModelInputModality, ModelOutputModality } from "@/types";

/**
 * Models table - stores capability and pricing metadata fetched from models.dev API.
 *
 * This table caches model information like input/output modalities, tool calling support,
 * context window size, and pricing. Data is synced periodically from models.dev.
 */
const modelsTable = pgTable(
  "models",
  {
    id: uuid("id").primaryKey().defaultRandom(),

    /** External source model ID format, e.g., "anthropic/claude-3-opus" */
    externalId: text("external_id").notNull(),

    /** Archestra provider name (mapped from external source) */
    provider: text("provider").$type<SupportedProvider>().notNull(),

    /** Model ID in Archestra format (without provider prefix) */
    modelId: text("model_id").notNull(),

    /** Human-readable model description */
    description: text("description"),

    /** Maximum context window size in tokens */
    contextLength: integer("context_length"),

    /** Supported input modalities */
    inputModalities: jsonb("input_modalities").$type<ModelInputModality[]>(),

    /** Supported output modalities */
    outputModalities: jsonb("output_modalities").$type<ModelOutputModality[]>(),

    /** Whether the model supports function/tool calling */
    supportsToolCalling: boolean("supports_tool_calling"),

    /** Price per token for prompt/input (in dollars) */
    promptPricePerToken: numeric("prompt_price_per_token", {
      precision: 20,
      scale: 12,
    }),

    /** Price per token for completion/output (in dollars) */
    completionPricePerToken: numeric("completion_price_per_token", {
      precision: 20,
      scale: 12,
    }),

    /** Custom admin-set price per million tokens for input (nullable, overrides models.dev price) */
    customPricePerMillionInput: numeric("custom_price_per_million_input", {
      precision: 10,
      scale: 2,
    }),

    /** Custom admin-set price per million tokens for output (nullable, overrides models.dev price) */
    customPricePerMillionOutput: numeric("custom_price_per_million_output", {
      precision: 10,
      scale: 2,
    }),

    /** Whether this model should be excluded from chat model selection. */
    ignored: boolean("ignored").notNull().default(false),

    /**
     * Embedding dimension metadata. When non-null, the model is treated as an
     * embedding model and can be selected for knowledge base embeddings.
     */
    embeddingDimensions: integer(
      "embedding_dimensions",
    ).$type<SupportedEmbeddingDimension>(),

    /** Whether this model was discovered via an LLM Proxy request (ensureModelExists).
     * Models with this flag are preserved even without API key links,
     * so users can define custom token pricing for metrics. */
    discoveredViaLlmProxy: boolean("discovered_via_llm_proxy")
      .notNull()
      .default(false),

    /** When this metadata was last synced from external source */
    lastSyncedAt: timestamp("last_synced_at", { mode: "date" })
      .notNull()
      .defaultNow(),

    createdAt: timestamp("created_at", { mode: "date" }).notNull().defaultNow(),
    updatedAt: timestamp("updated_at", { mode: "date" })
      .notNull()
      .defaultNow()
      .$onUpdate(() => new Date()),
  },
  (table) => ({
    /** Unique constraint on provider + model_id to prevent duplicates */
    providerModelUnique: unique("models_provider_model_unique").on(
      table.provider,
      table.modelId,
    ),
    /** Index for fast lookups by provider + model_id */
    providerModelIdx: index("models_provider_model_idx").on(
      table.provider,
      table.modelId,
    ),
    /** Index for lookups by external_id */
    externalIdIdx: index("models_external_id_idx").on(table.externalId),
  }),
);

export default modelsTable;
