export interface AIModelDefinition {
  label: string;
  value: string;
  providerId: string;
  recommended?: boolean;
  badge?: string;
  description?: string;
  speedRating?: string;
}

export interface AIProviderDefinition {
  id: string;
  name: string;
  description: string;
  badge: string;
  iconName: string;
  models: AIModelDefinition[];
}

/**
 * Central Provider & Model Validation Helper
 */
export function validateAndSanitizeAIModel(provider: string, model: string): { valid: boolean; model: string } {
  const normProvider = (provider || "openai").toLowerCase().trim();
  const providers = getDynamicAIProviders();
  const providerDef = providers.find((p) => p.id === normProvider);

  if (!providerDef) {
    return { valid: false, model: "gpt-4o-mini" };
  }

  const validModel = providerDef.models.find((m) => m.value === model);
  if (validModel) {
    return { valid: true, model };
  }

  // Fallback to recommended model for provider
  const recModel = providerDef.models.find((m) => m.recommended) || providerDef.models[0];
  return { valid: false, model: recModel ? recModel.value : (normProvider === "gemini" ? "gemini-1.5-flash" : "gpt-4o-mini") };
}

export function getDynamicAIProviders(): AIProviderDefinition[] {
  return [
    {
      id: "openai",
      name: "OpenAI API (GPT Engines)",
      description: "Industry-standard LLMs with advanced tool calling and product reasoning.",
      badge: "OpenAI Official",
      iconName: "robot",
      models: [
        {
          label: "OpenAI: gpt-4o-mini (Ultra Fast & Recommended)",
          value: "gpt-4o-mini",
          providerId: "openai",
          recommended: true,
          badge: "Recommended",
          description: "Fastest response times, low latency, and efficient token usage.",
          speedRating: "Ultra Fast",
        },
        {
          label: "OpenAI: gpt-4o (High Performance AI)",
          value: "gpt-4o",
          providerId: "openai",
          badge: "Pro Level",
          description: "High capability model for complex multi-product queries and custom store logic.",
          speedRating: "High Speed",
        },
        {
          label: "OpenAI: gpt-4-turbo (Advanced Function Calling)",
          value: "gpt-4-turbo",
          providerId: "openai",
          badge: "Turbo",
          description: "High precision tool execution for Shopify cart, discounts, and checkout.",
          speedRating: "Standard",
        },
        {
          label: "OpenAI: gpt-3.5-turbo (Legacy Standard)",
          value: "gpt-3.5-turbo",
          providerId: "openai",
          badge: "Legacy",
          description: "Standard conversational engine.",
          speedRating: "Standard",
        },
      ],
    },
    {
      id: "gemini",
      name: "Google Gemini API (Gemini Engines)",
      description: "Google DeepMind high-speed multimodal models with fast inference.",
      badge: "Google DeepMind",
      iconName: "brain",
      models: [
        {
          label: "Google Gemini: gemini-1.5-flash (Next-Gen Fast & Recommended)",
          value: "gemini-1.5-flash",
          providerId: "gemini",
          recommended: true,
          badge: "Recommended",
          description: "Next-gen ultra fast DeepMind engine tuned for conversational ecommerce.",
          speedRating: "Ultra Fast",
        },
        {
          label: "Google Gemini: gemini-1.5-pro (Advanced Reasoning & 1M Context)",
          value: "gemini-1.5-pro",
          providerId: "gemini",
          badge: "1M Context",
          description: "Handles massive product catalogs & complex store policies.",
          speedRating: "Standard",
        },
        {
          label: "Google Gemini: gemini-2.0-flash (Experimental High Speed)",
          value: "gemini-2.0-flash",
          providerId: "gemini",
          badge: "Experimental",
          description: "Next-generation experimental flash model.",
          speedRating: "High Speed",
        },
      ],
    },
  ];
}

import prisma from "../db.server";
import { encryptToken, decryptToken } from "../lib/security/encryption";
import { logger } from "../lib/security/logger";
import { registerShop } from "./shop.server";
import { getDefaultStoreDomainSync } from "./platform-settings.server";

