import { createOpenRouter } from "@openrouter/ai-sdk-provider";
import type { ModelCapability } from "@decocms/shared/sdk";
import type {
  StudioProvider,
  ModelInfo,
  OAuthPkceResult,
  OpenRouterAPIModel,
  ProviderAdapter,
} from "../types";
const OPENROUTER_ICON_URL =
  "https://assets.decocache.com/decocms/284f1ad9-3fd8-494c-be88-16671069f3b9/openrouter.svg";

export const openrouterAdapter: ProviderAdapter = {
  info: {
    id: "openrouter",
    name: "OpenRouter",
    description: "One account, hundreds of AI models",
    logo: OPENROUTER_ICON_URL,
  },

  supportedMethods: ["oauth-pkce", "api-key"],

  getOAuthUrl({ callbackUrl, codeChallenge, codeChallengeMethod }) {
    const params = new URLSearchParams({
      callback_url: callbackUrl,
      code_challenge: codeChallenge,
      code_challenge_method: codeChallengeMethod,
    });
    return `https://openrouter.ai/auth?${params}`;
  },

  async exchangeOAuthCode({
    code,
    codeVerifier,
    codeChallengeMethod,
  }): Promise<OAuthPkceResult> {
    const res = await fetch("https://openrouter.ai/api/v1/auth/keys", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        code,
        code_verifier: codeVerifier,
        code_challenge_method: codeChallengeMethod,
      }),
      signal: AbortSignal.timeout(30_000),
    });
    if (!res.ok) {
      throw new Error(`OpenRouter OAuth exchange failed: ${res.status}`);
    }
    const data = await res.json();
    return { apiKey: data.key, userId: data.user_id };
  },

  create(apiKey): StudioProvider {
    const aiSdk = createOpenRouter({
      apiKey,
    });

    const headers = { Authorization: `Bearer ${apiKey}` };

    return {
      info: this.info,
      aiSdk,

      async listModels(): Promise<ModelInfo[]> {
        const mapV1Model = (m: OpenRouterAPIModel): ModelInfo => {
          const contextWindow = m.context_length ?? 0;
          const reportedMaxOut = m.top_provider.max_completion_tokens || null;
          const maxOutputTokens =
            reportedMaxOut &&
            (contextWindow === 0 || reportedMaxOut < contextWindow)
              ? reportedMaxOut
              : null;
          return {
            providerId: "openrouter",
            modelId: m.id,
            title: m.name,
            description: m.description ?? null,
            logo: null,
            capabilities: [
              ...new Set([
                // OpenRouter uses "image" in input_modalities to mean vision (can see images).
                // Map it to "vision" so we distinguish from "image" (image generation output).
                ...m.architecture.input_modalities.map((mod) =>
                  mod === "image" ? "vision" : mod,
                ),
                ...m.architecture.output_modalities,
                ...(m.supported_parameters?.includes("tools")
                  ? (["tools"] as const)
                  : []),
                ...(m.supported_parameters?.includes("reasoning")
                  ? (["reasoning"] as const)
                  : []),
              ]),
            ] as ModelCapability[],
            limits: {
              contextWindow,
              maxOutputTokens,
            },
            costs: {
              input: m.pricing.prompt ?? 0,
              output: m.pricing.completion ?? 0,
            },
          };
        };

        // v1 is the authoritative source — has supported_parameters, canonical slugs, etc.
        const res = await fetch("https://openrouter.ai/api/v1/models", {
          headers,
          signal: AbortSignal.timeout(30_000),
        });
        if (!res.ok)
          throw new Error(`OpenRouter listModels failed: ${res.status}`);
        const { data }: { data: OpenRouterAPIModel[] } = await res.json();
        const models = data.map(mapV1Model);

        return models;
      },
    };
  },
};
