// src/models/ai-provider.ts
// Copyright (C) 2025 DTP Technologies, LLC
// All Rights Reserved

import { Schema, Document, model } from "mongoose";

export type ApiType = "ollama" | "openai";

/**
 * Normalised capability flags stored with each model record.  These are
 * populated during model refresh from provider-specific metadata and drive
 * slot-based filtering in the UI (e.g. only canCallTools models for Agent).
 */
export interface IAiModelSettings {
  temperature?: number;
  topP?: number;
  topK?: number;
  numCtx?: number;
}

export interface IAiModelCapabilities {
  /** Model supports structured function / tool calling via the API. */
  canCallTools: boolean;
  /** Model accepts image inputs (multimodal / vision). */
  hasVision: boolean;
  /** Model can produce vector embeddings (required for the Vector slot). */
  hasEmbedding: boolean;
  /** Model has an explicit reasoning / thinking phase (e.g. o1, QwQ). */
  hasThinking: boolean;
  /** Model is instruction-tuned / chat-tuned (as opposed to a base model). */
  isInstructTuned: boolean;
}

export const AiModelCapabilitiesSchema = new Schema<IAiModelCapabilities>(
  {
    canCallTools: { type: Boolean, default: false },
    hasVision: { type: Boolean, default: false },
    hasEmbedding: { type: Boolean, default: false },
    hasThinking: { type: Boolean, default: false },
    isInstructTuned: { type: Boolean, default: false },
  },
  { _id: false },
);

export interface IAiModel {
  id: string;
  name: string;
  /**
   * Raw parameter count in billions (float).  Use parameterLabel for display.
   */
  parameterCount?: number;
  /**
   * Human-readable parameter size label sourced directly from the provider,
   * e.g. "7b", "70b", "3.8b".
   */
  parameterLabel?: string;
  contextWindow?: number;
  capabilities: IAiModelCapabilities;
  settings?: IAiModelSettings;
}

export const AiModelSettingsSchema = new Schema<IAiModelSettings>(
  {
    temperature: { type: Number },
    topP: { type: Number },
    topK: { type: Number },
    numCtx: { type: Number },
  },
  { _id: false },
);

export const AiModelSchema = new Schema<IAiModel>(
  {
    id: { type: String, required: true },
    name: { type: String, required: true },
    parameterCount: { type: Number },
    parameterLabel: { type: String },
    contextWindow: { type: Number },
    capabilities: {
      type: AiModelCapabilitiesSchema,
      default: () => ({
        canCallTools: false,
        hasVision: false,
        hasEmbedding: false,
        hasThinking: false,
        isInstructTuned: false,
      }),
    },
    settings: {
      type: AiModelSettingsSchema,
      default: undefined,
    },
  },
  { _id: false },
);

export interface IAiProvider extends Document {
  name: string;
  apiType: ApiType;
  baseUrl: string;
  apiKey: string;
  enabled: boolean;
  models: IAiModel[];
  lastModelRefresh: Date;
}

export const AiProviderSchema = new Schema<IAiProvider>({
  name: { type: String, required: true },
  apiType: { type: String, enum: ["ollama", "openai"], required: true },
  baseUrl: { type: String, required: true },
  apiKey: { type: String, required: true, select: false },
  enabled: { type: Boolean, default: true, required: true },
  models: { type: [AiModelSchema], default: [], required: true },
  lastModelRefresh: { type: Date, default: Date.now },
});

AiProviderSchema.index({ name: 1 }, { unique: true });

export const AiProvider = model<IAiProvider>("AiProvider", AiProviderSchema);
export default AiProvider;

// Note: Index synchronization is now handled during application startup
// to ensure the database connection is established first.
// See src/lib/db.ts for the syncDatabaseIndexes function.