export interface SystemIntegrationsData {
  aiProvider: string;
  openaiApiKeyMasked: string;
  openaiModel: string;
  openaiTemperature: number;
  openaiMaxTokens: number;
  openaiEnabled: boolean;
  openaiHasKey: boolean;
  geminiApiKeyMasked: string;
  geminiModel: string;
  geminiTemperature: number;
  geminiMaxTokens: number;
  geminiEnabled: boolean;
  geminiHasKey: boolean;
}

async function resolveValidShopId(shopId: string): Promise<string> {
  if (shopId && shopId !== "s1") {
    const existing = await prisma.shop.findUnique({ where: { id: shopId } });
    if (existing) return existing.id;
  }
  const firstShop = await prisma.shop.findFirst();
  if (firstShop) return firstShop.id;

  const created = await registerShop({
    shopifyDomain: getDefaultStoreDomainSync(),
    accessToken: "shpss_sample_token",
    scopes: "read_products,read_content",
  });
  return created.id;
}

export function maskApiKey(apiKey?: string | null): string {
  if (!apiKey) return "";
  let raw = apiKey;
  if (apiKey.includes(":")) {
    try {
      raw = decryptToken(apiKey);
    } catch {
      raw = apiKey;
    }
  }
  if (!raw) return "";
  if (raw.length <= 4) return "••••••••";
  const lastFour = raw.slice(-4);
  return `••••••••••••${lastFour}`;
}

export async function getAIIntegrationSettings(shopId?: string): Promise<SystemIntegrationsData> {
  const settings = await prisma.systemIntegration.findFirst({
    orderBy: { createdAt: "asc" },
  });

  const openaiRawKey = settings?.openaiApiKey ? decryptToken(settings.openaiApiKey) : process.env.OPENAI_API_KEY;
  const geminiRawKey = settings?.geminiApiKey ? decryptToken(settings.geminiApiKey) : process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY;

  return {
    aiProvider: settings?.aiProvider || "openai",
    openaiApiKeyMasked: maskApiKey(settings?.openaiApiKey),
    openaiModel: settings?.openaiModel || "gpt-4o-mini",
    openaiTemperature: settings?.openaiTemperature ?? 0.7,
    openaiMaxTokens: settings?.openaiMaxTokens ?? 1000,
    openaiEnabled: settings?.openaiEnabled ?? true,
    openaiHasKey: Boolean(openaiRawKey && openaiRawKey.trim().length > 0),
    geminiApiKeyMasked: maskApiKey(settings?.geminiApiKey),
    geminiModel: settings?.geminiModel || "gemini-1.5-flash",
    geminiTemperature: settings?.geminiTemperature ?? 0.7,
    geminiMaxTokens: settings?.geminiMaxTokens ?? 1000,
    geminiEnabled: settings?.geminiEnabled ?? true,
    geminiHasKey: Boolean(geminiRawKey && geminiRawKey.trim().length > 0),
  };
}

