"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import Link from "next/link";
import { Edit, Eye, Plus, Trash2, Wrench } 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 RepairFormDialog from "@/components/repairs/RepairFormDialog";
import { RepairPriorityBadge, RepairStatusBadge, priorityLabels, 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, RepairListResponse, RepairPayload, RepairPriority, RepairSource, RepairStatus } from "@/types/repair";

const pageSize = 10;

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) {
  return new Intl.DateTimeFormat("de-DE", { dateStyle: "short", timeStyle: "short" }).format(new Date(value));
}

function deviceLabel(repair: Repair) {
  return `${repair.device_manufacturer} ${repair.device_model}`.trim();
}

export default function RepairsPage() {
  const { showToast } = useToast();
  const [repairs, setRepairs] = useState<Repair[]>([]);
  const [total, setTotal] = useState(0);
  const [currentUser, setCurrentUser] = useState<CurrentUser | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState("");
  const [formError, setFormError] = useState("");
  const [statusError, setStatusError] = useState("");
  const [cancelError, setCancelError] = useState("");
  const [pending, setPending] = useState(false);
  const [search, setSearch] = useState("");
  const [statusFilter, setStatusFilter] = useState<RepairStatus | "all">("all");
  const [sourceFilter, setSourceFilter] = useState<RepairSource | "all">("all");
  const [priorityFilter, setPriorityFilter] = useState<RepairPriority | "all">("all");
  const [page, setPage] = useState(1);
  const [sortKey, setSortKey] = useState("created_at");
  const [sortDirection, setSortDirection] = useState<"asc" | "desc">("desc");
  const [formOpen, setFormOpen] = useState(false);
  const [statusOpen, setStatusOpen] = useState(false);
  const [selectedRepair, setSelectedRepair] = useState<Repair | null>(null);
  const [cancelRepair, setCancelRepair] = useState<Repair | null>(null);

  const loadRepairs = useCallback(async () => {
    setLoading(true);
    setError("");
    try {
      const params = new URLSearchParams();
      params.set("limit", String(pageSize));
      params.set("offset", String((page - 1) * pageSize));
      if (search.trim()) params.set("q", search.trim());
      if (statusFilter !== "all") params.set("status", statusFilter);
      if (sourceFilter !== "all") params.set("source", sourceFilter);
      if (priorityFilter !== "all") params.set("priority", priorityFilter);
      const [repairResponse, meResponse] = await Promise.all([
        api.get<RepairListResponse>(`/repairs?${params.toString()}`),
        api.get<CurrentUser>("/me"),
      ]);
      setRepairs(repairResponse.data.items);
      setTotal(repairResponse.data.total);
      setCurrentUser(meResponse.data);
    } catch (err) {
      setError(getErrorMessage(err));
    } finally {
      setLoading(false);
    }
  }, [page, priorityFilter, search, sourceFilter, statusFilter]);

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

  const sortedRepairs = useMemo(() => [...repairs].sort((first, second) => {
    const firstValue = String(first[sortKey as keyof Repair] ?? "").toLowerCase();
    const secondValue = String(second[sortKey as keyof Repair] ?? "").toLowerCase();
    if (firstValue === secondValue) return 0;
    const result = firstValue > secondValue ? 1 : -1;
    return sortDirection === "asc" ? result : -result;
  }), [repairs, sortDirection, sortKey]);

  const pageCount = Math.max(1, Math.ceil(total / pageSize));
  const currentPage = Math.min(page, pageCount);
  const canCreate = hasPermission(currentUser, "repairs.create");
  const canUpdate = hasPermission(currentUser, "repairs.update");
  const canUpdateStatus = hasPermission(currentUser, "repairs.status.update");
  const canDelete = hasPermission(currentUser, "repairs.delete");

  const columns: DataTableColumn<Repair>[] = [
    { key: "repair_number", label: "Reparaturnummer", sortable: true, render: (repair) => <span className="font-medium text-slate-950">{repair.repair_number}</span> },
    { key: "status", label: "Status", sortable: true, render: (repair) => <RepairStatusBadge status={repair.status} /> },
    { key: "priority", label: "Priorität", sortable: true, render: (repair) => <RepairPriorityBadge priority={repair.priority} /> },
    { key: "customer_name", label: "Kunde", sortable: true, render: (repair) => repair.customer_name },
    { key: "device_model", label: "Gerät", sortable: true, render: (repair) => deviceLabel(repair) },
    { key: "fault_description", label: "Fehler", render: (repair) => <span title={repair.fault_description}>{repair.fault_description.slice(0, 80)}{repair.fault_description.length > 80 ? "..." : ""}</span> },
    { key: "source", label: "Quelle", sortable: true, render: (repair) => repair.source },
    { key: "created_at", label: "Erstellt", sortable: true, render: (repair) => formatDate(repair.created_at) },
    {
      key: "actions",
      label: "Aktionen",
      className: "px-4 py-3 text-right",
      render: (repair) => (
        <div className="flex justify-end gap-2">
          <Link href={`/repairs/${repair.id}`} className={buttonVariants({ variant: "ghost", size: "icon-sm" })} title="Details"><Eye size={16} /></Link>
          {canUpdate && <Button type="button" variant="ghost" size="icon-sm" title="Bearbeiten" onClick={() => { setSelectedRepair(repair); setFormError(""); setFormOpen(true); }}><Edit size={16} /></Button>}
          {canUpdateStatus && <Button type="button" variant="ghost" size="icon-sm" title="Status ändern" onClick={() => { setSelectedRepair(repair); setStatusError(""); setStatusOpen(true); }}><Wrench size={16} /></Button>}
          {canDelete && <Button type="button" variant="destructive" size="icon-sm" title="Stornieren" onClick={() => setCancelRepair(repair)}><Trash2 size={16} /></Button>}
        </div>
      ),
    },
  ];

  function handleSort(key: string) {
    if (sortKey === key) {
      setSortDirection((current) => (current === "asc" ? "desc" : "asc"));
      return;
    }
    setSortKey(key);
    setSortDirection("asc");
  }

  async function saveRepair(payload: RepairPayload) {
    setPending(true);
    setFormError("");
    try {
      if (selectedRepair) {
        const response = await api.put<Repair>(`/repairs/${selectedRepair.id}`, payload);
        setRepairs((current) => current.map((repair) => repair.id === selectedRepair.id ? response.data : repair));
        showToast({ type: "success", title: "Reparatur aktualisiert", description: response.data.repair_number });
      } else {
        const response = await api.post<Repair>("/repairs", payload);
        setRepairs((current) => [response.data, ...current].slice(0, pageSize));
        setTotal((current) => current + 1);
        showToast({ type: "success", title: "Reparatur angelegt", description: response.data.repair_number });
      }
      setFormOpen(false);
    } 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 (!selectedRepair) return;
    setPending(true);
    setStatusError("");
    try {
      const response = await api.put<Repair>(`/repairs/${selectedRepair.id}/status`, { status, note });
      setRepairs((current) => current.map((repair) => repair.id === selectedRepair.id ? response.data : repair));
      showToast({ type: "success", title: "Status aktualisiert", description: response.data.repair_number });
      setStatusOpen(false);
    } catch (err) {
      const message = getErrorMessage(err);
      setStatusError(message);
      showToast({ type: "error", title: "Status konnte nicht gespeichert werden", description: message });
    } finally {
      setPending(false);
    }
  }

  async function confirmCancel() {
    if (!cancelRepair) return;
    setPending(true);
    setCancelError("");
    try {
      const response = await api.delete<Repair>(`/repairs/${cancelRepair.id}`);
      setRepairs((current) => current.map((repair) => repair.id === cancelRepair.id ? response.data : repair));
      showToast({ type: "success", title: "Reparatur storniert", description: cancelRepair.repair_number });
      setCancelRepair(null);
    } catch (err) {
      const message = getErrorMessage(err);
      setCancelError(message);
      showToast({ type: "error", title: "Reparatur konnte nicht storniert werden", description: message });
    } 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">Reparaturen</h1>
          <p className="mt-1 text-sm text-slate-500">{total} Werkstattvorgänge</p>
        </div>
        {canCreate && <Button type="button" onClick={() => { setSelectedRepair(null); setFormError(""); setFormOpen(true); }}><Plus size={16} />Reparatur anlegen</Button>}
      </div>

      <div className="flex flex-col gap-3 rounded-lg border bg-white p-4 xl:flex-row xl:items-center">
        <SearchInput value={search} onChange={(value) => { setSearch(value); setPage(1); }} placeholder="Reparaturen suchen" />
        <select value={statusFilter} onChange={(event) => { setStatusFilter(event.target.value as RepairStatus | "all"); setPage(1); }} className="h-8 rounded-lg border border-input bg-transparent px-2.5 text-sm">
          <option value="all">Alle Status</option>
          {(["new", "accepted", "diagnosis", "estimate", "waiting_for_customer", "approved", "repair", "final_test", "ready_for_pickup", "shipped", "completed", "cancelled"] as RepairStatus[]).map((status) => <option key={status} value={status}>{statusLabels[status]}</option>)}
        </select>
        <select value={sourceFilter} onChange={(event) => { setSourceFilter(event.target.value as RepairSource | "all"); setPage(1); }} className="h-8 rounded-lg border border-input bg-transparent px-2.5 text-sm">
          <option value="all">Alle Quellen</option>
          {["manual", "website", "customer_portal", "email", "phone"].map((source) => <option key={source} value={source}>{source}</option>)}
        </select>
        <select value={priorityFilter} onChange={(event) => { setPriorityFilter(event.target.value as RepairPriority | "all"); setPage(1); }} className="h-8 rounded-lg border border-input bg-transparent px-2.5 text-sm">
          <option value="all">Alle Prioritäten</option>
          {(["low", "normal", "high", "urgent"] as RepairPriority[]).map((priority) => <option key={priority} value={priority}>{priorityLabels[priority]}</option>)}
        </select>
      </div>

      {!loading && !error && total === 0 && !search && statusFilter === "all" && sourceFilter === "all" && priorityFilter === "all" ? (
        <EmptyState
          title="Noch keine Reparaturen vorhanden."
          description="Lege den ersten Werkstattvorgang manuell an oder nutze später die Website-Intake-Schnittstelle."
          action={canCreate ? <Button type="button" onClick={() => setFormOpen(true)}><Plus size={16} />Reparatur anlegen</Button> : undefined}
        />
      ) : (
        <DataTable
          columns={columns}
          rows={sortedRepairs}
          rowKey={(repair) => repair.id}
          sortKey={sortKey}
          sortDirection={sortDirection}
          loading={loading}
          error={error}
          emptyTitle="Noch keine Reparaturen vorhanden."
          emptyDescription="Passe Suche oder Filter an oder lege eine Reparatur an."
          onSort={handleSort}
        />
      )}

      <div className="flex items-center justify-between text-sm text-slate-600">
        <span>Seite {currentPage} von {pageCount}</span>
        <div className="flex gap-2">
          <Button type="button" variant="outline" disabled={currentPage === 1} onClick={() => setPage((current) => Math.max(1, current - 1))}>Zurück</Button>
          <Button type="button" variant="outline" disabled={currentPage === pageCount} onClick={() => setPage((current) => Math.min(pageCount, current + 1))}>Weiter</Button>
        </div>
      </div>

      <RepairFormDialog key={`form-${selectedRepair?.id ?? "new"}-${formOpen}`} open={formOpen} repair={selectedRepair} pending={pending} serverError={formError} onOpenChange={setFormOpen} onSubmit={saveRepair} />
      <RepairStatusDialog key={`status-${selectedRepair?.id ?? "none"}-${statusOpen}`} open={statusOpen} repair={selectedRepair} pending={pending} serverError={statusError} onOpenChange={setStatusOpen} onSubmit={saveStatus} />

      <ConfirmDialog
        open={Boolean(cancelRepair)}
        title="Reparatur stornieren"
        description="Die Reparatur wird nicht physisch gelöscht, sondern auf storniert gesetzt."
        confirmLabel="Stornieren"
        pending={pending}
        onOpenChange={(open) => {
          if (!open) {
            setCancelRepair(null);
            setCancelError("");
          }
        }}
        onConfirm={confirmCancel}
      >
        {cancelRepair && (
          <div className="space-y-2 text-sm">
            <p className="font-medium">{cancelRepair.repair_number}</p>
            <p>{cancelRepair.customer_name} · {deviceLabel(cancelRepair)}</p>
            {cancelError && <p className="text-red-600">{cancelError}</p>}
          </div>
        )}
      </ConfirmDialog>
    </div>
  );
}
