"use client";

import { useCallback, useEffect, useState } from "react";
import type { ReactNode } from "react";
import { ExternalLink, MailCheck, Save, Send, ShieldCheck } from "lucide-react";

import { useToast } from "@/components/common/ToastProvider";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { api } from "@/lib/api";
import type {
  PublicLinksSettings,
  SettingsSource,
  SmtpSettings,
  SmtpSettingsPayload,
  SmtpTestResponse,
} from "@/types/system-settings";

type SettingsTab = "smtp" | "public-links";

const sourceLabels: Record<SettingsSource, string> = {
  database: "Admin-Konfiguration",
  environment: "Umgebung",
  missing: "Nicht konfiguriert",
};

function getErrorMessage(error: unknown, fallback: string) {
  if (typeof error === "object" && error !== null && "response" in error) {
    const response = (error as { response?: { data?: { detail?: string; message?: string } } }).response;
    return response?.data?.detail ?? response?.data?.message ?? fallback;
  }
  return fallback;
}

function emptySmtpSettings(): SmtpSettings {
  return {
    host: "",
    port: 587,
    username: "",
    password_is_set: false,
    from_email: "",
    from_name: "Funktechnik Schubert",
    use_tls: true,
    enabled: false,
    source: "missing",
  };
}

export default function SettingsPage() {
  const { showToast } = useToast();
  const [activeTab, setActiveTab] = useState<SettingsTab>("smtp");
  const [smtp, setSmtp] = useState<SmtpSettings>(emptySmtpSettings());
  const [newPassword, setNewPassword] = useState("");
  const [testRecipient, setTestRecipient] = useState("");
  const [publicLinks, setPublicLinks] = useState<PublicLinksSettings>({
    repair_status_base_url: "",
    source: "missing",
  });
  const [loading, setLoading] = useState(true);
  const [savingSmtp, setSavingSmtp] = useState(false);
  const [sendingTest, setSendingTest] = useState(false);
  const [savingPublicLinks, setSavingPublicLinks] = useState(false);
  const [error, setError] = useState("");

  const loadSettings = useCallback(async () => {
    setError("");
    setLoading(true);
    try {
      const [smtpResponse, publicLinksResponse] = await Promise.all([
        api.get<SmtpSettings>("/system-settings/smtp"),
        api.get<PublicLinksSettings>("/system-settings/public-links"),
      ]);
      setSmtp(smtpResponse.data);
      setPublicLinks(publicLinksResponse.data);
    } catch (err) {
      setError(getErrorMessage(err, "Einstellungen konnten nicht geladen werden."));
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    queueMicrotask(() => {
      void loadSettings();
    });
  }, [loadSettings]);

  async function saveSmtp() {
    setSavingSmtp(true);
    try {
      const payload: SmtpSettingsPayload = {
        host: smtp.host,
        port: smtp.port,
        username: smtp.username,
        from_email: smtp.from_email,
        from_name: smtp.from_name,
        use_tls: smtp.use_tls,
        enabled: smtp.enabled,
      };

      if (newPassword) {
        payload.password = newPassword;
      }

      const response = await api.put<SmtpSettings>("/system-settings/smtp", payload);
      setSmtp(response.data);
      setNewPassword("");
      showToast({ type: "success", title: "SMTP-Konfiguration gespeichert" });
    } catch (err) {
      showToast({
        type: "error",
        title: "SMTP konnte nicht gespeichert werden",
        description: getErrorMessage(err, "Bitte prüfe die Eingaben."),
      });
    } finally {
      setSavingSmtp(false);
    }
  }

  async function sendTestMail() {
    setSendingTest(true);
    try {
      const response = await api.post<SmtpTestResponse>("/system-settings/smtp/test", {
        recipient: testRecipient,
      });
      showToast({
        type: response.data.success ? "success" : "error",
        title: response.data.success ? "Testmail versendet" : "Testmail fehlgeschlagen",
        description: response.data.message,
      });
    } catch (err) {
      showToast({
        type: "error",
        title: "Testmail fehlgeschlagen",
        description: getErrorMessage(err, "Die Testmail konnte nicht versendet werden."),
      });
    } finally {
      setSendingTest(false);
    }
  }

  async function savePublicLinks() {
    setSavingPublicLinks(true);
    try {
      const response = await api.put<PublicLinksSettings>("/system-settings/public-links", {
        repair_status_base_url: publicLinks.repair_status_base_url,
      });
      setPublicLinks(response.data);
      showToast({ type: "success", title: "Öffentliche Links gespeichert" });
    } catch (err) {
      showToast({
        type: "error",
        title: "Öffentliche Links konnten nicht gespeichert werden",
        description: getErrorMessage(err, "Bitte prüfe die Basis-URL."),
      });
    } finally {
      setSavingPublicLinks(false);
    }
  }

  if (loading) {
    return <div className="rounded-lg border bg-white p-8 text-slate-500">Einstellungen werden geladen...</div>;
  }

  if (error) {
    return <div className="rounded-lg border bg-white p-8 text-red-600">{error}</div>;
  }

  return (
    <div className="space-y-6">
      <div className="flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between">
        <div>
          <h1 className="text-3xl font-bold text-slate-950">Einstellungen</h1>
          <p className="mt-1 text-sm text-slate-500">SMTP-Versand und öffentliche Statuslinks verwalten</p>
        </div>
        <div className="inline-flex w-fit rounded-lg border bg-white p-1">
          <TabButton active={activeTab === "smtp"} onClick={() => setActiveTab("smtp")}>
            SMTP
          </TabButton>
          <TabButton active={activeTab === "public-links"} onClick={() => setActiveTab("public-links")}>
            Öffentliche Links
          </TabButton>
        </div>
      </div>

      {activeTab === "smtp" ? (
        <section className="rounded-lg border bg-white p-6">
          <div className="mb-6 flex flex-col gap-3 border-b pb-5 lg:flex-row lg:items-start lg:justify-between">
            <div>
              <div className="flex items-center gap-2">
                <MailCheck className="h-5 w-5 text-slate-500" />
                <h2 className="text-lg font-semibold text-slate-950">SMTP</h2>
              </div>
              <p className="mt-1 text-sm text-slate-500">
                Quelle: {sourceLabels[smtp.source]}
                {smtp.password_is_set ? " · Passwort ist gesetzt" : ""}
              </p>
            </div>
            <Button type="button" onClick={() => void saveSmtp()} disabled={savingSmtp}>
              <Save />
              {savingSmtp ? "Speichert..." : "Speichern"}
            </Button>
          </div>

          <div className="grid gap-5 lg:grid-cols-2">
            <label className="flex items-center gap-3 rounded-lg border p-4 text-sm font-medium text-slate-800">
              <input
                type="checkbox"
                className="h-4 w-4 rounded border-slate-300"
                checked={smtp.enabled}
                onChange={(event) => setSmtp((current) => ({ ...current, enabled: event.target.checked }))}
              />
              SMTP über Admin-Konfiguration aktivieren
            </label>

            <label className="flex items-center gap-3 rounded-lg border p-4 text-sm font-medium text-slate-800">
              <input
                type="checkbox"
                className="h-4 w-4 rounded border-slate-300"
                checked={smtp.use_tls}
                onChange={(event) => setSmtp((current) => ({ ...current, use_tls: event.target.checked }))}
              />
              TLS / STARTTLS aktiv
            </label>

            <Field label="SMTP Host">
              <Input value={smtp.host} onChange={(event) => setSmtp((current) => ({ ...current, host: event.target.value }))} />
            </Field>

            <Field label="Port">
              <Input
                type="number"
                min={1}
                max={65535}
                value={smtp.port}
                onChange={(event) => setSmtp((current) => ({ ...current, port: Number(event.target.value) || 587 }))}
              />
            </Field>

            <Field label="Benutzername">
              <Input value={smtp.username} onChange={(event) => setSmtp((current) => ({ ...current, username: event.target.value }))} />
            </Field>

            <Field label={smtp.password_is_set ? "Neues Passwort setzen" : "Passwort"}>
              <Input
                type="password"
                value={newPassword}
                placeholder={smtp.password_is_set ? "Leer lassen, um aktuelles Passwort zu behalten" : ""}
                onChange={(event) => setNewPassword(event.target.value)}
              />
            </Field>

            <Field label="Absenderadresse">
              <Input
                type="email"
                value={smtp.from_email}
                onChange={(event) => setSmtp((current) => ({ ...current, from_email: event.target.value }))}
              />
            </Field>

            <Field label="Absendername">
              <Input value={smtp.from_name} onChange={(event) => setSmtp((current) => ({ ...current, from_name: event.target.value }))} />
            </Field>
          </div>

          <div className="mt-6 rounded-lg border border-blue-100 bg-blue-50 p-4 text-sm text-blue-950">
            Für Apple Mail/iCloud: smtp.mail.me.com, Port 587, TLS/STARTTLS aktiv,
            Benutzername vollständige Mailadresse, Passwort = app-spezifisches Passwort.
          </div>

          <div className="mt-6 rounded-lg border bg-slate-50 p-4">
            <div className="flex items-center gap-2">
              <Send className="h-5 w-5 text-slate-500" />
              <h3 className="font-semibold text-slate-950">Testmail senden</h3>
            </div>
            <div className="mt-4 flex flex-col gap-3 sm:flex-row">
              <Input
                type="email"
                placeholder="empfaenger@example.com"
                value={testRecipient}
                onChange={(event) => setTestRecipient(event.target.value)}
              />
              <Button type="button" onClick={() => void sendTestMail()} disabled={sendingTest || !testRecipient}>
                <Send />
                {sendingTest ? "Sendet..." : "Testmail"}
              </Button>
            </div>
          </div>
        </section>
      ) : (
        <section className="rounded-lg border bg-white p-6">
          <div className="mb-6 flex flex-col gap-3 border-b pb-5 lg:flex-row lg:items-start lg:justify-between">
            <div>
              <div className="flex items-center gap-2">
                <ExternalLink className="h-5 w-5 text-slate-500" />
                <h2 className="text-lg font-semibold text-slate-950">Öffentliche Links</h2>
              </div>
              <p className="mt-1 text-sm text-slate-500">Quelle: {sourceLabels[publicLinks.source]}</p>
            </div>
            <Button type="button" onClick={() => void savePublicLinks()} disabled={savingPublicLinks}>
              <Save />
              {savingPublicLinks ? "Speichert..." : "Speichern"}
            </Button>
          </div>

          <Field label="Reparaturstatus Basis-URL">
            <Input
              placeholder="https://test.funktechnik-schubert.de/status"
              value={publicLinks.repair_status_base_url}
              onChange={(event) => setPublicLinks((current) => ({ ...current, repair_status_base_url: event.target.value }))}
            />
          </Field>

          <div className="mt-5 flex items-start gap-3 rounded-lg border border-emerald-100 bg-emerald-50 p-4 text-sm text-emerald-950">
            <ShieldCheck className="mt-0.5 h-5 w-5 shrink-0" />
            <p>
              Statusmails erzeugen weiterhin sichere Einmal-Token in Hermes. Die Basis-URL bestimmt nur,
              auf welche öffentliche Website-Route der Link zeigt.
            </p>
          </div>
        </section>
      )}
    </div>
  );
}

function TabButton({
  active,
  onClick,
  children,
}: {
  active: boolean;
  onClick: () => void;
  children: ReactNode;
}) {
  return (
    <button
      type="button"
      className={`rounded-md px-3 py-2 text-sm font-medium transition-colors ${
        active ? "bg-slate-900 text-white" : "text-slate-600 hover:bg-slate-100 hover:text-slate-950"
      }`}
      onClick={onClick}
    >
      {children}
    </button>
  );
}

function Field({ label, children }: { label: string; children: ReactNode }) {
  return (
    <label className="block">
      <span className="mb-1.5 block text-sm font-medium text-slate-700">{label}</span>
      {children}
    </label>
  );
}
