import { isAiConfigured } from "../ai-client.js";
import { createAuditEntry } from "../lib/audit.js";
import { testSmtpConnection } from "../lib/email.js";
import {
  getRuntimeSecretStatuses,
  RUNTIME_SECRET_FIELDS,
  resolveSystemSettingsRuntime,
} from "../lib/system-settings-runtime.js";
import type { TRPCContext } from "../trpc.js";
import { DEFAULT_SUMMARY_PROMPT } from "./resource.js";
import {
  buildSettingsUpdatePayload,
  buildSystemSettingsViewModel,
  sanitizeSettingsAuditSnapshot,
  type SettingsUpdateInput,
  testRuntimeAiConnection,
} from "./settings-support.js";

type SettingsProcedureContext = Pick<TRPCContext, "db" | "dbUser">;

function withAuditUser(userId: string | undefined) {
  return userId ? { userId } : {};
}

export async function getSystemSettingsView(
  ctx: SettingsProcedureContext,
) {
  const settings = await ctx.db.systemSettings.findUnique({
    where: { id: "singleton" },
  });
  const runtimeSettings = resolveSystemSettingsRuntime(settings);
  const runtimeSecrets = getRuntimeSecretStatuses(settings);
  return buildSystemSettingsViewModel({
    settings,
    runtimeSettings,
    runtimeSecrets,
    defaultSummaryPrompt: DEFAULT_SUMMARY_PROMPT,
  });
}

export async function updateSystemSettings(
  ctx: SettingsProcedureContext,
  input: SettingsUpdateInput,
) {
  const { data, ignoredSecretFields } = buildSettingsUpdatePayload(input);

  if (Object.keys(data).length === 0) {
    return {
      ok: true,
      ignoredSecretFields,
      secretStorageMode: "environment-only" as const,
    };
  }

  const before = await ctx.db.systemSettings.findUnique({ where: { id: "singleton" } });

  await ctx.db.systemSettings.upsert({
    where: { id: "singleton" },
    create: { id: "singleton", ...data },
    update: data,
  });

  const sanitizedBefore = before
    ? sanitizeSettingsAuditSnapshot(before as unknown as Record<string, unknown>)
    : undefined;
  const sanitizedAfter = sanitizeSettingsAuditSnapshot(data);

  void createAuditEntry({
    db: ctx.db,
    entityType: "SystemSettings",
    entityId: "singleton",
    entityName: "System Settings",
    action: before ? "UPDATE" : "CREATE",
    ...withAuditUser(ctx.dbUser?.id),
    ...(sanitizedBefore !== undefined ? { before: sanitizedBefore } : {}),
    after: sanitizedAfter,
    source: "ui",
  });

  return {
    ok: true,
    ignoredSecretFields,
    secretStorageMode: "environment-only" as const,
  };
}

export async function clearStoredRuntimeSecrets(
  ctx: SettingsProcedureContext,
) {
  const existing = await ctx.db.systemSettings.findUnique({
    where: { id: "singleton" },
    select: Object.fromEntries(
      RUNTIME_SECRET_FIELDS.map((field) => [field, true]),
    ) as Record<(typeof RUNTIME_SECRET_FIELDS)[number], true>,
  });

  const clearedFields = RUNTIME_SECRET_FIELDS.filter((field) => !!existing?.[field]);

  if (clearedFields.length === 0) {
    return { ok: true, clearedFields: [] as string[] };
  }

  await ctx.db.systemSettings.update({
    where: { id: "singleton" },
    data: Object.fromEntries(clearedFields.map((field) => [field, null])),
  });

  void createAuditEntry({
    db: ctx.db,
    entityType: "SystemSettings",
    entityId: "singleton",
    entityName: "Runtime Secrets",
    action: "UPDATE",
    ...withAuditUser(ctx.dbUser?.id),
    after: { clearedFields },
    source: "ui",
    summary: `Cleared ${clearedFields.length} legacy runtime secret field(s) from database storage`,
  });

  return { ok: true, clearedFields };
}

export async function testSettingsAiConnection(
  ctx: SettingsProcedureContext,
) {
  const settings = resolveSystemSettingsRuntime(await ctx.db.systemSettings.findUnique({
    where: { id: "singleton" },
  }));
  return testRuntimeAiConnection(settings);
}

export async function testSettingsSmtpConnection(
  ctx: SettingsProcedureContext,
) {
  const result = await testSmtpConnection();

  void createAuditEntry({
    db: ctx.db,
    entityType: "SystemSettings",
    entityId: "singleton",
    entityName: "SMTP Connection Test",
    action: "UPDATE",
    ...withAuditUser(ctx.dbUser?.id),
    after: { testResult: result.ok ? "success" : "failed" },
    source: "ui",
    summary: result.ok ? "SMTP connection test succeeded" : "SMTP connection test failed",
  });

  return result;
}

export async function testSettingsGeminiConnection(
  ctx: SettingsProcedureContext,
) {
  const settings = resolveSystemSettingsRuntime(await ctx.db.systemSettings.findUnique({
    where: { id: "singleton" },
    select: { geminiApiKey: true, geminiModel: true },
  }));

  if (!settings?.geminiApiKey) {
    return { ok: false, error: "Gemini API key is not configured." };
  }

  try {
    const { generateGeminiImage } = await import("../gemini-client.js");
    const model = settings.geminiModel ?? "gemini-2.5-flash-image";
    const dataUrl = await generateGeminiImage(
      settings.geminiApiKey,
      "A simple blue circle on white background, minimal, 256x256",
      model,
    );
    const hasImage = dataUrl.startsWith("data:image/");

    void createAuditEntry({
      db: ctx.db,
      entityType: "SystemSettings",
      entityId: "singleton",
      entityName: "Gemini Connection Test",
      action: "UPDATE",
      ...withAuditUser(ctx.dbUser?.id),
      after: { testResult: hasImage ? "success" : "failed" },
      source: "ui",
      summary: hasImage ? "Gemini image generation test succeeded" : "Gemini test returned no image",
    });

    return { ok: hasImage, model, preview: hasImage ? `${dataUrl.slice(0, 100)}...` : undefined };
  } catch (err) {
    const { parseGeminiError } = await import("../gemini-client.js");
    return { ok: false, error: parseGeminiError(err) };
  }
}

export async function getAiConfiguredStatus(
  ctx: SettingsProcedureContext,
) {
  const settings = resolveSystemSettingsRuntime(await ctx.db.systemSettings.findUnique({
    where: { id: "singleton" },
    select: {
      aiProvider: true,
      azureOpenAiEndpoint: true,
      azureOpenAiDeployment: true,
      azureOpenAiApiKey: true,
    },
  }));
  return { configured: isAiConfigured(settings) };
}
