"use client";

import { useCallback, useEffect, useState } from "react";
import Link from "next/link";
import { ArrowLeft, CheckCircle2, Copy, Edit, Link2, Mail, ShieldCheck, Wrench, XCircle } from "lucide-react";

import DetailSection from "@/components/common/DetailSection";
import { useToast } from "@/components/common/ToastProvider";
import RepairFormDialog from "@/components/repairs/RepairFormDialog";
import { RepairPriorityBadge, RepairStatusBadge, statusLabels } from "@/components/repairs/RepairStatusBadge";
import RepairStatusDialog from "@/components/repairs/RepairStatusDialog";
import { Button, buttonVariants } from "@/components/ui/button";
import { api } from "@/lib/api";
import { hasPermission } from "@/lib/permissions";
import type { CurrentUser } from "@/types/rbac";
import type {
  Repair,
  RepairNotificationOverview,
  RepairPayload,
  RepairPublicLink,
  RepairPublicLinkCreated,
  RepairStatus,
  RepairStatusHistory,
} from "@/types/repair";

type Params = {
  params: Promise<{
    id: string;
  }>;
};

function getErrorMessage(error: unknown) {
  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 ?? "Aktion konnte nicht abgeschlossen werden";
  }
  return "Aktion konnte nicht abgeschlossen werden";
}

function formatDate(value?: string | null) {
  if (!value) return "-";
  return new Intl.DateTimeFormat("de-DE", { dateStyle: "short", timeStyle: "short" }).format(new Date(value));
}

function DetailItem({ label, value }: { label: string; value?: string | number | boolean | null }) {
  return (
    <div>
      <dt className="text-xs font-medium uppercase tracking-wide text-slate-500">{label}</dt>
      <dd className="mt-1 whitespace-pre-wrap text-sm text-slate-950">{typeof value === "boolean" ? (value ? "Ja" : "Nein") : value || "-"}</dd>
    </div>
  );
}

function historyLabel(item: RepairStatusHistory) {
  const oldStatus = item.old_status ? statusLabels[item.old_status as RepairStatus] ?? item.old_status : "Start";
  return `${oldStatus} → ${statusLabels[item.new_status]}`;
}

