import { AIProvider, SupportedAIProvider } from "./types";
import { OpenAIProvider } from "./openai-provider";
import { GeminiProvider } from "./gemini-provider";
import { LocalFallbackProvider } from "./local-provider";
import { getTenantByDomain } from "../security/tenant-context";
import prisma from "../../db.server";

export interface ResolvedStoreAIConfig {
  provider: AIProvider;
  model: string;
  systemPrompt?: string;
  aiProviderName: SupportedAIProvider;
}

/**
 * Returns the appropriate AIProvider instance based on merchant store settings.
 * Hides provider decision details so agent loops do not care whether OpenAI or Gemini is used.
 */
export function getAIProvider(
  settings?: {
    aiProvider?: string;
    model?: string;
    openaiModel?: string;
    geminiModel?: string;
    systemPrompt?: string | null;
  } | null,
  overrideProviderName?: string
): ResolvedStoreAIConfig {
  let providerName: SupportedAIProvider = "openai";
  let modelName = "gpt-4o-mini";
  let systemPrompt = settings?.systemPrompt || undefined;

  if (settings?.aiProvider) {
    providerName = settings.aiProvider.toLowerCase() as SupportedAIProvider;
  }

  if (overrideProviderName) {
    providerName = overrideProviderName.toLowerCase() as SupportedAIProvider;
  }

  let providerInstance: AIProvider;

  if (providerName === "gemini") {
    let candidate = settings?.model && settings.model.startsWith("gemini-") ? settings.model : (settings?.geminiModel || settings?.model || "gemini-1.5-flash");
    if (candidate.startsWith("gpt-") || candidate === "gemini-3.6-flash") {
      candidate = "gemini-1.5-flash";
    }
    modelName = candidate;
    providerInstance = new GeminiProvider();
  } else if (providerName === "openai") {
    let candidate = settings?.model && settings.model.startsWith("gpt-") ? settings.model : (settings?.openaiModel || settings?.model || "gpt-4o-mini");
    if (candidate.startsWith("gemini-")) {
      candidate = "gpt-4o-mini";
    }
    modelName = candidate;
    providerInstance = new OpenAIProvider();
  } else {
    providerInstance = new LocalFallbackProvider();
    modelName = "local-engine";
  }

  return {
    provider: providerInstance,
    model: modelName,
    systemPrompt,
    aiProviderName: providerName,
  };
}

/**
 * Convenience method to resolve AI provider for a shop domain directly from DB tenant settings.
 */
export async function getAIProviderForShop(
  shopDomain: string,
  overrideProviderName?: string
): Promise<ResolvedStoreAIConfig> {
  try {
    const tenant = await getTenantByDomain(shopDomain);
    const settings = await prisma.chatbotSettings.findUnique({
      where: { shopId: tenant.shopId },
    });
    return getAIProvider(settings, overrideProviderName);
  } catch (e) {
    return getAIProvider(null, overrideProviderName);
  }
}
