"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import Link from "next/link";
import { Download, Edit, Eye, Plus, Trash2 } from "lucide-react";

import ConfirmDialog from "@/components/common/ConfirmDialog";
import DataTable, { type DataTableColumn } from "@/components/common/DataTable";
import EmptyState from "@/components/common/EmptyState";
import SearchInput from "@/components/common/SearchInput";
import { useToast } from "@/components/common/ToastProvider";
import DocumentTypeBadge from "@/components/knowledge/DocumentTypeBadge";
import { DeviceFormDialog, DocumentUploadDialog, ManufacturerFormDialog } from "@/components/knowledge/KnowledgeForms";
import TagList from "@/components/knowledge/TagList";
import { Button, buttonVariants } from "@/components/ui/button";
import { api } from "@/lib/api";
import type { DevicePayload, DocumentPayload, DocumentType, KnowledgeDevice, KnowledgeDocument, KnowledgeManufacturer, ManufacturerPayload } from "@/types/knowledge";

function errorMessage(error: unknown) {
  if (typeof error === "object" && error !== null && "response" in error) {
    return (error as { response?: { data?: { detail?: string } } }).response?.data?.detail ?? "Aktion fehlgeschlagen";
  }
  return "Aktion fehlgeschlagen";
}

function fileSize(value: number) {
  if (!value) return "-";
  if (value < 1024 * 1024) return `${Math.round(value / 1024)} KB`;
  return `${(value / 1024 / 1024).toFixed(1)} MB`;
}