export default function RepairDetailPage({ params }: Params) {
  const { showToast } = useToast();
  const [repairId, setRepairId] = useState("");
  const [repair, setRepair] = useState<Repair | null>(null);
  const [history, setHistory] = useState<RepairStatusHistory[]>([]);
  const [publicLink, setPublicLink] = useState<RepairPublicLink | null>(null);
  const [lastCreatedStatusPath, setLastCreatedStatusPath] = useState("");
  const [notifications, setNotifications] = useState<RepairNotificationOverview | null>(null);
  const [currentUser, setCurrentUser] = useState<CurrentUser | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState("");
  const [pending, setPending] = useState(false);
  const [formOpen, setFormOpen] = useState(false);
  const [statusOpen, setStatusOpen] = useState(false);
  const [formError, setFormError] = useState("");
  const [statusError, setStatusError] = useState("");
  const [communicationPending, setCommunicationPending] = useState(false);

  useEffect(() => {
    params.then((resolved) => setRepairId(resolved.id));
  }, [params]);

  const loadRepair = useCallback(async () => {
    if (!repairId) return;
    setLoading(true);
    setError("");
    try {
      const [repairResponse, historyResponse, meResponse] = await Promise.all([
        api.get<Repair>(`/repairs/${repairId}`),
        api.get<RepairStatusHistory[]>(`/repairs/${repairId}/history`),
        api.get<CurrentUser>("/me"),
      ]);
      setRepair(repairResponse.data);
      setHistory(historyResponse.data);
      setCurrentUser(meResponse.data);
      const notificationResponse = await api.get<RepairNotificationOverview>(`/repairs/${repairId}/notifications`);
      setNotifications(notificationResponse.data);
      if (hasPermission(meResponse.data, "repairs.public_link.manage")) {
        const publicLinkResponse = await api.get<RepairPublicLink>(`/repairs/${repairId}/public-link`);
        setPublicLink(publicLinkResponse.data);
      } else {
        setPublicLink(null);
      }
      setLastCreatedStatusPath("");
    } catch (err) {
      setError(getErrorMessage(err));
    } finally {
      setLoading(false);
    }
  }, [repairId]);

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

  async function saveRepair(payload: RepairPayload) {
    if (!repair) return;
    setPending(true);
    setFormError("");
    try {
      const response = await api.put<Repair>(`/repairs/${repair.id}`, payload);
      setRepair(response.data);
      setFormOpen(false);
      showToast({ type: "success", title: "Reparatur aktualisiert", description: response.data.repair_number });
    } catch (err) {
      const message = getErrorMessage(err);
      setFormError(message);
      showToast({ type: "error", title: "Reparatur konnte nicht gespeichert werden", description: message });
    } finally {
      setPending(false);
    }
  }

  async function saveStatus(status: RepairStatus, note: string) {
    if (!repair) return;
    setPending(true);
    setStatusError("");
    try {
      const response = await api.put<Repair>(`/repairs/${repair.id}/status`, { status, note });
      const historyResponse = await api.get<RepairStatusHistory[]>(`/repairs/${repair.id}/history`);
      const notificationResponse = await api.get<RepairNotificationOverview>(`/repairs/${repair.id}/notifications`);
      setRepair(response.data);
      setHistory(historyResponse.data);
      setNotifications(notificationResponse.data);
      setStatusOpen(false);
      showToast({ type: "success", title: "Status aktualisiert", description: response.data.repair_number });
    } catch (err) {
      const message = getErrorMessage(err);
      setStatusError(message);
      showToast({ type: "error", title: "Status konnte nicht gespeichert werden", description: message });
    } finally {
      setPending(false);
    }
  }

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

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

  const canUpdate = hasPermission(currentUser, "repairs.update");
  const canUpdateStatus = hasPermission(currentUser, "repairs.status.update");
  const canManagePublicLink = hasPermission(currentUser, "repairs.public_link.manage");

  async function createPublicLink() {
    if (!repair || !canManagePublicLink) return;
    setCommunicationPending(true);
    try {
      const response = await api.post<RepairPublicLinkCreated>(`/repairs/${repair.id}/public-link`);
      setPublicLink(response.data);
      setLastCreatedStatusPath(response.data.public_status_path);
      showToast({ type: "success", title: "Statuslink erstellt", description: "Der Klartextlink wird nur jetzt angezeigt." });
    } catch (err) {
      const message = getErrorMessage(err);
      showToast({ type: "error", title: "Statuslink konnte nicht erstellt werden", description: message });
    } finally {
      setCommunicationPending(false);
    }
  }

  async function revokePublicLink() {
    if (!repair || !canManagePublicLink) return;
    setCommunicationPending(true);
    try {
      const response = await api.delete<RepairPublicLink>(`/repairs/${repair.id}/public-link`);
      setPublicLink(response.data);
      setLastCreatedStatusPath("");
      showToast({ type: "success", title: "Statuslink deaktiviert", description: repair.repair_number });
    } catch (err) {
      const message = getErrorMessage(err);
      showToast({ type: "error", title: "Statuslink konnte nicht deaktiviert werden", description: message });
    } finally {
      setCommunicationPending(false);
    }
  }

  async function copyPublicLink() {
    if (!lastCreatedStatusPath) {
      showToast({ type: "error", title: "Kein Klartextlink verfügbar", description: "Der sichere Link wird nur direkt nach der Erstellung angezeigt." });
      return;
    }
    const absolutePath = new URL(lastCreatedStatusPath, window.location.origin).toString();
    try {
      await navigator.clipboard.writeText(absolutePath);
      showToast({ type: "success", title: "Link kopiert", description: lastCreatedStatusPath });
    } catch {
      showToast({ type: "error", title: "Link konnte nicht kopiert werden", description: "Bitte kopiere den angezeigten Link manuell." });
    }
  }

  return (
    <div className="space-y-6">
      <div className="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
        <div>
          <Link href="/repairs" className="mb-3 inline-flex items-center gap-2 text-sm text-slate-500 hover:text-slate-950"><ArrowLeft size={16} />Zurück</Link>
          <div className="flex flex-wrap items-center gap-3">
            <h1 className="text-3xl font-bold text-slate-950">{repair.repair_number}</h1>
            <RepairStatusBadge status={repair.status} />
            <RepairPriorityBadge priority={repair.priority} />
          </div>
          <p className="mt-1 text-sm text-slate-500">{repair.customer_name} · {repair.device_manufacturer} {repair.device_model}</p>
        </div>
        <div className="flex flex-wrap gap-2">
          {canUpdate && <Button type="button" variant="outline" onClick={() => setFormOpen(true)}><Edit size={16} />Bearbeiten</Button>}
          {canUpdateStatus && <Button type="button" onClick={() => setStatusOpen(true)}><Wrench size={16} />Status ändern</Button>}
        </div>
      </div>

      <div className="grid gap-4 xl:grid-cols-2">
        <DetailSection title="Kundendaten">
          <dl className="grid gap-4 md:grid-cols-2">
            <DetailItem label="Name" value={repair.customer_name} />
            <DetailItem label="E-Mail" value={repair.customer_email} />
            <DetailItem label="Telefon" value={repair.customer_phone} />
            <DetailItem label="Kunden-ID" value={repair.customer_id} />
          </dl>
        </DetailSection>

        <DetailSection title="Gerätedaten">
          <dl className="grid gap-4 md:grid-cols-2">
            <DetailItem label="Hersteller" value={repair.device_manufacturer} />
            <DetailItem label="Modell" value={repair.device_model} />
            <DetailItem label="Seriennummer" value={repair.device_serial_number} />
            <DetailItem label="Gerätetyp" value={repair.device_type} />
            <DetailItem label="Gerät geöffnet" value={repair.device_opened} />
          </dl>
        </DetailSection>
      </div>

      <DetailSection title="Fehler und Annahme">
        <dl className="grid gap-4">
          <DetailItem label="Fehlerbeschreibung" value={repair.fault_description} />
          <DetailItem label="Zubehör" value={repair.accessories} />
          <DetailItem label="Vorarbeiten" value={repair.previous_work} />
          <DetailItem label="Annahmenotizen" value={repair.intake_notes} />
        </dl>
      </DetailSection>

      <DetailSection title="Werkstatt">
        <dl className="grid gap-4 md:grid-cols-2">
          <DetailItem label="Diagnose" value={repair.diagnosis_notes} />
          <DetailItem label="Reparaturnotizen" value={repair.repair_notes} />
          <DetailItem label="Kostenschätzung" value={repair.estimate_notes} />
          <DetailItem label="Geschätzte Kosten" value={repair.estimated_cost_cents !== null ? `${(repair.estimated_cost_cents / 100).toFixed(2)} €` : ""} />
        </dl>
      </DetailSection>

      <DetailSection title="Metadaten">
        <dl className="grid gap-4 md:grid-cols-3">
          <DetailItem label="Quelle" value={repair.source} />
          <DetailItem label="Quellreferenz" value={repair.source_reference} />
          <DetailItem label="Erstellt" value={formatDate(repair.created_at)} />
          <DetailItem label="Aktualisiert" value={formatDate(repair.updated_at)} />
          <DetailItem label="Freigegeben" value={formatDate(repair.approved_at)} />
          <DetailItem label="Abgeschlossen" value={formatDate(repair.completed_at)} />
        </dl>
      </DetailSection>

      <DetailSection title="Statushistorie">
        {history.length === 0 ? (
          <p className="text-sm text-slate-500">Noch keine Statushistorie vorhanden.</p>
        ) : (
          <div className="space-y-0">
            {history.map((item) => (
              <div key={item.id} className="relative border-l border-slate-200 pb-5 pl-6 last:pb-0">
                <span className={`absolute -left-2 top-1 h-4 w-4 rounded-full ring-4 ring-white ${item.new_status === repair.status ? "bg-blue-600" : "bg-slate-300"}`} />
                <div className="flex flex-col gap-2 rounded-lg border bg-slate-50 p-4 sm:flex-row sm:items-start sm:justify-between">
                  <div className="space-y-2">
                    <div className="flex flex-wrap items-center gap-2">
                      <p className="font-medium text-slate-950">{historyLabel(item)}</p>
                      {item.new_status === repair.status && <span className="rounded-full bg-blue-50 px-2 py-1 text-xs font-medium text-blue-700 ring-1 ring-blue-600/20">Aktuell</span>}
                    </div>
                    <p className="text-xs text-slate-500">
                      {item.actor_display_name || item.actor_username || "System"}
                    </p>
                    {item.note && <p className="whitespace-pre-wrap text-sm text-slate-600">{item.note}</p>}
                  </div>
                  <time className="text-xs text-slate-500" dateTime={item.created_at}>{formatDate(item.created_at)}</time>
                </div>
              </div>
            ))}
          </div>
        )}
      </DetailSection>

      <DetailSection title="Kundenkommunikation">
        <div className="grid gap-4 xl:grid-cols-[1fr_1.3fr]">
          <div className="space-y-4 rounded-lg border bg-slate-50 p-4">
            <div className="flex items-start gap-3">
              {publicLink?.is_active ? <CheckCircle2 className="mt-0.5 text-emerald-600" size={20} /> : <XCircle className="mt-0.5 text-slate-400" size={20} />}
              <div>
                <p className="font-medium text-slate-950">Öffentlicher Statuslink {publicLink?.is_active ? "aktiv" : "inaktiv"}</p>
                <p className="mt-1 text-sm text-slate-500">
                  Kunden erhalten später Statusupdates per E-Mail mit sicherem Link. Ein Kundenlogin ist dafür nicht erforderlich.
                </p>
              </div>
            </div>
            <dl className="grid gap-3 text-sm">
              <DetailItem label="Token-Hinweis" value={publicLink?.token_hint ? `...${publicLink.token_hint}` : "-"} />
              <DetailItem label="Zuletzt verwendet" value={formatDate(publicLink?.last_used_at)} />
              <DetailItem label="Erstellt" value={formatDate(publicLink?.created_at)} />
            </dl>
            {lastCreatedStatusPath && (
              <div className="rounded-lg border border-amber-200 bg-amber-50 p-3 text-sm text-amber-900">
                <p className="font-medium">Einmaliger Klartextlink</p>
                <p className="mt-1 break-all">{lastCreatedStatusPath}</p>
              </div>
            )}
            {canManagePublicLink ? (
              <div className="flex flex-wrap gap-2">
                <Button type="button" onClick={createPublicLink} disabled={communicationPending}><Link2 size={16} />Statuslink erstellen</Button>
                <Button type="button" variant="outline" onClick={copyPublicLink} disabled={!lastCreatedStatusPath || communicationPending}><Copy size={16} />Link kopieren</Button>
                <Button type="button" variant="destructive" onClick={revokePublicLink} disabled={!publicLink?.is_active || communicationPending}>Statuslink deaktivieren</Button>
              </div>
            ) : (
              <p className="text-sm text-slate-500">Für die Verwaltung des Statuslinks ist `repairs.public_link.manage` erforderlich.</p>
            )}
          </div>

          <div className="space-y-3">
            <div className="flex items-center gap-2 text-sm font-medium text-slate-950">
              <Mail size={16} />
              Vorbereitete Benachrichtigungen
            </div>
            <div className="grid gap-2">
              {notifications?.templates.map((template) => (
                <div key={template.event_type} className="rounded-lg border bg-white p-3">
                  <div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
                    <p className="font-medium text-slate-950">{template.subject}</p>
                    {template.status && <RepairStatusBadge status={template.status} />}
                  </div>
                  <p className="mt-2 line-clamp-2 text-sm text-slate-500">{template.text}</p>
                </div>
              ))}
              {!notifications?.templates.length && <p className="text-sm text-slate-500">Noch keine Vorlagen vorbereitet.</p>}
            </div>
            <div className="rounded-lg border bg-slate-50 p-3 text-sm text-slate-500">
              <div className="flex items-start gap-2">
                <ShieldCheck className="mt-0.5 text-slate-500" size={16} />
                <p>Notification Events werden gespeichert, sobald später echter E-Mail-Versand angebunden wird. Interne Notizen werden nicht öffentlich ausgegeben.</p>
              </div>
            </div>
          </div>
        </div>
      </DetailSection>

      <DetailSection title="Audit und Aktivität vorbereitet">
        <p className="text-sm text-slate-500">Reparaturaktionen werden in den Audit Logs erfasst und erscheinen im Activity Feed, wenn `repairs.read` vorhanden ist.</p>
        <Link href="/audit-logs" className={buttonVariants({ variant: "outline", size: "sm", className: "mt-4" })}>Audit Logs öffnen</Link>
      </DetailSection>

      <RepairFormDialog key={`form-${repair.id}-${formOpen}`} open={formOpen} repair={repair} pending={pending} serverError={formError} onOpenChange={setFormOpen} onSubmit={saveRepair} />
      <RepairStatusDialog key={`status-${repair.id}-${statusOpen}`} open={statusOpen} repair={repair} pending={pending} serverError={statusError} onOpenChange={setStatusOpen} onSubmit={saveStatus} />
    </div>
  );
}
