"use client";

import * as React from "react";
import { toast } from "sonner";
import { useTheme } from "next-themes";
import {
  Loader2,
  Save,
  Wifi,
  WifiOff,
  Trash2,
  Brain,
  FolderSearch,
  HardDrive,
  Settings,
  Sun,
  Moon,
  Monitor,
  Bell,
  Mail,
  LayoutGrid,
  Globe,
  Check,
  RefreshCw,
} from "lucide-react";

import { Header } from "@/components/layout/header";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Badge } from "@/components/ui/badge";
import { Switch } from "@/components/ui/switch";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs";

const AI_PROVIDERS = [
  {
    value: "gateway",
    label: "Vercel AI Gateway",
    defaultModel: "openai/gpt-4o-mini",
    hint: "openai/gpt-4o-mini, google/gemini-2.5-flash, anthropic/claude-sonnet-4-20250514",
  },
  {
    value: "ollama",
    label: "Ollama (Local)",
    defaultModel: "llava:7b",
    hint: "llava:7b, moondream, llama3.2-vision",
  },
] as const;

import { Checkbox } from "@/components/ui/checkbox";

type MondayColumn = { id: string; title: string; type: string };

const MONDAY_MAPPABLE_FIELDS = [
  { field: "name", label: "Name" },
  { field: "gender", label: "Gender" },
  { field: "dateOfBirth", label: "Date of Birth" },
  { field: "maritalStatus", label: "Marital Status" },
  { field: "visitType", label: "Visit Type" },
  { field: "followUp", label: "Follow-Up" },
  { field: "cellPhone", label: "Cell Phone" },
  { field: "homePhone", label: "Home Phone" },
  { field: "email", label: "Email" },
  { field: "address", label: "Address" },
  { field: "aptNumber", label: "Apt #" },
  { field: "city", label: "City" },
  { field: "state", label: "State" },
  { field: "zip", label: "Zip" },
  { field: "prayerRequests", label: "Prayer Requests" },
  { field: "prayerForTeam", label: "For Prayer Team" },
  { field: "prayerConfidential", label: "Confidential" },
  { field: "messageTopics", label: "Message Topics" },
  { field: "messageTopicsOther", label: "Other - Topics" },
  { field: "nextStep", label: "Next Step" },
  { field: "attendanceDuration", label: "Attendance Duration" },
  { field: "campusPreference", label: "Campus Preference" },
  { field: "campusPreferenceOther", label: "Other Location" },
  { field: "howHeard", label: "How Did You Hear" },
  { field: "howHeardOther", label: "Other - How Heard" },
  { field: "serviceAttended", label: "A B C D" },
  { field: "serviceTime", label: "Service Time" },
  { field: "notes", label: "Notes" },
  { field: "planningCenter", label: "Planning Center" },
  { field: "iSaidYesBookSent", label: "I Said Yes Book Sent" },
  { field: "ftGuestLetterSent", label: "FT Guest Letter Sent" },
  { field: "reviewStatus", label: "Review Status" },
] as const;

type SettingsData = {
  ollamaUrl: string;
  model: string;
  watchDir: string;
  watching: boolean;
  sourceRetentionDays: number;
  imageRetentionDays: number;
  aiProvider: string;
  aiModel: string;
  emailImapHost: string;
  emailImapPort: number;
  emailImapUser: string;
  emailImapPass: string;
  emailImapTls: boolean;
  emailFolder: string;
  emailWatching: boolean;
  emailProcessed: string;
  emailProcessedFolder: string;
  mondayApiToken: string;
  mondayBoardId: string;
  mondayEnabled: boolean;
  mondayColumnMap: Record<string, unknown> | null;
  mondayWebhookId: string;
  mondayWebhookUrl: string;
  webhookUrl: string;
  webhookSecret: string;
  webhookEnabled: boolean;
  webhookEvents: string[] | null;
};

const NOTIFICATION_STORAGE_KEY = "echo-ocr-notification-prefs";

type NotificationPrefs = {
  processingComplete: boolean;
  processingErrors: boolean;
  folderWatchAlerts: boolean;
  cleanupReminders: boolean;
};

const DEFAULT_NOTIFICATION_PREFS: NotificationPrefs = {
  processingComplete: true,
  processingErrors: true,
  folderWatchAlerts: true,
  cleanupReminders: false,
};

function loadNotificationPrefs(): NotificationPrefs {
  if (typeof window === "undefined") return DEFAULT_NOTIFICATION_PREFS;
  try {
    const raw = localStorage.getItem(NOTIFICATION_STORAGE_KEY);
    if (raw) return { ...DEFAULT_NOTIFICATION_PREFS, ...JSON.parse(raw) };
  } catch {}
  return DEFAULT_NOTIFICATION_PREFS;
}

