"use server";

import { prisma } from "@dpf/db";
import { getBuiltInToolsOverview } from "@/lib/actions/built-in-tools";
import { queryMcpIntegrations } from "@/lib/actions/mcp-catalog";
import {
  NATIVE_INTEGRATIONS,
  getNativeIntegrationCredentialIds,
  type NativeIntegrationId,
} from "@/lib/tools/native-integration-catalog";

type CatalogSearchParams = {
  query: string;
  category?: string;
  archetypeId?: string;
  pricingModel?: string;
  limit?: number;
};

type ConnectionCatalogBase = {
  id: string;
  kind: "mcp" | "native" | "built_in";
  name: string;
  description: string | null;
  category: string;
  pricingModel: string | null;
};

export type McpConnectionCatalogEntry = ConnectionCatalogBase & {
  kind: "mcp";
  vendor: string | null;
  documentationUrl: string | null;
  logoUrl: string | null;
  rating: { toNumber(): number } | number | null;
  ratingCount: number | null;
  isVerified: boolean;
  activeServerId: string | null;
};

export type NativeConnectionCatalogEntry = ConnectionCatalogBase & {
  kind: "native";
  href: string;
  configured: boolean;
  statusLabel: "Configured" | "Needs attention" | "Available";
  provider: string;
  model: "native";
};

export type BuiltInConnectionCatalogEntry = ConnectionCatalogBase & {
  kind: "built_in";
  href: string;
  configured: boolean;
  statusLabel: "Configured" | "Needs setup" | "Available";
  configKey: string | null;
  capability: string;
  model: "built-in";
};

export type ConnectionCatalogEntry =
  | McpConnectionCatalogEntry
  | NativeConnectionCatalogEntry
  | BuiltInConnectionCatalogEntry;

export type ConnectionCatalogSection = {
  kind: ConnectionCatalogEntry["kind"];
  title: string;
  description: string;
  entries: ConnectionCatalogEntry[];
};

function matchesQuery(entry: { name: string; description: string | null; category: string }, query: string) {
  const normalized = query.trim().toLowerCase();
  if (!normalized) return true;
  return [entry.name, entry.description ?? "", entry.category]
    .join(" ")
    .toLowerCase()
    .includes(normalized);
}

export async function getConnectionCatalog(params: CatalogSearchParams): Promise<{
  totalCount: number;
  counts: { mcp: number; native: number; builtIn: number };
  sections: ConnectionCatalogSection[];
}> {
  const { query, category, pricingModel, archetypeId, limit = 60 } = params;

  const [integrations, activeLinks, builtInsOverview, nativeCredentials] = await Promise.all([
    queryMcpIntegrations({
      query,
      ...(category ? { category } : {}),
      ...(pricingModel ? { pricingModel } : {}),
      ...(archetypeId ? { archetypeId } : {}),
      limit,
    }),
    prisma.mcpServer.findMany({
      where: { integrationId: { not: null }, status: "active" },
      select: { integrationId: true, id: true },
    }),
    getBuiltInToolsOverview(),
    prisma.integrationCredential.findMany({
      where: { integrationId: { in: getNativeIntegrationCredentialIds() } },
      select: { integrationId: true, status: true },
    }),
  ]);

  const activeMap = new Map(activeLinks.map((server) => [server.integrationId, server.id]));
  const nativeStatusMap = new Map<NativeIntegrationId, { configured: boolean; hasError: boolean }>();

  for (const descriptor of NATIVE_INTEGRATIONS) {
    nativeStatusMap.set(descriptor.id, { configured: false, hasError: false });
  }

  const idByCredentialId = new Map(
    NATIVE_INTEGRATIONS.map((integration) => [integration.integrationId, integration.id]),
  );

  for (const credential of nativeCredentials) {
    const descriptorId = idByCredentialId.get(credential.integrationId);
    if (!descriptorId) continue;
    const current = nativeStatusMap.get(descriptorId);
    if (!current) continue;

    current.configured ||= credential.status === "connected";
    current.hasError ||= credential.status === "error";
  }

  const mcpEntries: McpConnectionCatalogEntry[] = integrations.map((integration) => ({
    id: integration.id,
    kind: "mcp",
    name: integration.name,
    description: integration.shortDescription,
    category: integration.category,
    pricingModel: integration.pricingModel,
    vendor: integration.vendor,
    documentationUrl: integration.documentationUrl,
    logoUrl: integration.logoUrl,
    rating: integration.rating,
    ratingCount: integration.ratingCount,
    isVerified: integration.isVerified,
    activeServerId: activeMap.get(integration.id) ?? null,
  }));

  const nativeEntries: NativeConnectionCatalogEntry[] = NATIVE_INTEGRATIONS
    .map((integration) => {
      const status = nativeStatusMap.get(integration.id) ?? { configured: false, hasError: false };
      const statusLabel: NativeConnectionCatalogEntry["statusLabel"] = status.configured
        ? "Configured"
        : status.hasError
          ? "Needs attention"
          : "Available";
      return {
        id: integration.id,
        kind: "native" as const,
        name: integration.name,
        description: integration.description,
        category: integration.category,
        pricingModel: integration.pricingModel,
        href: integration.href,
        configured: status.configured,
        statusLabel,
        provider: integration.provider,
        model: integration.model,
      };
    })
    .filter((entry) => matchesQuery(entry, query));

  const builtInEntries: BuiltInConnectionCatalogEntry[] = builtInsOverview.tools
    .map((tool) => {
      const statusLabel: BuiltInConnectionCatalogEntry["statusLabel"] = tool.configKey
        ? (tool.configured ? "Configured" : "Needs setup")
        : "Available";

      return {
        id: tool.id,
        kind: "built_in" as const,
        name: tool.name,
        description: tool.description,
        category: "built-in",
        pricingModel: "free",
        href: "/platform/tools/built-ins",
        configured: tool.configured,
        statusLabel,
        configKey: tool.configKey,
        capability: tool.capability,
        model: tool.model,
      };
    })
    .filter((entry) => matchesQuery(entry, query));

  const sections: ConnectionCatalogSection[] = [
    {
      kind: "mcp",
      title: "MCP Catalog",
      description: "Registry-backed MCP integrations you can evaluate before activating as MCP Services.",
      entries: mcpEntries,
    },
    {
      kind: "native",
      title: "Native Integrations",
      description: "First-class DPF-owned enterprise anchors with dedicated auth, approval, and governance flows.",
      entries: nativeEntries,
    },
    {
      kind: "built_in",
      title: "Built-in Tools",
      description: "Platform-native tools that ship with DPF and may require local operator configuration.",
      entries: builtInEntries,
    },
  ];

  return {
    totalCount: mcpEntries.length + nativeEntries.length + builtInEntries.length,
    counts: {
      mcp: mcpEntries.length,
      native: nativeEntries.length,
      builtIn: builtInEntries.length,
    },
    sections,
  };
}
