"use client";

import { useRouter } from "next/navigation";
import { useState, useTransition } from "react";
import {
  resetAssistantName,
  resetAssistantSystemPrompt,
  setAssistantEnabled,
  setAssistantName,
  setAssistantModelRoute,
  setAssistantSystemPrompt,
} from "@/app/settings/assistant-actions";
import { DEFAULT_ASSISTANT_NAME, MAX_ASSISTANT_NAME_LENGTH } from "@/lib/assistant-config";
import type { AssistantModelRoute } from "@/lib/llm/models";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Switch } from "@/components/ui/switch";

type Props = {
  enabled: boolean;
  name: string;
  modelRoute: string | null;
  systemPrompt: string | null;
  defaultSystemPrompt: string;
};

function normalizeAssistantModelRoute(value: string | null): AssistantModelRoute {
  return value === "uncensored" ? "uncensored" : "auto";
}

export function AssistantSettings({
  enabled,
  name,
  modelRoute,
  systemPrompt,
  defaultSystemPrompt,
}: Props) {
  const [isPending, startTransition] = useTransition();
  const router = useRouter();

  const effectivePrompt = systemPrompt ?? defaultSystemPrompt;
  const [selectedRoute, setSelectedRoute] = useState<AssistantModelRoute>(() =>
    normalizeAssistantModelRoute(modelRoute),
  );
  const [savedName, setSavedName] = useState(name);
  const [draftName, setDraftName] = useState(name);
  const [savedPrompt, setSavedPrompt] = useState(systemPrompt);
  const [draftPrompt, setDraftPrompt] = useState(effectivePrompt);

  const nameDirty = draftName.trim() !== savedName;
  const promptDirty =
    savedPrompt === null
      ? draftPrompt.trim() !== defaultSystemPrompt.trim()
      : draftPrompt.trim() !== savedPrompt.trim();
  const usingDefaultPrompt = savedPrompt === null;

  function toggle(next: boolean) {
    startTransition(async () => {
      await setAssistantEnabled(next);
      router.refresh();
    });
  }

  function changeModelRoute(nextRoute: string) {
    const route = normalizeAssistantModelRoute(nextRoute);
    setSelectedRoute(route);

    startTransition(async () => {
      await setAssistantModelRoute(route);
      router.refresh();
    });
  }

  function saveName() {
    const next = draftName.trim();
    if (!next) return;

    startTransition(async () => {
      await setAssistantName(next);
      setSavedName(next);
      setDraftName(next);
      router.refresh();
    });
  }

  function savePrompt() {
    const next = draftPrompt.trim();
    if (!next) return;

    startTransition(async () => {
      const isDefault = next === defaultSystemPrompt.trim();
      await setAssistantSystemPrompt(isDefault ? null : next);
      setSavedPrompt(isDefault ? null : next);
      setDraftPrompt(next);
      router.refresh();
    });
  }

  function handleResetName() {
    startTransition(async () => {
      await resetAssistantName();
      setSavedName(DEFAULT_ASSISTANT_NAME);
      setDraftName(DEFAULT_ASSISTANT_NAME);
      router.refresh();
    });
  }

  function handleResetPrompt() {
    startTransition(async () => {
      await resetAssistantSystemPrompt();
      setSavedPrompt(null);
      setDraftPrompt(defaultSystemPrompt);
      router.refresh();
    });
  }

  return (
    <div className="flex flex-col gap-5">
      <label className="flex items-center justify-between gap-4">
        <div className="min-w-0">
          <div className="text-sm font-medium">AI assistant</div>
          <p className="muted text-[12px] mt-0.5">
            Off by default. Turn on to show a chat bubble in the bottom-right corner.
          </p>
        </div>
        <Switch
          checked={enabled}
          disabled={isPending}
          onCheckedChange={toggle}
          aria-label="AI assistant"
        />
      </label>

      <div className="flex flex-col gap-2">
        <div className="min-w-0">
          <label htmlFor="assistant-model-route" className="text-sm font-medium">
            Model route
          </label>
          <p className="muted text-[12px] mt-0.5">
            Choose the default router family for your assistant. Individual models can still be
            picked from the chat panel.
          </p>
        </div>
        <select
          id="assistant-model-route"
          aria-label="Assistant model route"
          value={selectedRoute}
          disabled={isPending}
          onChange={(event) => changeModelRoute(event.target.value)}
          className="input h-10"
        >
          <option value="auto">Auto</option>
          <option value="uncensored">Uncensored</option>
        </select>
      </div>

      <div className="flex flex-col gap-2">
        <div className="flex items-end justify-between gap-3">
          <div className="min-w-0 flex-1">
            <label htmlFor="assistant-name" className="text-sm font-medium">
              Assistant name
            </label>
            <p className="muted text-[12px] mt-0.5">Shown in the chat bubble and message labels.</p>
          </div>
          <Button
            type="button"
            variant="ghost"
            size="sm"
            disabled={isPending || savedName === DEFAULT_ASSISTANT_NAME}
            onClick={handleResetName}
          >
            Reset
          </Button>
        </div>
        <Input
          id="assistant-name"
          value={draftName}
          maxLength={MAX_ASSISTANT_NAME_LENGTH}
          disabled={isPending}
          onChange={(event) => setDraftName(event.target.value)}
          aria-label="Assistant name"
        />
        <Button
          type="button"
          size="sm"
          disabled={!nameDirty || isPending || !draftName.trim()}
          onClick={saveName}
        >
          {isPending ? "Saving…" : "Save name"}
        </Button>
      </div>

      <div className="flex flex-col gap-2">
        <div className="flex items-end justify-between gap-3">
          <div className="min-w-0 flex-1">
            <label htmlFor="assistant-system-prompt" className="text-sm font-medium">
              System prompt
            </label>
            <p className="muted text-[12px] mt-0.5">
              Instructions sent to the model before each conversation. Customize tone, priorities,
              or household context.
            </p>
          </div>
          <Button
            type="button"
            variant="ghost"
            size="sm"
            disabled={isPending || usingDefaultPrompt}
            onClick={handleResetPrompt}
          >
            Reset
          </Button>
        </div>
        <textarea
          id="assistant-system-prompt"
          value={draftPrompt}
          rows={10}
          disabled={isPending}
          onChange={(event) => setDraftPrompt(event.target.value)}
          aria-label="Assistant system prompt"
          className="input min-h-[180px] resize-y font-mono text-[12px] leading-relaxed"
        />
        <Button
          type="button"
          size="sm"
          disabled={!promptDirty || isPending || !draftPrompt.trim()}
          onClick={savePrompt}
        >
          {isPending ? "Saving…" : "Save prompt"}
        </Button>
      </div>
    </div>
  );
}