export async function saveAIIntegrationSettings(
  shopId: string | undefined,
  payload: {
    aiProvider?: string;
    openaiApiKey?: string;
    openaiModel?: string;
    openaiTemperature?: number;
    openaiMaxTokens?: number;
    openaiEnabled?: boolean;
    geminiApiKey?: string;
    geminiModel?: string;
    geminiTemperature?: number;
    geminiMaxTokens?: number;
    geminiEnabled?: boolean;
  }
) {
  const existing = await prisma.systemIntegration.findFirst({
    orderBy: { createdAt: "asc" },
  });
  const targetId = existing ? existing.id : "global";

  const updateData: any = {};

  if (payload.aiProvider !== undefined) {
    updateData.aiProvider = payload.aiProvider;
  }

  // OpenAI Key handling - encrypt if valid unmasked key, preserve if masked, nullify if explicitly empty
  if (payload.openaiApiKey !== undefined) {
    const keyVal = payload.openaiApiKey.trim();
    if (keyVal.length > 0 && !keyVal.startsWith("••••")) {
      updateData.openaiApiKey = encryptToken(keyVal);
    }
  }

  if (payload.openaiModel !== undefined) updateData.openaiModel = payload.openaiModel;
  if (payload.openaiTemperature !== undefined) updateData.openaiTemperature = payload.openaiTemperature;
  if (payload.openaiMaxTokens !== undefined) updateData.openaiMaxTokens = payload.openaiMaxTokens;
  if (payload.openaiEnabled !== undefined) updateData.openaiEnabled = payload.openaiEnabled;

  // Gemini Key handling - encrypt if valid unmasked key, preserve if masked, nullify if explicitly empty
  if (payload.geminiApiKey !== undefined) {
    const keyVal = payload.geminiApiKey.trim();
    if (keyVal.length > 0 && !keyVal.startsWith("••••")) {
      updateData.geminiApiKey = encryptToken(keyVal);
    }
  }

  if (payload.geminiModel !== undefined) updateData.geminiModel = payload.geminiModel;
  if (payload.geminiTemperature !== undefined) updateData.geminiTemperature = payload.geminiTemperature;
  if (payload.geminiMaxTokens !== undefined) updateData.geminiMaxTokens = payload.geminiMaxTokens;
  if (payload.geminiEnabled !== undefined) updateData.geminiEnabled = payload.geminiEnabled;

  const createData = {
    id: "global",
    aiProvider: payload.aiProvider || existing?.aiProvider || "openai",
    openaiModel: payload.openaiModel || existing?.openaiModel || "gpt-4o-mini",
    openaiTemperature: payload.openaiTemperature ?? existing?.openaiTemperature ?? 0.7,
    openaiMaxTokens: payload.openaiMaxTokens ?? existing?.openaiMaxTokens ?? 1000,
    openaiEnabled: payload.openaiEnabled ?? existing?.openaiEnabled ?? true,
    geminiModel: payload.geminiModel || existing?.geminiModel || "gemini-1.5-flash",
    geminiTemperature: payload.geminiTemperature ?? existing?.geminiTemperature ?? 0.7,
    geminiMaxTokens: payload.geminiMaxTokens ?? existing?.geminiMaxTokens ?? 1000,
    geminiEnabled: payload.geminiEnabled ?? existing?.geminiEnabled ?? true,
    ...updateData,
  };

  const result = await prisma.systemIntegration.upsert({
    where: { id: targetId },
    update: updateData,
    create: createData,
  });

  // Synchronize store-specific ChatbotSettings
  try {
    const activeProvider = payload.aiProvider || result.aiProvider || "openai";
    
    // Determine target shops to update
    let targetShops: string[] = [];
    if (shopId && shopId !== "global" && shopId !== "s1") {
      const targetShop = await prisma.shop.findUnique({ where: { id: shopId } });
      if (targetShop) targetShops = [targetShop.id];
    }

    if (targetShops.length === 0) {
      const allShops = await prisma.shop.findMany({ select: { id: true } });
      targetShops = allShops.map((s) => s.id);
    }

    for (const sId of targetShops) {
      const existingSettings = await prisma.chatbotSettings.findUnique({ where: { shopId: sId } });
      const currentModel = activeProvider === "gemini" 
        ? (payload.geminiModel || existingSettings?.geminiModel || existingSettings?.model || "gemini-1.5-flash")
        : (payload.openaiModel || existingSettings?.openaiModel || existingSettings?.model || "gpt-4o-mini");

      const validated = validateAndSanitizeAIModel(activeProvider, currentModel);

      await prisma.chatbotSettings.upsert({
        where: { shopId: sId },
        update: {
          aiProvider: activeProvider,
          model: validated.model,
          ...(activeProvider === "openai" ? { openaiModel: validated.model } : {}),
          ...(activeProvider === "gemini" ? { geminiModel: validated.model } : {}),
        },
        create: {
          shopId: sId,
          aiProvider: activeProvider,
          model: validated.model,
          openaiModel: activeProvider === "openai" ? validated.model : "gpt-4o-mini",
          geminiModel: activeProvider === "gemini" ? validated.model : "gemini-1.5-flash",
        },
      });
    }
  } catch (err) {
    logger.warn("Warning: Failed to sync store ChatbotSettings during saveAIIntegrationSettings", { error: String(err) });
  }

  const firstShop = await prisma.shop.findFirst();
  if (firstShop) {
    await prisma.auditLog.create({
      data: {
        shopId: firstShop.id,
        action: "AI Configuration Updated",
        resource: payload.aiProvider ? `Provider: ${payload.aiProvider}` : "Provider Settings",
        status: "SUCCESS",
      },
    });
  }

  return result;
}

