'use node';

import { getAuthUserId } from '@convex-dev/auth/server';
import { ConvexError, v } from 'convex/values';

import type { Id } from './_generated/dataModel';
import type { ActionCtx } from './_generated/server';
import { internal } from './_generated/api';
import { action } from './_generated/server';
import { encryptSecret } from './secretCrypto';

const provider = v.union(
  v.literal('openai'),
  v.literal('anthropic'),
  v.literal('google'),
  v.literal('openrouter'),
  v.literal('requesty'),
  v.literal('litellm'),
  v.literal('cloudflare_ai_gateway'),
  v.literal('custom_openai_compatible'),
  v.literal('opencode_openai_login'),
);

const authType = v.union(
  v.literal('api_key'),
  v.literal('opencode_auth_json'),
  v.literal('none'),
);

const reasoningEffort = v.union(
  v.literal('none'),
  v.literal('minimal'),
  v.literal('low'),
  v.literal('medium'),
  v.literal('high'),
  v.literal('xhigh'),
);

const getRequiredUserId = async (ctx: ActionCtx): Promise<Id<'users'>> => {
  const userId = await getAuthUserId(ctx);
  if (!userId) throw new ConvexError('Not authenticated.');
  return userId;
};

const previewSecret = (secret: string) => {
  const trimmed = secret.trim();
  if (!trimmed) return undefined;
  if (trimmed.startsWith('{')) return 'auth json configured';
  if (trimmed.length <= 10) return 'configured';
  return `${trimmed.slice(0, 7)}...${trimmed.slice(-4)}`;
};

export const save = action({
  args: {
    profileId: v.optional(v.id('aiProviderProfiles')),
    name: v.string(),
    provider,
    authType,
    secret: v.optional(v.string()),
    baseUrl: v.optional(v.string()),
    defaultModel: v.string(),
    modelOptions: v.optional(v.array(v.string())),
    reasoningEffort,
    enabled: v.boolean(),
  },
  handler: async (ctx, args): Promise<Id<'aiProviderProfiles'>> => {
    const ownerId = await getRequiredUserId(ctx);
    const secret = args.secret?.trim();
    if (!args.profileId && args.authType !== 'none' && !secret) {
      throw new ConvexError('A credential is required for this provider.');
    }
    return await ctx.runMutation(
      internal.aiProviderProfiles.upsertEncryptedInternal,
      {
        ownerId,
        profileId: args.profileId,
        name: args.name,
        provider: args.provider,
        authType: args.authType,
        encryptedSecret: secret ? encryptSecret(secret) : undefined,
        secretPreview: secret ? previewSecret(secret) : undefined,
        baseUrl: args.baseUrl,
        defaultModel: args.defaultModel,
        modelOptions: args.modelOptions,
        reasoningEffort: args.reasoningEffort,
        enabled: args.enabled,
      },
    );
  },
});
