"use client";

import { DEFAULT_OPENAI_MODEL } from "@nexus/shared";
import { useEffect, useState } from "react";
import { trpc } from "~/lib/trpc/client.js";
import { AiProviderPanel, GenerationSettingsPanel } from "./system-settings/AiSettingsPanels.js";
import { LegacyRuntimeSecretsNotice } from "./system-settings/LegacyRuntimeSecretsNotice.js";
import {
  type ImageProvider,
  type Provider,
  type ScoreWeights,
  type SaveResult,
  type SystemRole,
  type UrlParsedType,
} from "./system-settings/shared.js";
import { AnonymizationSettingsPanel } from "./system-settings/AnonymizationSettingsPanel.js";
import { ImageGenerationPanel } from "./system-settings/ImageGenerationPanel.js";
import { SmtpSettingsPanel } from "./system-settings/SmtpSettingsPanel.js";
import { TimelineSettingsPanel } from "./system-settings/TimelineSettingsPanel.js";
import { VacationSettingsPanel } from "./system-settings/VacationSettingsPanel.js";
import { ValueScorePanel } from "./system-settings/ValueScorePanel.js";
import { parseAzureUrl, type GeminiTestResult } from "./system-settings/shared.js";

export function SystemSettingsClient() {
  const [provider, setProvider] = useState<Provider>("openai");
  const [endpoint, setEndpoint] = useState("");
  const [model, setModel] = useState(DEFAULT_OPENAI_MODEL);
  const [apiVersion, setApiVersion] = useState("2025-01-01-preview");
  const [maxTokens, setMaxTokens] = useState(2000);
  const [temperature, setTemperature] = useState(1);
  const [summaryPrompt, setSummaryPrompt] = useState("");
  const [saved, setSaved] = useState(false);
  const [testResult, setTestResult] = useState<SaveResult | null>(null);
  const [urlPasteValue, setUrlPasteValue] = useState("");
  const [urlParseError, setUrlParseError] = useState(false);
  const [urlParsedType, setUrlParsedType] = useState<UrlParsedType>(null);
  const [scoreWeights, setScoreWeights] = useState<ScoreWeights>({
    skillDepth: 0.3,
    skillBreadth: 0.15,
    costEfficiency: 0.25,
    chargeability: 0.15,
    experience: 0.15,
  });
  const [scoreVisibleRoles, setScoreVisibleRoles] = useState<SystemRole[]>(["ADMIN", "MANAGER"]);
  const [scoreSaved, setScoreSaved] = useState(false);
  const [recomputeResult, setRecomputeResult] = useState<{ updated: number } | null>(null);
  const [dalleDeployment, setDalleDeployment] = useState("");
  const [dalleEndpoint, setDalleEndpoint] = useState("");
  const [imageProvider, setImageProvider] = useState<ImageProvider>("dalle");
  const [geminiModel, setGeminiModel] = useState("");
  const [imageSaved, setImageSaved] = useState(false);
  const [anonymizationEnabled, setAnonymizationEnabled] = useState(false);
  const [anonymizationDomain, setAnonymizationDomain] = useState("superhartmut.de");
  const [anonymizationSaved, setAnonymizationSaved] = useState(false);
  const [vacationDefaultDays, setVacationDefaultDays] = useState(28);
  const [vacationSaved, setVacationSaved] = useState(false);
  const [undoMaxSteps, setUndoMaxSteps] = useState(50);
  const [timelineSaved, setTimelineSaved] = useState(false);
  const [legacyCleanupResult, setLegacyCleanupResult] = useState<string | null>(null);
  const [geminiTestResult, setGeminiTestResult] = useState<GeminiTestResult | null>(null);

  const utils = trpc.useUtils();
  const { data: settings, isLoading } = trpc.settings.getSystemSettings.useQuery(undefined, {
    staleTime: 0,
  });

  useEffect(() => {
    if (!settings) {
      return;
    }

    setProvider((settings.aiProvider ?? "openai") as Provider);
    setEndpoint(settings.azureOpenAiEndpoint ?? "");
    setModel(settings.azureOpenAiDeployment ?? DEFAULT_OPENAI_MODEL);
    setApiVersion(settings.azureApiVersion ?? "2025-01-01-preview");
    setMaxTokens(settings.aiMaxCompletionTokens ?? 2000);
    setTemperature(settings.aiTemperature ?? 1);
    setSummaryPrompt(settings.aiSummaryPrompt ?? "");
    if (settings.scoreWeights) {
      setScoreWeights(settings.scoreWeights as ScoreWeights);
    }
    if (settings.scoreVisibleRoles) {
      setScoreVisibleRoles(settings.scoreVisibleRoles as SystemRole[]);
    }
    setDalleDeployment(settings.azureDalleDeployment ?? "");
    setDalleEndpoint(settings.azureDalleEndpoint ?? "");
    setImageProvider((settings.imageProvider ?? "dalle") as ImageProvider);
    setGeminiModel(settings.geminiModel ?? "");
    setAnonymizationEnabled(settings.anonymizationEnabled ?? false);
    setAnonymizationDomain(settings.anonymizationDomain ?? "superhartmut.de");
    setVacationDefaultDays(settings.vacationDefaultDays ?? 28);
    setUndoMaxSteps(settings.timelineUndoMaxSteps ?? 50);
  }, [settings]);

  function invalidateSystemSettings() {
    void utils.settings.getSystemSettings.invalidate();
  }

  function handleUrlPaste(raw: string) {
    setUrlPasteValue(raw);
    if (!raw) {
      setUrlParseError(false);
      setUrlParsedType(null);
      return;
    }

    const parsed = parseAzureUrl(raw);
    if (!parsed) {
      setUrlParseError(true);
      setUrlParsedType(null);
      return;
    }

    setEndpoint(parsed.endpoint);
    setApiVersion(parsed.apiVersion);
    if (parsed.deployment) {
      setModel(parsed.deployment);
    }
    setUrlParseError(false);
    setUrlParsedType(parsed.urlType);
    setUrlPasteValue("");
  }

  const updateMutation = trpc.settings.updateSystemSettings.useMutation({
    onSuccess: () => {
      setSaved(true);
      setTestResult(null);
      setLegacyCleanupResult(null);
      invalidateSystemSettings();
      setTimeout(() => setSaved(false), 3000);
    },
  });

  const testMutation = trpc.settings.testAiConnection.useMutation({
    onSuccess: (data) => setTestResult(data),
    onError: (error) => setTestResult({ ok: false, error: error.message }),
  });

  const saveScoreMutation = trpc.settings.updateSystemSettings.useMutation({
    onSuccess: () => {
      setScoreSaved(true);
      invalidateSystemSettings();
      setTimeout(() => setScoreSaved(false), 3000);
    },
  });

  const recomputeMutation = trpc.resource.recomputeValueScores.useMutation({
    onSuccess: (data) => setRecomputeResult(data),
  });

  const saveAnonymizationMutation = trpc.settings.updateSystemSettings.useMutation({
    onSuccess: () => {
      setAnonymizationSaved(true);
      setLegacyCleanupResult(null);
      invalidateSystemSettings();
      setTimeout(() => setAnonymizationSaved(false), 3000);
    },
  });

  const saveVacationMutation = trpc.settings.updateSystemSettings.useMutation({
    onSuccess: () => {
      setVacationSaved(true);
      invalidateSystemSettings();
      setTimeout(() => setVacationSaved(false), 3000);
    },
  });

  const saveTimelineMutation = trpc.settings.updateSystemSettings.useMutation({
    onSuccess: () => {
      setTimelineSaved(true);
      invalidateSystemSettings();
      setTimeout(() => setTimelineSaved(false), 3000);
    },
  });

  const saveImageMutation = trpc.settings.updateSystemSettings.useMutation({
    onSuccess: () => {
      setImageSaved(true);
      setLegacyCleanupResult(null);
      invalidateSystemSettings();
      setTimeout(() => setImageSaved(false), 3000);
    },
  });

  const clearRuntimeSecretsMutation = trpc.settings.clearStoredRuntimeSecrets.useMutation({
    onSuccess: (data) => {
      setLegacyCleanupResult(
        data.clearedFields.length > 0
          ? `Cleared ${data.clearedFields.length} legacy database secret field${data.clearedFields.length === 1 ? "" : "s"}.`
          : "No legacy database secrets were left to clear.",
      );
      invalidateSystemSettings();
    },
    onError: (error) => setLegacyCleanupResult(error.message),
  });

  const testGeminiMutation = trpc.settings.testGeminiConnection.useMutation({
    onSuccess: (data) => setGeminiTestResult(data as GeminiTestResult),
    onError: (error) => setGeminiTestResult({ ok: false, error: error.message }),
  });

  function handleSave() {
    updateMutation.mutate({
      aiProvider: provider,
      azureOpenAiEndpoint: provider === "azure" ? endpoint : "",
      azureOpenAiDeployment: model,
      azureApiVersion: provider === "azure" ? apiVersion : undefined,
      aiMaxCompletionTokens: maxTokens,
      aiTemperature: temperature,
      aiSummaryPrompt: summaryPrompt || undefined,
    });
  }

  function handleSaveScoreSettings() {
    saveScoreMutation.mutate({ scoreWeights, scoreVisibleRoles });
  }

  function handleSaveImage() {
    saveImageMutation.mutate({
      imageProvider,
      azureDalleDeployment: dalleDeployment || undefined,
      azureDalleEndpoint: provider === "azure" && dalleEndpoint ? dalleEndpoint : undefined,
      geminiModel: geminiModel || undefined,
    });
  }

  function handleSaveVacation() {
    saveVacationMutation.mutate({ vacationDefaultDays });
  }

  function handleSaveTimeline() {
    saveTimelineMutation.mutate({ timelineUndoMaxSteps: undoMaxSteps });
  }

  function handleSaveAnonymization() {
    saveAnonymizationMutation.mutate({
      anonymizationEnabled,
      anonymizationDomain: anonymizationDomain.trim() || "superhartmut.de",
      anonymizationMode: "global",
    });
  }

  function updateWeight(key: keyof ScoreWeights, value: number) {
    setScoreWeights((previous) => ({ ...previous, [key]: value }));
  }

  function toggleRole(role: SystemRole) {
    setScoreVisibleRoles((previous) =>
      previous.includes(role) ? previous.filter((entry) => entry !== role) : [...previous, role],
    );
  }

  function handleClearLegacyRuntimeSecrets() {
    if (
      typeof window !== "undefined" &&
      !window.confirm(
        "Clear all legacy runtime secrets from database storage? Environment-based deployment secrets must already be configured.",
      )
    ) {
      return;
    }

    clearRuntimeSecretsMutation.mutate();
  }

  const weightSum = Object.values(scoreWeights).reduce((sum, value) => sum + value, 0);
  const weightSumOk = Math.abs(weightSum - 1.0) < 0.01;

  if (isLoading) {
    return (
      <div className="app-page">
        <div className="h-8 w-48 rounded shimmer-skeleton" />
      </div>
    );
  }

  if (!settings) {
    return (
      <div className="app-page">
        <div className="rounded-2xl border border-red-200 bg-red-50 px-5 py-4 text-sm text-red-700 dark:border-red-800 dark:bg-red-950/30 dark:text-red-300">
          System settings could not be loaded.
        </div>
      </div>
    );
  }

  return (
    <div className="app-page space-y-6">
      <div className="app-page-header gap-4">
        <div>
          <h1 className="app-page-title">System Settings</h1>
          <p className="app-page-subtitle mt-1">
            Configure AI integration for skill profile generation.
          </p>
        </div>
      </div>

      <LegacyRuntimeSecretsNotice
        fields={settings.legacyStoredSecretFields}
        result={legacyCleanupResult}
        isPending={clearRuntimeSecretsMutation.isPending}
        onClear={handleClearLegacyRuntimeSecrets}
      />

      <div className="grid grid-cols-1 items-start gap-6 lg:grid-cols-2">
        <AiProviderPanel
          provider={provider}
          endpoint={endpoint}
          model={model}
          apiVersion={apiVersion}
          urlPasteValue={urlPasteValue}
          urlParseError={urlParseError}
          urlParsedType={urlParsedType}
          runtimeSecret={settings.runtimeSecrets.azureOpenAiApiKey}
          testResult={testResult}
          isSaving={updateMutation.isPending}
          isTesting={testMutation.isPending}
          saved={saved}
          onProviderChange={(nextProvider) => {
            setProvider(nextProvider);
            setTestResult(null);
          }}
          onEndpointChange={setEndpoint}
          onModelChange={setModel}
          onApiVersionChange={setApiVersion}
          onUrlPaste={handleUrlPaste}
          onSave={handleSave}
          onTest={() => {
            setTestResult(null);
            testMutation.mutate();
          }}
        />

        <GenerationSettingsPanel
          maxTokens={maxTokens}
          temperature={temperature}
          summaryPrompt={summaryPrompt}
          defaultSummaryPrompt={settings.defaultSummaryPrompt ?? ""}
          isSaving={updateMutation.isPending}
          saved={saved}
          onMaxTokensChange={setMaxTokens}
          onTemperatureChange={setTemperature}
          onSummaryPromptChange={setSummaryPrompt}
          onSave={handleSave}
          onResetSummaryPrompt={() => setSummaryPrompt("")}
        />
      </div>

      <ValueScorePanel
        scoreWeights={scoreWeights}
        scoreVisibleRoles={scoreVisibleRoles}
        weightSum={weightSum}
        weightSumOk={weightSumOk}
        scoreSaved={scoreSaved}
        recomputeResult={recomputeResult}
        isSaving={saveScoreMutation.isPending}
        isRecomputing={recomputeMutation.isPending}
        onUpdateWeight={updateWeight}
        onToggleRole={toggleRole}
        onRecompute={() => {
          setRecomputeResult(null);
          recomputeMutation.mutate();
        }}
        onSave={handleSaveScoreSettings}
      />

      <ImageGenerationPanel
        provider={provider}
        imageProvider={imageProvider}
        dalleDeployment={dalleDeployment}
        dalleEndpoint={dalleEndpoint}
        geminiModel={geminiModel}
        imageSaved={imageSaved}
        geminiTestResult={geminiTestResult}
        runtimeSecrets={settings.runtimeSecrets}
        isSaving={saveImageMutation.isPending}
        isTestingGemini={testGeminiMutation.isPending}
        onImageProviderChange={setImageProvider}
        onDalleDeploymentChange={setDalleDeployment}
        onDalleEndpointChange={setDalleEndpoint}
        onGeminiModelChange={setGeminiModel}
        onSave={handleSaveImage}
        onTestGemini={() => testGeminiMutation.mutate()}
      />

      <SmtpSettingsPanel initialSettings={settings} onSettingsSaved={invalidateSystemSettings} />

      <VacationSettingsPanel
        vacationDefaultDays={vacationDefaultDays}
        vacationSaved={vacationSaved}
        isSaving={saveVacationMutation.isPending}
        onVacationDefaultDaysChange={setVacationDefaultDays}
        onSave={handleSaveVacation}
      />

      <TimelineSettingsPanel
        undoMaxSteps={undoMaxSteps}
        timelineSaved={timelineSaved}
        isSaving={saveTimelineMutation.isPending}
        onUndoMaxStepsChange={setUndoMaxSteps}
        onSave={handleSaveTimeline}
      />

      <AnonymizationSettingsPanel
        anonymizationEnabled={anonymizationEnabled}
        anonymizationDomain={anonymizationDomain}
        anonymizationSaved={anonymizationSaved}
        anonymizationSecret={settings.runtimeSecrets.anonymizationSeed}
        isSaving={saveAnonymizationMutation.isPending}
        onAnonymizationEnabledChange={setAnonymizationEnabled}
        onAnonymizationDomainChange={setAnonymizationDomain}
        onSave={handleSaveAnonymization}
      />
    </div>
  );
}