export default function KnowledgeDocumentsPage() {
  const { showToast } = useToast();
  const [documents, setDocuments] = useState<KnowledgeDocument[]>([]);
  const [manufacturers, setManufacturers] = useState<KnowledgeManufacturer[]>([]);
  const [devices, setDevices] = useState<KnowledgeDevice[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState("");
  const [formError, setFormError] = useState("");
  const [pending, setPending] = useState(false);
  const [search, setSearch] = useState("");
  const [manufacturerFilter, setManufacturerFilter] = useState("all");
  const [typeFilter, setTypeFilter] = useState<DocumentType | "all">("all");
  const [sortKey, setSortKey] = useState("created_at");
  const [sortDirection, setSortDirection] = useState<"asc" | "desc">("desc");
  const [formOpen, setFormOpen] = useState(false);
  const [manufacturerFormOpen, setManufacturerFormOpen] = useState(false);
  const [deviceFormOpen, setDeviceFormOpen] = useState(false);
  const [deviceInitialManufacturerId, setDeviceInitialManufacturerId] = useState<number | null>(null);
  const [selected, setSelected] = useState<KnowledgeDocument | null>(null);
  const [deleteItem, setDeleteItem] = useState<KnowledgeDocument | null>(null);

  const loadItems = useCallback(async () => {
    setLoading(true);
    try {
      const [manufacturerResponse, deviceResponse, documentResponse] = await Promise.all([
        api.get<KnowledgeManufacturer[]>("/knowledge/manufacturers?limit=100"),
        api.get<KnowledgeDevice[]>("/knowledge/devices?limit=100"),
        api.get<KnowledgeDocument[]>("/knowledge/documents?limit=100"),
      ]);
      setManufacturers(manufacturerResponse.data);
      setDevices(deviceResponse.data);
      setDocuments(documentResponse.data);
      setError("");
    } catch (err) {
      setError(errorMessage(err));
    } finally {
      setLoading(false);
    }
  }, []);

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

  const rows = useMemo(() => documents
    .filter((item) => manufacturerFilter === "all" || item.manufacturer_id === Number(manufacturerFilter))
    .filter((item) => typeFilter === "all" || item.document_type === typeFilter)
    .filter((item) => [item.title, item.manufacturer.name, item.device?.name ?? "", ...item.tags].some((value) => value.toLowerCase().includes(search.toLowerCase())))
    .sort((a, b) => {
      const av = sortKey === "manufacturer" ? a.manufacturer.name : String(a[sortKey as keyof KnowledgeDocument] ?? "");
      const bv = sortKey === "manufacturer" ? b.manufacturer.name : String(b[sortKey as keyof KnowledgeDocument] ?? "");
      const result = av.toLowerCase() > bv.toLowerCase() ? 1 : av.toLowerCase() < bv.toLowerCase() ? -1 : 0;
      return sortDirection === "asc" ? result : -result;
    }), [documents, manufacturerFilter, search, sortDirection, sortKey, typeFilter]);

  const selectedManufacturerId = manufacturerFilter === "all"
    ? devices[0]?.manufacturer_id ?? manufacturers[0]?.id ?? null
    : Number(manufacturerFilter);
  const selectedManufacturer = manufacturers.find((manufacturer) => manufacturer.id === selectedManufacturerId) ?? null;
  const selectedManufacturerDevices = selectedManufacturerId
    ? devices.filter((device) => device.manufacturer_id === selectedManufacturerId)
    : [];
  const canUpload = manufacturers.length > 0
    && devices.length > 0
    && (manufacturerFilter === "all" || selectedManufacturerDevices.length > 0);

  const columns: DataTableColumn<KnowledgeDocument>[] = [
    { key: "title", label: "Titel", sortable: true, render: (item) => <span className="font-medium">{item.title}</span> },
    { key: "manufacturer", label: "Hersteller", sortable: true, render: (item) => item.manufacturer.name },
    { key: "device", label: "Gerät", render: (item) => item.device?.name ?? "-" },
    { key: "document_type", label: "Typ", sortable: true, render: (item) => <DocumentTypeBadge type={item.document_type} /> },
    { key: "language", label: "Sprache", sortable: true, render: (item) => item.language },
    { key: "file_size", label: "Größe", render: (item) => fileSize(item.file_size) },
    { key: "tags", label: "Tags", render: (item) => <TagList tags={item.tags} /> },
    {
      key: "actions",
      label: "Aktionen",
      className: "px-4 py-3 text-right",
      render: (item) => (
        <div className="flex justify-end gap-2">
          <Link href={`/knowledge/documents/${item.id}`} className={buttonVariants({ variant: "ghost", size: "icon-sm" })} title="Details"><Eye size={16} /></Link>
          {item.file_name && <Link href={`/api/knowledge/documents/${item.id}/download`} className={buttonVariants({ variant: "ghost", size: "icon-sm" })} title="Download"><Download size={16} /></Link>}
          <Button variant="ghost" size="icon-sm" title="Bearbeiten" onClick={() => { setSelected(item); setFormError(""); setFormOpen(true); }}><Edit size={16} /></Button>
          <Button variant="destructive" size="icon-sm" title="Löschen" onClick={() => setDeleteItem(item)}><Trash2 size={16} /></Button>
        </div>
      ),
    },
  ];

  async function save(payload: DocumentPayload, file: File | null) {
    if (!payload.manufacturer_id || !payload.device_id || (!selected && !file)) {
      const message = "Die Datei konnte nicht hochgeladen werden, weil die Zuordnung unvollständig ist.";
      setFormError(message);
      showToast({ type: "error", title: "Dokument kann nicht gespeichert werden", description: message });
      return;
    }

    setPending(true);
    setFormError("");
    try {
      if (selected) {
        await api.put(`/knowledge/documents/${selected.id}`, payload);
        showToast({ type: "success", title: "Dokument aktualisiert", description: payload.title });
      } else {
        if (!file) return;
        const formData = new FormData();
        Object.entries(payload).forEach(([key, value]) => {
          if (key === "tags") formData.append(key, (value as string[]).join(","));
          else if (value !== null && value !== undefined) formData.append(key, String(value));
        });
        formData.append("file", file);
        await api.post("/knowledge/documents/upload", formData);
        showToast({ type: "success", title: "Dokument hochgeladen", description: payload.title });
      }
      setFormOpen(false);
      await loadItems();
    } catch (err) {
      const message = errorMessage(err);
      setFormError(message);
      showToast({ type: "error", title: "Dokument konnte nicht gespeichert werden", description: message });
    } finally {
      setPending(false);
    }
  }

  async function saveManufacturer(payload: ManufacturerPayload) {
    setPending(true);
    setFormError("");
    try {
      const response = await api.post<KnowledgeManufacturer>("/knowledge/manufacturers", payload);
      showToast({ type: "success", title: "Hersteller erstellt", description: response.data.name });
      setManufacturerFilter(String(response.data.id));
      setDeviceInitialManufacturerId(response.data.id);
      setManufacturerFormOpen(false);
      await loadItems();
    } catch (err) {
      const message = errorMessage(err);
      setFormError(message);
      showToast({ type: "error", title: "Hersteller konnte nicht gespeichert werden", description: message });
    } finally {
      setPending(false);
    }
  }

  async function saveDevice(payload: DevicePayload) {
    setPending(true);
    setFormError("");
    try {
      const response = await api.post<KnowledgeDevice>("/knowledge/devices", payload);
      showToast({ type: "success", title: "Gerät erstellt", description: response.data.name });
      setManufacturerFilter(String(response.data.manufacturer_id));
      setDeviceFormOpen(false);
      await loadItems();
    } catch (err) {
      const message = errorMessage(err);
      setFormError(message);
      showToast({ type: "error", title: "Gerät konnte nicht gespeichert werden", description: message });
    } finally {
      setPending(false);
    }
  }

  function openDeviceCreate(manufacturerId: number | null = selectedManufacturerId) {
    setDeviceInitialManufacturerId(manufacturerId);
    setFormError("");
    setDeviceFormOpen(true);
  }

  async function confirmDelete() {
    if (!deleteItem) return;
    setPending(true);
    try {
      await api.delete(`/knowledge/documents/${deleteItem.id}`);
      showToast({ type: "success", title: "Dokument gelöscht", description: deleteItem.title });
      setDeleteItem(null);
      await loadItems();
    } catch (err) {
      showToast({ type: "error", title: "Dokument konnte nicht gelöscht werden", description: errorMessage(err) });
    } finally {
      setPending(false);
    }
  }

  return (
    <div className="space-y-6">
      <div className="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
        <div><h1 className="text-3xl font-bold text-slate-950">Dokumente</h1><p className="mt-1 text-sm text-slate-500">{rows.length} Unterlagen</p></div>
        <Button onClick={() => { setSelected(null); setFormError(""); setFormOpen(true); }} disabled={!canUpload}><Plus size={16} />Upload</Button>
      </div>
      <div className="flex flex-col gap-3 rounded-lg border bg-white p-4 lg:flex-row">
        <SearchInput value={search} onChange={setSearch} placeholder="Dokumente suchen" />
        <select className="h-8 rounded-lg border px-2 text-sm" value={manufacturerFilter} onChange={(event) => setManufacturerFilter(event.target.value)}>
          <option value="all">Alle Hersteller</option>
          {manufacturers.map((item) => <option key={item.id} value={item.id}>{item.name}</option>)}
        </select>
        <select className="h-8 rounded-lg border px-2 text-sm" value={typeFilter} onChange={(event) => setTypeFilter(event.target.value as DocumentType | "all")}>
          <option value="all">Alle Typen</option>
          <option value="manual">Bedienungsanleitung</option>
          <option value="service_manual">Service Manual</option>
          <option value="schematic">Schaltplan</option>
          <option value="alignment">Abgleich</option>
          <option value="parts_list">Ersatzteile</option>
          <option value="firmware">Firmware</option>
          <option value="datasheet">Datenblatt</option>
          <option value="service_bulletin">Bulletin</option>
          <option value="other">Sonstiges</option>
        </select>
      </div>
      {!loading && !error && manufacturers.length === 0 ? (
        <EmptyState
          title="Es ist noch kein Hersteller vorhanden"
          description="Bitte lege zuerst einen Hersteller an. Danach kannst du Geräte und Dokumente wie Schaltpläne oder Service Manuals erfassen."
          action={<Button onClick={() => { setFormError(""); setManufacturerFormOpen(true); }}><Plus size={16} />Hersteller anlegen</Button>}
        />
      ) : !loading && !error && devices.length === 0 ? (
        <EmptyState
          title="Es ist noch kein Gerät vorhanden"
          description="Dokumente wie Schaltpläne oder Service Manuals müssen einem Gerät zugeordnet werden."
          action={<Button onClick={() => openDeviceCreate()}><Plus size={16} />Gerät anlegen</Button>}
        />
      ) : !loading && !error && selectedManufacturer && manufacturerFilter !== "all" && selectedManufacturerDevices.length === 0 ? (
        <EmptyState
          title="Für diesen Hersteller existiert noch kein Gerät"
          description="Lege zuerst ein Gerät für diesen Hersteller an. Danach kannst du Dokumente diesem Gerät zuordnen."
          action={<Button onClick={() => openDeviceCreate(selectedManufacturer.id)}><Plus size={16} />Gerät für diesen Hersteller anlegen</Button>}
        />
      ) : !loading && !error && documents.length === 0 ? (
        <EmptyState
          title="Es ist noch kein Dokument vorhanden"
          description="Lade das erste Dokument hoch, sobald Hersteller und Gerät angelegt sind."
          action={<Button onClick={() => { setSelected(null); setFormError(""); setFormOpen(true); }} disabled={!canUpload}><Plus size={16} />Dokument hochladen</Button>}
        />
      ) : !loading && !error && rows.length === 0 ? (
        <EmptyState
          title="Keine Dokumente gefunden"
          description="Für Suche oder Filter gibt es keinen Treffer. Passe die Filter an oder lade ein neues Dokument hoch."
          action={<Button onClick={() => { setSelected(null); setFormError(""); setFormOpen(true); }} disabled={!canUpload}><Plus size={16} />Dokument hochladen</Button>}
        />
      ) : (
        <DataTable columns={columns} rows={rows} rowKey={(item) => item.id} sortKey={sortKey} sortDirection={sortDirection} loading={loading} error={error} emptyTitle="Keine Dokumente" emptyDescription="Lade das erste Service-Dokument hoch." onSort={(key) => { setSortKey(key); setSortDirection((current) => sortKey === key && current === "asc" ? "desc" : "asc"); }} />
      )}
      <DocumentUploadDialog
        open={formOpen}
        document={selected}
        manufacturers={manufacturers}
        devices={devices}
        initialManufacturerId={selectedManufacturerId}
        pending={pending}
        error={formError}
        onOpenChange={setFormOpen}
        onSubmit={save}
        onValidationError={(message) => showToast({ type: "error", title: "Upload unvollständig", description: message })}
      />
      <ManufacturerFormDialog open={manufacturerFormOpen} manufacturer={null} pending={pending} error={formError} onOpenChange={setManufacturerFormOpen} onSubmit={saveManufacturer} />
      <DeviceFormDialog open={deviceFormOpen} device={null} manufacturers={manufacturers} initialManufacturerId={deviceInitialManufacturerId} pending={pending} error={formError} onOpenChange={setDeviceFormOpen} onSubmit={saveDevice} />
      <ConfirmDialog open={Boolean(deleteItem)} title="Dokument löschen" description="Der Datenbankeintrag und die gespeicherte Datei werden entfernt." pending={pending} onOpenChange={(open) => !open && setDeleteItem(null)} onConfirm={confirmDelete}>
        {deleteItem && <p className="text-sm font-medium">{deleteItem.title}</p>}
      </ConfirmDialog>
    </div>
  );
}