export default function SettingsPage() {
  const { theme, setTheme } = useTheme();

  const [settings, setSettings] = React.useState<SettingsData>({
    ollamaUrl: "",
    model: "",
    watchDir: "",
    watching: false,
    sourceRetentionDays: 30,
    imageRetentionDays: 180,
    aiProvider: "gateway",
    aiModel: "",
    emailImapHost: "imap.dreamhost.com",
    emailImapPort: 993,
    emailImapUser: "echo-ocr@stillwell.cloud",
    emailImapPass: "",
    emailImapTls: true,
    emailFolder: "INBOX",
    emailWatching: false,
    emailProcessed: "mark_read",
    emailProcessedFolder: "Processed",
    mondayApiToken: "",
    mondayBoardId: "",
    mondayEnabled: false,
    mondayColumnMap: null,
    mondayWebhookId: "",
    mondayWebhookUrl: "",
    webhookUrl: "",
    webhookSecret: "",
    webhookEnabled: false,
    webhookEvents: null,
  });
  const [loading, setLoading] = React.useState(true);
  const [saving, setSaving] = React.useState(false);
  const [aiTestStatus, setAiTestStatus] = React.useState<"idle" | "testing" | "success" | "error">("idle");
  const [cleanupStatus, setCleanupStatus] = React.useState<{ sourcesEligible: number; imagesEligible: number } | null>(null);
  const [cleaning, setCleaning] = React.useState(false);
  const [emailTestStatus, setEmailTestStatus] = React.useState<"idle" | "testing" | "success" | "error">("idle");
  const [mondayColumns, setMondayColumns] = React.useState<MondayColumn[]>([]);
  const [fetchingColumns, setFetchingColumns] = React.useState(false);
  const [subscribing, setSubscribing] = React.useState(false);
  const [pushingAll, setPushingAll] = React.useState(false);
  const [webhookTestStatus, setWebhookTestStatus] = React.useState<"idle" | "testing" | "success" | "error">("idle");
  const [recoverCount, setRecoverCount] = React.useState<number | null>(null);
  const [recovering, setRecovering] = React.useState(false);
  const [notifPrefs, setNotifPrefs] = React.useState<NotificationPrefs>(DEFAULT_NOTIFICATION_PREFS);

  React.useEffect(() => {
    setNotifPrefs(loadNotificationPrefs());
  }, []);

  const updateNotifPref = (key: keyof NotificationPrefs, value: boolean) => {
    setNotifPrefs((prev) => {
      const next = { ...prev, [key]: value };
      try { localStorage.setItem(NOTIFICATION_STORAGE_KEY, JSON.stringify(next)); } catch {}
      return next;
    });
    toast.success("Notification preference updated");
  };

  const fetchCleanupStatus = React.useCallback(() => {
    fetch("/api/cleanup")
      .then((r) => r.json())
      .then((data) => {
        if (data.sourcesEligible !== undefined) setCleanupStatus(data);
      })
      .catch(() => {});
  }, []);

  React.useEffect(() => {
    fetch("/api/settings")
      .then((r) => r.json())
      .then((data) => {
        setSettings(data);
        setLoading(false);
      })
      .catch(() => {
        setLoading(false);
      });
    fetchCleanupStatus();
    fetch("/api/cards/recover-survey")
      .then((r) => r.json())
      .then((data) => { if (data.missingCount !== undefined) setRecoverCount(data.missingCount); })
      .catch(() => {});
  }, [fetchCleanupStatus]);

  const handleSave = async () => {
    setSaving(true);
    try {
      const res = await fetch("/api/settings", {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(settings),
      });
      if (!res.ok) throw new Error();
      toast.success("Settings saved");
    } catch {
      toast.error("Failed to save settings");
    } finally {
      setSaving(false);
    }
  };

  const testAiProvider = async () => {
    setAiTestStatus("testing");
    try {
      const res = await fetch("/api/ai-test", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          provider: settings.aiProvider,
          model: settings.aiModel,
          ollamaUrl: settings.ollamaUrl,
        }),
        signal: AbortSignal.timeout(15000),
      });
      if (res.ok) {
        setAiTestStatus("success");
        toast.success("AI provider connected successfully");
      } else {
        const data = await res.json().catch(() => ({}));
        setAiTestStatus("error");
        toast.error(data.error || "AI provider test failed");
      }
    } catch {
      setAiTestStatus("error");
      toast.error("Cannot reach AI provider. Check your configuration and API keys.");
    }
  };

  const handleProviderChange = (value: string | null) => {
    if (!value) return;
    const provider = AI_PROVIDERS.find((p) => p.value === value);
    setSettings((s) => ({
      ...s,
      aiProvider: value,
      aiModel: provider?.defaultModel || "",
    }));
    setAiTestStatus("idle");
  };

  const toggleWatch = async () => {
    try {
      const action = settings.watching ? "stop" : "start";
      const res = await fetch("/api/watch", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ action, watchDir: settings.watchDir }),
      });
      if (!res.ok) throw new Error();
      setSettings((s) => ({ ...s, watching: !s.watching }));
      toast.success(action === "start" ? "Folder watching started" : "Folder watching stopped");
    } catch {
      toast.error("Failed to toggle folder watching");
    }
  };

  const toggleEmailWatch = async () => {
    try {
      const action = settings.emailWatching ? "stop" : "start";
      const res = await fetch("/api/email-watch", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ action }),
      });
      if (!res.ok) {
        const data = await res.json().catch(() => ({}));
        throw new Error(data.error || "Failed");
      }
      setSettings((s) => ({ ...s, emailWatching: !s.emailWatching }));
      toast.success(action === "start" ? "Email monitoring started" : "Email monitoring stopped");
    } catch (err) {
      toast.error(err instanceof Error ? err.message : "Failed to toggle email monitoring");
    }
  };

  const testEmailConnection = async () => {
    setEmailTestStatus("testing");
    try {
      const res = await fetch("/api/email-watch/test", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          host: settings.emailImapHost,
          port: settings.emailImapPort,
          user: settings.emailImapUser,
          pass: settings.emailImapPass,
          tls: settings.emailImapTls,
        }),
        signal: AbortSignal.timeout(15000),
      });
      const data = await res.json().catch(() => ({}));
      if (res.ok && data.ok) {
        setEmailTestStatus("success");
        toast.success(data.message || "Connected successfully");
      } else {
        setEmailTestStatus("error");
        toast.error(data.error || "Connection failed");
      }
    } catch {
      setEmailTestStatus("error");
      toast.error("Cannot reach email server. Check your configuration.");
    }
  };

  const fetchMondayColumns = async () => {
    setFetchingColumns(true);
    try {
      const res = await fetch("/api/integrations/monday/columns", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ token: settings.mondayApiToken, boardId: settings.mondayBoardId }),
      });
      const data = await res.json();
      if (res.ok && data.columns) {
        setMondayColumns(data.columns);
        const typeMap: Record<string, string> = {};
        for (const col of data.columns as MondayColumn[]) {
          typeMap[col.id] = col.type;
        }
        setSettings((s) => ({
          ...s,
          mondayColumnMap: { ...(s.mondayColumnMap || {}), _columnTypes: typeMap },
        }));
        toast.success(`Found ${data.columns.length} columns`);
      } else {
        toast.error(data.error || "Failed to fetch columns");
      }
    } catch {
      toast.error("Failed to connect to Monday.com");
    } finally {
      setFetchingColumns(false);
    }
  };

  const toggleMondaySubscription = async () => {
    setSubscribing(true);
    try {
      const isSubscribed = !!settings.mondayWebhookId;
      const callbackUrl = settings.mondayWebhookUrl || `${window.location.origin}/api/integrations/monday/webhook`;
      const res = await fetch("/api/integrations/monday/subscribe", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          action: isSubscribed ? "unsubscribe" : "subscribe",
          callbackUrl,
        }),
      });
      const data = await res.json();
      if (res.ok) {
        setSettings((s) => ({
          ...s,
          mondayWebhookId: data.webhookId || "",
          mondayWebhookUrl: isSubscribed ? "" : callbackUrl,
        }));
        toast.success(isSubscribed ? "Unsubscribed from Monday.com changes" : "Subscribed to Monday.com changes");
      } else {
        toast.error(data.error || "Failed");
      }
    } catch {
      toast.error("Subscription change failed");
    } finally {
      setSubscribing(false);
    }
  };

  const pushAllToMonday = async () => {
    setPushingAll(true);
    try {
      const res = await fetch("/api/integrations/monday/sync-all", { method: "POST" });
      const data = await res.json();
      if (res.ok) {
        if (data.synced === 0 && data.failed === 0) {
          toast.success("All cards are already synced to Monday.com");
        } else if (data.failed > 0 && data.synced === 0) {
          const errDetail = data.errors?.[0] ? `\n${data.errors[0]}` : "";
          toast.error(`All ${data.failed} card(s) failed to push to Monday.com${errDetail}`);
        } else if (data.failed > 0) {
          toast.warning(`Pushed ${data.synced} card(s), but ${data.failed} failed`);
        } else {
          toast.success(`Pushed ${data.synced} card(s) to Monday.com`);
        }
      } else {
        toast.error(data.error || "Sync failed");
      }
    } catch {
      toast.error("Failed to sync cards to Monday.com");
    } finally {
      setPushingAll(false);
    }
  };

  const testWebhook = async () => {
    setWebhookTestStatus("testing");
    try {
      const res = await fetch("/api/integrations/webhook/test", { method: "POST" });
      const data = await res.json();
      if (data.ok) {
        setWebhookTestStatus("success");
        toast.success("Test webhook sent");
      } else {
        setWebhookTestStatus("error");
        toast.error(data.error || "Webhook test failed");
      }
    } catch {
      setWebhookTestStatus("error");
      toast.error("Webhook test failed");
    }
  };

  const setColumnMapping = (cardField: string, colId: string) => {
    setSettings((s) => ({
      ...s,
      mondayColumnMap: { ...(s.mondayColumnMap || {}), [cardField]: colId },
    }));
  };

  const toggleWebhookEvent = (event: string) => {
    setSettings((s) => {
      const current = s.webhookEvents ?? [];
      const next = current.includes(event) ? current.filter((e) => e !== event) : [...current, event];
      return { ...s, webhookEvents: next };
    });
  };

  const recoverSurveys = async () => {
    setRecovering(true);
    try {
      const res = await fetch("/api/cards/recover-survey", { method: "POST" });
      const data = await res.json();
      if (res.ok) {
        toast.success(data.message || `Recovery started for ${data.queued} card(s)`);
        setRecoverCount(0);
      } else {
        toast.error(data.error || "Recovery failed");
      }
    } catch {
      toast.error("Failed to start recovery");
    } finally {
      setRecovering(false);
    }
  };

  const runCleanup = async () => {
    setCleaning(true);
    try {
      const res = await fetch("/api/cleanup", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ dryRun: false }),
      });
      if (!res.ok) throw new Error();
      const data = await res.json();
      toast.success(
        `Cleanup complete: ${data.sourcesDeleted} source files, ${data.imagesDeleted} images, ${data.jobsPurged} jobs removed`
      );
      fetchCleanupStatus();
    } catch {
      toast.error("Cleanup failed");
    } finally {
      setCleaning(false);
    }
  };

  if (loading) {
    return (
      <div className="flex items-center justify-center py-20">
        <Loader2 className="size-8 animate-spin text-muted-foreground" />
      </div>
    );
  }

  const themeOptions = [
    { value: "light", label: "Light", icon: Sun, description: "Clean and bright interface" },
    { value: "dark", label: "Dark", icon: Moon, description: "Easy on the eyes in low light" },
    { value: "system", label: "System", icon: Monitor, description: "Follows your OS preference" },
  ] as const;

  return (
    <div className="space-y-6">
      <Header title="Settings" description="Configure your app and preferences" icon={Settings}>
        <Button className="rounded-xl" onClick={handleSave} disabled={saving}>
          {saving ? <Loader2 className="mr-2 size-4 animate-spin" /> : <Save className="mr-2 size-4" />}
          Save Settings
        </Button>
      </Header>

      <Tabs defaultValue="application">
        <TabsList variant="line" className="mb-4">
          <TabsTrigger value="application">Application</TabsTrigger>
          <TabsTrigger value="preferences">Preferences</TabsTrigger>
        </TabsList>

        <TabsContent value="application">
          <div className="grid gap-4 sm:gap-6 grid-cols-1 lg:grid-cols-2">
            <Card variant="glass">
              <CardHeader>
                <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
                  <div>
                    <CardTitle className="flex items-center gap-2 text-base">
                      <Brain className="size-4 text-primary" />
                      AI Provider
                    </CardTitle>
                    <CardDescription>Choose the AI model for OCR processing</CardDescription>
                  </div>
                  <Badge
                    variant="secondary"
                    className={
                      aiTestStatus === "success"
                        ? "bg-emerald-500/10 text-emerald-700 dark:text-emerald-300"
                        : aiTestStatus === "error"
                        ? "bg-red-500/10 text-red-700 dark:text-red-300"
                        : ""
                    }
                  >
                    {aiTestStatus === "success" && <Wifi className="mr-1 size-3" />}
                    {aiTestStatus === "error" && <WifiOff className="mr-1 size-3" />}
                    {aiTestStatus === "testing" && <Loader2 className="mr-1 size-3 animate-spin" />}
                    {aiTestStatus === "success"
                      ? "Connected"
                      : aiTestStatus === "error"
                      ? "Error"
                      : aiTestStatus === "testing"
                      ? "Testing..."
                      : "Not tested"}
                  </Badge>
                </div>
              </CardHeader>
              <CardContent className="space-y-4">
                <div>
                  <Label className="mb-1.5 block text-xs font-medium text-muted-foreground">Provider</Label>
                  <Select value={settings.aiProvider} onValueChange={handleProviderChange}>
                    <SelectTrigger>
                      <SelectValue placeholder="Select a provider" />
                    </SelectTrigger>
                    <SelectContent>
                      {AI_PROVIDERS.map((p) => (
                        <SelectItem key={p.value} value={p.value}>
                          {p.label}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                </div>
                <div>
                  <Label className="mb-1.5 block text-xs font-medium text-muted-foreground">Model</Label>
                  <Input
                    value={settings.aiModel}
                    onChange={(e) => setSettings((s) => ({ ...s, aiModel: e.target.value }))}
                    placeholder={AI_PROVIDERS.find((p) => p.value === settings.aiProvider)?.defaultModel || ""}
                  />
                  <p className="mt-1 text-xs text-muted-foreground">
                    {AI_PROVIDERS.find((p) => p.value === settings.aiProvider)?.hint || ""}
                  </p>
                </div>

                {settings.aiProvider === "ollama" && (
                  <div>
                    <Label className="mb-1.5 block text-xs font-medium text-muted-foreground">Ollama URL</Label>
                    <Input
                      value={settings.ollamaUrl}
                      onChange={(e) => setSettings((s) => ({ ...s, ollamaUrl: e.target.value }))}
                      placeholder="http://192.168.68.108:11434"
                    />
                  </div>
                )}

                {settings.aiProvider === "gateway" && (
                  <div className="rounded-xl border border-border/50 bg-muted/30 p-3">
                    <p className="text-xs text-muted-foreground">
                      Uses the <code className="rounded-md bg-muted px-1.5 py-0.5 text-foreground/80">AI_GATEWAY_API_KEY</code> env
                      var. Model format: <code className="rounded-md bg-muted px-1.5 py-0.5 text-foreground/80">provider/model</code>
                    </p>
                  </div>
                )}

                <Button variant="outline" size="sm" className="rounded-xl" onClick={testAiProvider} disabled={aiTestStatus === "testing"}>
                  {aiTestStatus === "testing" ? (
                    <Loader2 className="mr-2 size-3 animate-spin" />
                  ) : (
                    <Wifi className="mr-2 size-3" />
                  )}
                  Test Connection
                </Button>
              </CardContent>
            </Card>

            <Card variant="glass">
              <CardHeader>
                <CardTitle className="flex items-center gap-2 text-base">
                  <FolderSearch className="size-4 text-primary" />
                  Folder Monitoring
                </CardTitle>
                <CardDescription>Automatically process new PDFs dropped into a folder</CardDescription>
              </CardHeader>
              <CardContent className="space-y-4">
                <div>
                  <Label className="mb-1.5 block text-xs font-medium text-muted-foreground">Watch Directory</Label>
                  <Input
                    value={settings.watchDir}
                    onChange={(e) => setSettings((s) => ({ ...s, watchDir: e.target.value }))}
                    placeholder="/data/watch"
                  />
                  <p className="mt-1 text-xs text-muted-foreground">
                    Absolute path on the server. Mount a host folder into the container.
                  </p>
                </div>
                <div className="flex flex-wrap items-center gap-3">
                  <Button
                    variant={settings.watching ? "destructive" : "outline"}
                    size="sm"
                    className="rounded-xl"
                    onClick={toggleWatch}
                    disabled={!settings.watchDir}
                  >
                    {settings.watching ? "Stop Watching" : "Start Watching"}
                  </Button>
                  {settings.watching && (
                    <Badge className="bg-emerald-500/10 text-emerald-700 dark:text-emerald-300">
                      Active
                    </Badge>
                  )}
                </div>
              </CardContent>
            </Card>

            <Card variant="glass">
              <CardHeader>
                <CardTitle className="flex items-center gap-2 text-base">
                  <HardDrive className="size-4 text-primary" />
                  Storage & Cleanup
                </CardTitle>
                <CardDescription>Auto-purge uploaded files and images to save storage</CardDescription>
              </CardHeader>
              <CardContent className="space-y-4">
                <div>
                  <Label className="mb-1.5 block text-xs font-medium text-muted-foreground">
                    Source PDF Retention (days)
                  </Label>
                  <Input
                    type="number"
                    min={1}
                    value={settings.sourceRetentionDays}
                    onChange={(e) =>
                      setSettings((s) => ({
                        ...s,
                        sourceRetentionDays: parseInt(e.target.value) || 30,
                      }))
                    }
                  />
                  <p className="mt-1 text-xs text-muted-foreground">
                    Original uploaded PDFs are deleted after this many days. Card data is kept.
                  </p>
                </div>
                <div>
                  <Label className="mb-1.5 block text-xs font-medium text-muted-foreground">
                    Image Retention (days)
                  </Label>
                  <Input
                    type="number"
                    min={1}
                    value={settings.imageRetentionDays}
                    onChange={(e) =>
                      setSettings((s) => ({
                        ...s,
                        imageRetentionDays: parseInt(e.target.value) || 180,
                      }))
                    }
                  />
                  <p className="mt-1 text-xs text-muted-foreground">
                    Scanned card images are removed after this many days. Card data is kept.
                  </p>
                </div>
                <div className="rounded-xl border border-border/50 bg-muted/30 p-3">
                  <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
                    <div className="text-sm">
                      {cleanupStatus ? (
                        <>
                          <span className="font-medium">{cleanupStatus.sourcesEligible}</span> source files
                          {" and "}
                          <span className="font-medium">{cleanupStatus.imagesEligible}</span> card images eligible
                        </>
                      ) : (
                        "Checking..."
                      )}
                    </div>
                    <Button
                      variant="destructive"
                      size="sm"
                      className="shrink-0 rounded-xl"
                      onClick={runCleanup}
                      disabled={cleaning || !cleanupStatus || (cleanupStatus.sourcesEligible === 0 && cleanupStatus.imagesEligible === 0)}
                    >
                      {cleaning ? <Loader2 className="mr-2 size-3 animate-spin" /> : <Trash2 className="mr-2 size-3" />}
                      Run Cleanup Now
                    </Button>
                  </div>
                </div>

                {recoverCount !== null && recoverCount > 0 && (
                  <div className="mt-4 rounded-xl border border-amber-500/30 bg-amber-500/5 p-3">
                    <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
                      <div className="text-sm">
                        <span className="font-medium text-amber-700 dark:text-amber-300">{recoverCount}</span>{" "}
                        card(s) are missing their survey (back) side.
                        <span className="block mt-0.5 text-xs text-muted-foreground">
                          Re-extracts missing pages from the original source PDFs and runs OCR.
                        </span>
                      </div>
                      <Button
                        variant="outline"
                        size="sm"
                        className="shrink-0 rounded-xl border-amber-500/30 text-amber-700 hover:bg-amber-500/10 dark:text-amber-300"
                        onClick={recoverSurveys}
                        disabled={recovering}
                      >
                        {recovering ? <Loader2 className="mr-2 size-3 animate-spin" /> : <RefreshCw className="mr-2 size-3" />}
                        Recover Missing Backs
                      </Button>
                    </div>
                  </div>
                )}
              </CardContent>
            </Card>

            <Card variant="glass">
              <CardHeader>
                <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
                  <div>
                    <CardTitle className="flex items-center gap-2 text-base">
                      <Mail className="size-4 text-primary" />
                      Email Monitoring
                    </CardTitle>
                    <CardDescription>Watch an inbox for scanned card attachments</CardDescription>
                  </div>
                  <Badge
                    variant="secondary"
                    className={
                      emailTestStatus === "success"
                        ? "bg-emerald-500/10 text-emerald-700 dark:text-emerald-300"
                        : emailTestStatus === "error"
                        ? "bg-red-500/10 text-red-700 dark:text-red-300"
                        : ""
                    }
                  >
                    {emailTestStatus === "success" && <Wifi className="mr-1 size-3" />}
                    {emailTestStatus === "error" && <WifiOff className="mr-1 size-3" />}
                    {emailTestStatus === "testing" && <Loader2 className="mr-1 size-3 animate-spin" />}
                    {emailTestStatus === "success"
                      ? "Connected"
                      : emailTestStatus === "error"
                      ? "Error"
                      : emailTestStatus === "testing"
                      ? "Testing..."
                      : "Not tested"}
                  </Badge>
                </div>
              </CardHeader>
              <CardContent className="space-y-4">
                <div className="grid gap-4 sm:grid-cols-2">
                  <div>
                    <Label className="mb-1.5 block text-xs font-medium text-muted-foreground">IMAP Host</Label>
                    <Input
                      value={settings.emailImapHost}
                      onChange={(e) => setSettings((s) => ({ ...s, emailImapHost: e.target.value }))}
                      placeholder="imap.dreamhost.com"
                    />
                  </div>
                  <div>
                    <Label className="mb-1.5 block text-xs font-medium text-muted-foreground">Port</Label>
                    <Input
                      type="number"
                      value={settings.emailImapPort}
                      onChange={(e) => setSettings((s) => ({ ...s, emailImapPort: parseInt(e.target.value) || 993 }))}
                      placeholder="993"
                    />
                  </div>
                </div>
                <div className="grid gap-4 sm:grid-cols-2">
                  <div>
                    <Label className="mb-1.5 block text-xs font-medium text-muted-foreground">Username</Label>
                    <Input
                      value={settings.emailImapUser}
                      onChange={(e) => setSettings((s) => ({ ...s, emailImapUser: e.target.value }))}
                      placeholder="echo-ocr@stillwell.cloud"
                    />
                  </div>
                  <div>
                    <Label className="mb-1.5 block text-xs font-medium text-muted-foreground">Password</Label>
                    <Input
                      type="password"
                      value={settings.emailImapPass}
                      onChange={(e) => setSettings((s) => ({ ...s, emailImapPass: e.target.value }))}
                      placeholder="••••••••"
                    />
                  </div>
                </div>
                <div className="grid gap-4 sm:grid-cols-2">
                  <div>
                    <Label className="mb-1.5 block text-xs font-medium text-muted-foreground">Folder</Label>
                    <Input
                      value={settings.emailFolder}
                      onChange={(e) => setSettings((s) => ({ ...s, emailFolder: e.target.value }))}
                      placeholder="INBOX"
                    />
                  </div>
                  <div>
                    <Label className="mb-1.5 block text-xs font-medium text-muted-foreground">After Processing</Label>
                    <Select
                      value={settings.emailProcessed}
                      onValueChange={(val) => val && setSettings((s) => ({ ...s, emailProcessed: val }))}
                    >
                      <SelectTrigger>
                        <SelectValue />
                      </SelectTrigger>
                      <SelectContent>
                        <SelectItem value="mark_read">Mark as Read</SelectItem>
                        <SelectItem value="move">Move to Folder</SelectItem>
                        <SelectItem value="delete">Delete</SelectItem>
                      </SelectContent>
                    </Select>
                  </div>
                </div>
                {settings.emailProcessed === "move" && (
                  <div>
                    <Label className="mb-1.5 block text-xs font-medium text-muted-foreground">Move to Folder</Label>
                    <Input
                      value={settings.emailProcessedFolder}
                      onChange={(e) => setSettings((s) => ({ ...s, emailProcessedFolder: e.target.value }))}
                      placeholder="Processed"
                    />
                  </div>
                )}
                <div className="flex items-center gap-3">
                  <Label className="text-xs font-medium text-muted-foreground">TLS / SSL</Label>
                  <Switch
                    checked={settings.emailImapTls}
                    onCheckedChange={(val: boolean) => setSettings((s) => ({ ...s, emailImapTls: val }))}
                  />
                </div>
                <div className="flex flex-wrap items-center gap-3">
                  <Button
                    variant="outline"
                    size="sm"
                    className="rounded-xl"
                    onClick={testEmailConnection}
                    disabled={emailTestStatus === "testing" || !settings.emailImapHost || !settings.emailImapUser || !settings.emailImapPass}
                  >
                    {emailTestStatus === "testing" ? (
                      <Loader2 className="mr-2 size-3 animate-spin" />
                    ) : (
                      <Wifi className="mr-2 size-3" />
                    )}
                    Test Connection
                  </Button>
                  <Button
                    variant={settings.emailWatching ? "destructive" : "outline"}
                    size="sm"
                    className="rounded-xl"
                    onClick={toggleEmailWatch}
                    disabled={!settings.emailImapHost || !settings.emailImapUser || !settings.emailImapPass}
                  >
                    {settings.emailWatching ? "Stop Monitoring" : "Start Monitoring"}
                  </Button>
                  {settings.emailWatching && (
                    <Badge className="bg-emerald-500/10 text-emerald-700 dark:text-emerald-300">
                      Active
                    </Badge>
                  )}
                </div>
              </CardContent>
            </Card>

            <Card variant="glass">
              <CardHeader>
                <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
                  <div>
                    <CardTitle className="flex items-center gap-2 text-base">
                      <LayoutGrid className="size-4 text-primary" />
                      Monday.com Integration
                    </CardTitle>
                    <CardDescription>Bidirectional sync with Monday.com boards</CardDescription>
                  </div>
                  {settings.mondayEnabled && (
                    <Badge className="bg-emerald-500/10 text-emerald-700 dark:text-emerald-300">
                      <Check className="mr-1 size-3" /> Enabled
                    </Badge>
                  )}
                </div>
              </CardHeader>
              <CardContent className="space-y-4">
                <div className="grid gap-4 sm:grid-cols-2">
                  <div>
                    <Label className="mb-1.5 block text-xs font-medium text-muted-foreground">API Token</Label>
                    <Input
                      type="password"
                      value={settings.mondayApiToken}
                      onChange={(e) => setSettings((s) => ({ ...s, mondayApiToken: e.target.value }))}
                      placeholder="••••••••"
                    />
                  </div>
                  <div>
                    <Label className="mb-1.5 block text-xs font-medium text-muted-foreground">Board ID</Label>
                    <Input
                      value={settings.mondayBoardId}
                      onChange={(e) => setSettings((s) => ({ ...s, mondayBoardId: e.target.value }))}
                      placeholder="1234567890"
                    />
                  </div>
                </div>
                <div>
                  <Label className="mb-1.5 block text-xs font-medium text-muted-foreground">App URL (for webhook callback)</Label>
                  <Input
                    value={settings.mondayWebhookUrl || (typeof window !== "undefined" ? `${window.location.origin}/api/integrations/monday/webhook` : "")}
                    onChange={(e) => setSettings((s) => ({ ...s, mondayWebhookUrl: e.target.value }))}
                    placeholder="https://your-app.com/api/integrations/monday/webhook"
                  />
                </div>

                <div className="flex flex-wrap items-center gap-3">
                  <Button
                    variant="outline"
                    size="sm"
                    className="rounded-xl"
                    onClick={fetchMondayColumns}
                    disabled={fetchingColumns || !settings.mondayApiToken || !settings.mondayBoardId}
                  >
                    {fetchingColumns ? <Loader2 className="mr-2 size-3 animate-spin" /> : <LayoutGrid className="mr-2 size-3" />}
                    Fetch Columns
                  </Button>
                  <Button
                    variant={settings.mondayWebhookId ? "destructive" : "outline"}
                    size="sm"
                    className="rounded-xl"
                    onClick={toggleMondaySubscription}
                    disabled={subscribing || !settings.mondayApiToken || !settings.mondayBoardId}
                  >
                    {subscribing && <Loader2 className="mr-2 size-3 animate-spin" />}
                    {settings.mondayWebhookId ? "Unsubscribe" : "Subscribe to Changes"}
                  </Button>
                  {settings.mondayWebhookId && (
                    <Badge className="bg-emerald-500/10 text-emerald-700 dark:text-emerald-300">Subscribed</Badge>
                  )}
                </div>

                {mondayColumns.length > 0 && (
                  <div className="rounded-xl border border-border/50 bg-muted/20 p-3 space-y-2">
                    <p className="text-xs font-medium text-muted-foreground mb-2">Column Mapping</p>
                    <div className="grid gap-2 sm:grid-cols-2 max-h-[28rem] overflow-y-auto pr-1">
                      {MONDAY_MAPPABLE_FIELDS.map(({ field, label }) => (
                        <div key={field} className="flex items-center gap-2">
                          <span className="text-xs text-muted-foreground w-36 shrink-0">{label}</span>
                          <Select
                            value={String((settings.mondayColumnMap || {})[field] || "__none__")}
                            onValueChange={(v) => setColumnMapping(field, !v || v === "__none__" ? "" : v)}
                          >
                            <SelectTrigger className="h-8 text-xs">
                              <SelectValue placeholder="—" />
                            </SelectTrigger>
                            <SelectContent>
                              <SelectItem value="__none__">—</SelectItem>
                              {mondayColumns.map((col) => (
                                <SelectItem key={col.id} value={col.id}>{col.title} ({col.type})</SelectItem>
                              ))}
                            </SelectContent>
                          </Select>
                        </div>
                      ))}
                      <div className="flex items-center gap-2">
                        <span className="text-xs text-muted-foreground w-36 shrink-0">Files (images)</span>
                        <Select
                          value={String((settings.mondayColumnMap || {})._files || "__none__")}
                          onValueChange={(v) => setColumnMapping("_files", !v || v === "__none__" ? "" : v)}
                        >
                          <SelectTrigger className="h-8 text-xs">
                            <SelectValue placeholder="—" />
                          </SelectTrigger>
                          <SelectContent>
                            <SelectItem value="__none__">—</SelectItem>
                            {mondayColumns.filter((c) => c.type === "file").map((col) => (
                              <SelectItem key={col.id} value={col.id}>{col.title}</SelectItem>
                            ))}
                          </SelectContent>
                        </Select>
                      </div>
                    </div>
                  </div>
                )}

                <div className="flex flex-wrap items-center gap-3">
                  <div className="flex items-center gap-3">
                    <Label className="text-xs font-medium text-muted-foreground">Enable Integration</Label>
                    <Switch
                      checked={settings.mondayEnabled}
                      onCheckedChange={(val: boolean) => setSettings((s) => ({ ...s, mondayEnabled: val }))}
                    />
                  </div>
                  <Button
                    variant="outline"
                    size="sm"
                    className="rounded-xl"
                    onClick={pushAllToMonday}
                    disabled={pushingAll || !settings.mondayEnabled || !settings.mondayApiToken || !settings.mondayBoardId}
                  >
                    {pushingAll ? <Loader2 className="mr-2 size-3 animate-spin" /> : <LayoutGrid className="mr-2 size-3" />}
                    Push All to Monday.com
                  </Button>
                </div>
              </CardContent>
            </Card>

            <Card variant="glass">
              <CardHeader>
                <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
                  <div>
                    <CardTitle className="flex items-center gap-2 text-base">
                      <Globe className="size-4 text-primary" />
                      Webhook Integration
                    </CardTitle>
                    <CardDescription>POST card data to any external URL on events</CardDescription>
                  </div>
                  {settings.webhookEnabled && (
                    <Badge className="bg-emerald-500/10 text-emerald-700 dark:text-emerald-300">
                      <Check className="mr-1 size-3" /> Enabled
                    </Badge>
                  )}
                </div>
              </CardHeader>
              <CardContent className="space-y-4">
                <div>
                  <Label className="mb-1.5 block text-xs font-medium text-muted-foreground">Webhook URL</Label>
                  <Input
                    value={settings.webhookUrl}
                    onChange={(e) => setSettings((s) => ({ ...s, webhookUrl: e.target.value }))}
                    placeholder="https://example.com/webhook"
                  />
                </div>
                <div>
                  <Label className="mb-1.5 block text-xs font-medium text-muted-foreground">Secret (optional, for HMAC signing)</Label>
                  <Input
                    type="password"
                    value={settings.webhookSecret}
                    onChange={(e) => setSettings((s) => ({ ...s, webhookSecret: e.target.value }))}
                    placeholder="••••••••"
                  />
                </div>
                <div>
                  <Label className="mb-2 block text-xs font-medium text-muted-foreground">Events</Label>
                  <div className="grid gap-2 sm:grid-cols-2">
                    {[
                      { value: "ocr_complete", label: "OCR Complete" },
                      { value: "card_reviewed", label: "Card Reviewed" },
                      { value: "card_exported", label: "Card Exported" },
                      { value: "card_deleted", label: "Card Deleted" },
                    ].map((evt) => (
                      <label key={evt.value} className="flex items-center gap-2 text-sm cursor-pointer">
                        <Checkbox
                          checked={(settings.webhookEvents ?? []).includes(evt.value)}
                          onCheckedChange={() => toggleWebhookEvent(evt.value)}
                        />
                        {evt.label}
                      </label>
                    ))}
                  </div>
                </div>
                <div className="flex items-center gap-3">
                  <Label className="text-xs font-medium text-muted-foreground">Enable Webhook</Label>
                  <Switch
                    checked={settings.webhookEnabled}
                    onCheckedChange={(val: boolean) => setSettings((s) => ({ ...s, webhookEnabled: val }))}
                  />
                </div>
                <Button
                  variant="outline"
                  size="sm"
                  className="rounded-xl"
                  onClick={testWebhook}
                  disabled={webhookTestStatus === "testing" || !settings.webhookUrl}
                >
                  {webhookTestStatus === "testing" ? (
                    <Loader2 className="mr-2 size-3 animate-spin" />
                  ) : (
                    <Wifi className="mr-2 size-3" />
                  )}
                  Send Test
                </Button>
              </CardContent>
            </Card>
          </div>
        </TabsContent>

        <TabsContent value="preferences">
          <div className="grid gap-4 sm:gap-6 grid-cols-1 lg:grid-cols-2">
            <Card variant="glass" className="lg:col-span-2">
              <CardHeader>
                <CardTitle className="flex items-center gap-2 text-base">
                  <Sun className="size-4 text-primary dark:hidden" />
                  <Moon className="hidden size-4 text-primary dark:block" />
                  Appearance
                </CardTitle>
                <CardDescription>Choose how Echo OCR looks to you</CardDescription>
              </CardHeader>
              <CardContent>
                <div className="grid gap-3 sm:grid-cols-3">
                  {themeOptions.map((opt) => {
                    const Icon = opt.icon;
                    const active = theme === opt.value;
                    return (
                      <button
                        key={opt.value}
                        onClick={() => setTheme(opt.value)}
                        className={`group relative flex flex-col items-center gap-2 rounded-xl border p-4 text-center transition-all ${
                          active
                            ? "border-primary/40 bg-primary/5 ring-2 ring-primary/20"
                            : "border-border/50 bg-muted/20 hover:border-border hover:bg-muted/40"
                        }`}
                      >
                        <div
                          className={`flex size-10 items-center justify-center rounded-lg transition-colors ${
                            active
                              ? "bg-primary/10 text-primary"
                              : "bg-muted/50 text-muted-foreground group-hover:text-foreground"
                          }`}
                        >
                          <Icon className="size-5" />
                        </div>
                        <div>
                          <p className={`text-sm font-medium ${active ? "text-primary" : "text-foreground"}`}>
                            {opt.label}
                          </p>
                          <p className="mt-0.5 text-xs text-muted-foreground">
                            {opt.description}
                          </p>
                        </div>
                      </button>
                    );
                  })}
                </div>
              </CardContent>
            </Card>

            <Card variant="glass" className="lg:col-span-2">
              <CardHeader>
                <CardTitle className="flex items-center gap-2 text-base">
                  <Bell className="size-4 text-primary" />
                  Notifications
                </CardTitle>
                <CardDescription>Control which events generate toast notifications</CardDescription>
              </CardHeader>
              <CardContent>
                <div className="divide-y divide-border/50">
                  {([
                    { key: "processingComplete" as const, title: "Processing complete", desc: "When a PDF finishes OCR processing" },
                    { key: "processingErrors" as const, title: "Processing errors", desc: "When a job fails or encounters an error" },
                    { key: "folderWatchAlerts" as const, title: "Folder watch alerts", desc: "When the folder watcher starts, stops, or finds new files" },
                    { key: "cleanupReminders" as const, title: "Cleanup reminders", desc: "Periodic reminders when files are eligible for cleanup" },
                  ]).map((item) => (
                    <div
                      key={item.key}
                      className="flex items-center justify-between gap-4 py-3 first:pt-0 last:pb-0"
                    >
                      <div className="min-w-0">
                        <p className="text-sm font-medium">{item.title}</p>
                        <p className="text-xs text-muted-foreground">{item.desc}</p>
                      </div>
                      <Switch
                        checked={notifPrefs[item.key]}
                        onCheckedChange={(val: boolean) => updateNotifPref(item.key, val)}
                      />
                    </div>
                  ))}
                </div>
              </CardContent>
            </Card>
          </div>
        </TabsContent>
      </Tabs>
    </div>
  );
}
