"use client";

import * as React from "react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { apiFetch } from "@/lib/api";
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
import { Textarea } from "@/components/ui/textarea";
import { Switch } from "@/components/ui/switch";
import { Button } from "@/components/ui/button";
import { Select, SelectTrigger, SelectContent, SelectItem, SelectValue } from "@/components/ui/select";
import { CONTEXT_PRESETS, DEFAULT_SYSTEM_PROMPT, KEEP_ALIVE_PRESETS } from "@/lib/constants";
import { RotateCcw, Check, AlertTriangle, Loader2 } from "lucide-react";
import { ThemeToggle } from "@/components/theme-toggle";
import { toast } from "sonner";

interface MeResponse {
  user: {
    id: string;
    username: string;
    role: string;
    ollamaUrl: string;
    defaultModel: string | null;
    defaultContext: number;
    defaultSystemPrompt: string;
    defaultKeepAlive: number;
    showThinking: boolean;
  };
}

export function GeneralSettings() {
  const qc = useQueryClient();
  const meQuery = useQuery({
    queryKey: ["me"],
    queryFn: () => apiFetch<MeResponse>("/api/me"),
  });
  const me = meQuery.data?.user;

  const [ollamaUrl, setOllamaUrl] = React.useState("");
  const [defaultContext, setDefaultContext] = React.useState(8192);
  const [defaultSystemPrompt, setDefaultSystemPrompt] = React.useState("");
  const [defaultKeepAlive, setDefaultKeepAlive] = React.useState(300);
  const [keepAliveMode, setKeepAliveMode] = React.useState<"preset" | "custom">("preset");
  const [showThinking, setShowThinking] = React.useState(true);
  const [contextMode, setContextMode] = React.useState<"preset" | "custom">("preset");

  React.useEffect(() => {
    if (!me) return;
    setOllamaUrl(me.ollamaUrl);
    setDefaultContext(me.defaultContext);
    setDefaultSystemPrompt(me.defaultSystemPrompt || DEFAULT_SYSTEM_PROMPT);
    setDefaultKeepAlive(me.defaultKeepAlive);
    setShowThinking(me.showThinking);
    setContextMode(CONTEXT_PRESETS.some((p) => p.value === me.defaultContext) ? "preset" : "custom");
    setKeepAliveMode(
      KEEP_ALIVE_PRESETS.some((p) => p.value === me.defaultKeepAlive) ? "preset" : "custom",
    );
  }, [me]);

  const [testing, setTesting] = React.useState(false);
  const [testResult, setTestResult] = React.useState<{ ok: boolean; version?: string; error?: string } | null>(null);
  async function testConnection() {
    setTesting(true);
    setTestResult(null);
    try {
      const r = await apiFetch<{ ok: boolean; version?: string; error?: string }>(
        `/api/models/test?url=${encodeURIComponent(ollamaUrl)}`,
      );
      setTestResult(r);
    } catch (e) {
      setTestResult({ ok: false, error: e instanceof Error ? e.message : "Failed" });
    } finally {
      setTesting(false);
    }
  }

  const save = useMutation({
    mutationFn: () =>
      apiFetch("/api/me", {
        method: "PATCH",
        body: JSON.stringify({
          ollamaUrl,
          defaultContext,
          defaultSystemPrompt,
          defaultKeepAlive,
          showThinking,
        }),
      }),
    onSuccess: () => {
      toast.success("Settings saved");
      qc.invalidateQueries({ queryKey: ["me"] });
      qc.invalidateQueries({ queryKey: ["models"] });
    },
    onError: (e: Error) => toast.error(e.message),
  });

  if (!me) return <div className="p-4 text-sm text-muted-foreground">Loading…</div>;

  return (
    <div className="space-y-6">
      <Card>
        <CardHeader>
          <CardTitle>Ollama connection</CardTitle>
          <CardDescription>Where your Ollama runtime is hosted.</CardDescription>
        </CardHeader>
        <CardContent className="space-y-4">
          <div className="space-y-2">
            <Label htmlFor="url">API URL</Label>
            <div className="flex gap-2">
              <Input id="url" value={ollamaUrl} onChange={(e) => setOllamaUrl(e.target.value)} />
              <Button variant="secondary" onClick={testConnection} disabled={testing}>
                {testing ? <Loader2 className="animate-spin" /> : "Test"}
              </Button>
            </div>
            {testResult && (
              <p
                className={
                  testResult.ok
                    ? "flex items-center gap-1 text-xs text-emerald-600 dark:text-emerald-400"
                    : "flex items-center gap-1 text-xs text-destructive"
                }
              >
                {testResult.ok ? <Check className="h-3 w-3" /> : <AlertTriangle className="h-3 w-3" />}
                {testResult.ok ? `Connected (v${testResult.version})` : testResult.error}
              </p>
            )}
          </div>
        </CardContent>
      </Card>

      <Card>
        <CardHeader>
          <CardTitle>Appearance</CardTitle>
          <CardDescription>Theme preferences.</CardDescription>
        </CardHeader>
        <CardContent className="flex items-center justify-between">
          <div>
            <Label>Theme</Label>
            <p className="text-xs text-muted-foreground">Toggle between light and dark.</p>
          </div>
          <ThemeToggle />
        </CardContent>
      </Card>

      <Card>
        <CardHeader>
          <CardTitle>Defaults</CardTitle>
          <CardDescription>Applied to new chats.</CardDescription>
        </CardHeader>
        <CardContent className="space-y-4">
          <div className="space-y-2">
            <Label>Context window</Label>
            <Select
              value={contextMode === "preset" ? String(defaultContext) : "custom"}
              onValueChange={(v) => {
                if (v === "custom") setContextMode("custom");
                else {
                  setContextMode("preset");
                  setDefaultContext(Number(v));
                }
              }}
            >
              <SelectTrigger>
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                {CONTEXT_PRESETS.map((p) => (
                  <SelectItem key={p.value} value={String(p.value)}>
                    {p.label} ({p.value.toLocaleString()})
                  </SelectItem>
                ))}
                <SelectItem value="custom">Custom…</SelectItem>
              </SelectContent>
            </Select>
            {contextMode === "custom" && (
              <Input
                type="number"
                min={512}
                step={512}
                value={defaultContext}
                onChange={(e) => setDefaultContext(Number(e.target.value))}
              />
            )}
          </div>

          <div className="space-y-2">
            <Label>Keep model in memory (keep_alive)</Label>
            <p className="text-xs text-muted-foreground">
              How long Ollama should keep the model loaded after each response.
            </p>
            <Select
              value={keepAliveMode === "preset" ? String(defaultKeepAlive) : "custom"}
              onValueChange={(v) => {
                if (v === "custom") setKeepAliveMode("custom");
                else {
                  setKeepAliveMode("preset");
                  setDefaultKeepAlive(Number(v));
                }
              }}
            >
              <SelectTrigger>
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                {KEEP_ALIVE_PRESETS.map((p) => (
                  <SelectItem key={p.value} value={String(p.value)}>
                    {p.label}
                  </SelectItem>
                ))}
                <SelectItem value="custom">Custom (seconds)…</SelectItem>
              </SelectContent>
            </Select>
            {keepAliveMode === "custom" && (
              <Input
                type="number"
                min={-1}
                value={defaultKeepAlive}
                onChange={(e) => setDefaultKeepAlive(Number(e.target.value))}
                placeholder="Seconds (-1 = forever, 0 = unload)"
              />
            )}
          </div>

          <div className="space-y-2">
            <div className="flex items-center justify-between">
              <Label>Default system prompt</Label>
              <Button
                variant="ghost"
                size="sm"
                className="h-7 gap-1 text-xs"
                onClick={() => setDefaultSystemPrompt(DEFAULT_SYSTEM_PROMPT)}
              >
                <RotateCcw className="!h-3 !w-3" />
                Reset
              </Button>
            </div>
            <Textarea
              value={defaultSystemPrompt}
              onChange={(e) => setDefaultSystemPrompt(e.target.value)}
              className="min-h-[140px] text-sm"
            />
          </div>
          <div className="flex items-center justify-between rounded-lg border border-border px-4 py-3">
            <div>
              <Label>Show thinking by default</Label>
              <p className="text-xs text-muted-foreground">Display reasoning when models emit it.</p>
            </div>
            <Switch checked={showThinking} onCheckedChange={setShowThinking} />
          </div>
        </CardContent>
      </Card>

      <div className="flex justify-end">
        <Button onClick={() => save.mutate()} disabled={save.isPending}>
          {save.isPending ? "Saving…" : "Save changes"}
        </Button>
      </div>
    </div>
  );
}
