"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import { Eye, Filter, RotateCcw } from "lucide-react";

import DataTable, { type DataTableColumn } from "@/components/common/DataTable";
import SearchInput from "@/components/common/SearchInput";
import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { api } from "@/lib/api";
import type { ApiSuccess, AuditLog, AuditLogListResponse } from "@/types/audit";

const pageSize = 20;

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?.message ?? response?.data?.detail ?? "Audit Logs konnten nicht geladen werden";
  }
  return "Audit Logs konnten nicht geladen werden";
}

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

function formatJson(value: unknown) {
  if (value === null || value === undefined) {
    return "-";
  }

  return JSON.stringify(value, null, 2);
}

export default function AuditLogsPage() {
  const [items, setItems] = useState<AuditLog[]>([]);
  const [total, setTotal] = useState(0);
  const [page, setPage] = useState(1);
  const [search, setSearch] = useState("");
  const [entityType, setEntityType] = useState("");
  const [action, setAction] = useState("");
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState("");
  const [selectedLog, setSelectedLog] = useState<AuditLog | null>(null);

  const loadAuditLogs = useCallback(async () => {
    setLoading(true);
    setError("");

    try {
      const params = new URLSearchParams({
        page: String(page),
        page_size: String(pageSize),
      });

      if (entityType.trim()) {
        params.set("entity_type", entityType.trim());
      }

      if (action.trim()) {
        params.set("action", action.trim());
      }

      const response = await api.get<ApiSuccess<AuditLogListResponse>>(`/audit-logs?${params.toString()}`);
      setItems(response.data.data.items);
      setTotal(response.data.data.total);
    } catch (err) {
      setError(getErrorMessage(err));
    } finally {
      setLoading(false);
    }
  }, [action, entityType, page]);

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

  const filteredItems = useMemo(() => {
    const normalized = search.trim().toLowerCase();
    if (!normalized) {
      return items;
    }

    return items.filter((item) => (
      item.actor_username.toLowerCase().includes(normalized)
      || item.action.toLowerCase().includes(normalized)
      || item.entity_type.toLowerCase().includes(normalized)
      || item.entity_label.toLowerCase().includes(normalized)
    ));
  }, [items, search]);

  const totalPages = Math.max(1, Math.ceil(total / pageSize));

  const columns: DataTableColumn<AuditLog>[] = [
    {
      key: "created_at",
      label: "Zeitpunkt",
      render: (log) => <span className="whitespace-nowrap">{formatDate(log.created_at)}</span>,
    },
    {
      key: "actor_username",
      label: "Benutzer",
      render: (log) => log.actor_username || "System",
    },
    {
      key: "action",
      label: "Aktion",
      render: (log) => <span className="font-medium text-slate-950">{log.action}</span>,
    },
    {
      key: "entity",
      label: "Objekt",
      render: (log) => (
        <div>
          <p className="font-medium text-slate-900">{log.entity_label || "-"}</p>
          <p className="text-xs text-slate-500">{log.entity_type}{log.entity_id ? ` #${log.entity_id}` : ""}</p>
        </div>
      ),
    },
    {
      key: "ip_address",
      label: "IP",
      render: (log) => log.ip_address || "-",
    },
    {
      key: "details",
      label: "",
      className: "px-4 py-3 text-right",
      render: (log) => (
        <Button type="button" variant="outline" size="sm" onClick={() => setSelectedLog(log)}>
          <Eye size={16} />
          Details
        </Button>
      ),
    },
  ];

  return (
    <div className="space-y-6">
      <div className="flex flex-col gap-4 lg:flex-row lg:items-end lg:justify-between">
        <div>
          <h1 className="text-3xl font-bold text-slate-950">Audit Logs</h1>
          <p className="mt-1 text-sm text-slate-500">Nachvollziehbare Systemereignisse und Änderungen</p>
        </div>
        <Button type="button" variant="outline" onClick={() => void loadAuditLogs()}>
          <RotateCcw size={16} />
          Aktualisieren
        </Button>
      </div>

      <section className="rounded-lg border bg-white p-4">
        <div className="grid gap-4 lg:grid-cols-[1fr_220px_220px_auto] lg:items-end">
          <SearchInput value={search} onChange={setSearch} placeholder="Audit Logs durchsuchen..." />

          <div className="space-y-2">
            <Label htmlFor="entity-type">Objekttyp</Label>
            <Input
              id="entity-type"
              value={entityType}
              onChange={(event) => {
                setEntityType(event.target.value);
                setPage(1);
              }}
              placeholder="customers"
            />
          </div>

          <div className="space-y-2">
            <Label htmlFor="action">Aktion</Label>
            <Input
              id="action"
              value={action}
              onChange={(event) => {
                setAction(event.target.value);
                setPage(1);
              }}
              placeholder="users.update"
            />
          </div>

          <Button
            type="button"
            variant="outline"
            onClick={() => {
              setSearch("");
              setEntityType("");
              setAction("");
              setPage(1);
            }}
          >
            <Filter size={16} />
            Zurücksetzen
          </Button>
        </div>
      </section>

      <DataTable
        columns={columns}
        rows={filteredItems}
        rowKey={(row) => row.id}
        sortKey="created_at"
        sortDirection="desc"
        loading={loading}
        error={error}
        emptyTitle="Keine Audit Logs gefunden"
        emptyDescription="Für die aktuellen Filter sind keine Einträge vorhanden."
        onSort={() => undefined}
      />

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

      <Dialog open={selectedLog !== null} onOpenChange={(open) => !open && setSelectedLog(null)}>
        <DialogContent className="max-w-5xl">
          <DialogHeader>
            <DialogTitle>Audit Log Details</DialogTitle>
          </DialogHeader>
          {selectedLog && (
            <div className="space-y-4">
              <div className="grid gap-3 text-sm md:grid-cols-3">
                <Detail label="Aktion" value={selectedLog.action} />
                <Detail label="Benutzer" value={selectedLog.actor_username || "System"} />
                <Detail label="Zeitpunkt" value={formatDate(selectedLog.created_at)} />
                <Detail label="Objekt" value={`${selectedLog.entity_type}${selectedLog.entity_id ? ` #${selectedLog.entity_id}` : ""}`} />
                <Detail label="Label" value={selectedLog.entity_label || "-"} />
                <Detail label="IP" value={selectedLog.ip_address || "-"} />
              </div>

              <div className="grid gap-4 lg:grid-cols-3">
                <JsonPanel title="Vorher" value={selectedLog.before_data} />
                <JsonPanel title="Nachher" value={selectedLog.after_data} />
                <JsonPanel title="Metadaten" value={selectedLog.metadata_data} />
              </div>
            </div>
          )}
        </DialogContent>
      </Dialog>
    </div>
  );
}

function Detail({ label, value }: { label: string; value: string }) {
  return (
    <div className="rounded-lg border bg-slate-50 p-3">
      <p className="text-xs font-semibold uppercase text-slate-500">{label}</p>
      <p className="mt-1 break-words text-slate-950">{value}</p>
    </div>
  );
}

function JsonPanel({ title, value }: { title: string; value: unknown }) {
  return (
    <div>
      <h2 className="mb-2 text-sm font-semibold text-slate-950">{title}</h2>
      <pre className="max-h-96 overflow-auto rounded-lg border bg-slate-950 p-3 text-xs text-slate-100">
        {formatJson(value)}
      </pre>
    </div>
  );
}