import { checkRateLimit } from "../lib/security/rate-limit";

export async function testAIProviderConnection(
  shopId: string | undefined,
  provider: "openai" | "gemini",
  customApiKey?: string,
  customModel?: string
): Promise<{ success: boolean; message: string }> {
  try {
    checkRateLimit({ key: `ai_test:${shopId || "global"}`, maxTokens: 10, refillIntervalMs: 60000 });

    const settings = await prisma.systemIntegration.findFirst({
      orderBy: { createdAt: "asc" },
    });
    let apiKey = "";
    let model = "";

    if (provider === "openai") {
      model = customModel || settings?.openaiModel || "gpt-4o-mini";
      if (customApiKey && customApiKey.trim().length > 0 && !customApiKey.startsWith("••••")) {
        apiKey = customApiKey.trim();
      } else {
        apiKey = settings?.openaiApiKey ? decryptToken(settings.openaiApiKey) : process.env.OPENAI_API_KEY || "";
      }

      if (!apiKey) {
        return {
          success: false,
          message: "No OpenAI API key found. Please enter and save a valid API key.",
        };
      }

      const targetUrl = "https://api.openai.com/v1/models";
      const parsedUrl = new URL(targetUrl);
      if (parsedUrl.protocol !== "https:" || parsedUrl.hostname !== "api.openai.com") {
        throw new Error("SSRF Protection: Invalid target endpoint domain.");
      }

      const controller = new AbortController();
      const timeoutId = setTimeout(() => controller.abort(), 10000);

      const res = await fetch(targetUrl, {
        method: "GET",
        headers: {
          Authorization: `Bearer ${apiKey}`,
        },
        signal: controller.signal,
      });
      clearTimeout(timeoutId);

      if (res.ok) {
        return { success: true, message: "Connected to OpenAI successfully!" };
      } else {
        return {
          success: false,
          message: "Unable to connect to OpenAI. Please check your API key and configuration.",
        };
      }
    } else {
      model = customModel || settings?.geminiModel || "gemini-1.5-flash";
      if (customApiKey && customApiKey.trim().length > 0 && !customApiKey.startsWith("••••")) {
        apiKey = customApiKey.trim();
      } else {
        apiKey = settings?.geminiApiKey ? decryptToken(settings.geminiApiKey) : process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY || "";
      }

      if (!apiKey) {
        return {
          success: false,
          message: "No Google Gemini API key found. Please enter and save a valid API key.",
        };
      }

      const targetUrl = `https://generativelanguage.googleapis.com/v1beta/models?key=${apiKey}`;
      const parsedUrl = new URL(targetUrl);
      if (parsedUrl.protocol !== "https:" || parsedUrl.hostname !== "generativelanguage.googleapis.com") {
        throw new Error("SSRF Protection: Invalid target endpoint domain.");
      }

      const controller = new AbortController();
      const timeoutId = setTimeout(() => controller.abort(), 10000);

      const res = await fetch(targetUrl, {
        method: "GET",
        headers: {
          "Content-Type": "application/json",
        },
        signal: controller.signal,
      });
      clearTimeout(timeoutId);

      if (res.ok) {
        return { success: true, message: "Connected to Google Gemini successfully!" };
      } else {
        return {
          success: false,
          message: "Unable to connect to Google Gemini. Please check your API key and configuration.",
        };
      }
    }
  } catch (err: any) {
    logger.error(`Error testing connection for provider ${provider}`, err);
    return {
      success: false,
      message: err.message?.includes("Rate limit")
        ? err.message
        : `Unable to connect to ${provider === "openai" ? "OpenAI" : "Google Gemini"}. Please check your API key and network configuration.`,
    };
  }
}
