// app/(app)/devices/page.tsx
'use client';

import { useCallback, useEffect, useState } from 'react';
import { useSearchParams, useRouter } from 'next/navigation';
import Button from '@/components/ui/Button';
import Table, { TableColumn } from '@/components/ui/Table';
import { Dropdown } from '@/components/ui/Dropdown';
import Tabs from '@/components/ui/Tabs';
import {
  BookOpenIcon,
  PencilIcon,
  TrashIcon,
  PlusIcon
} from '@heroicons/react/24/outline';
import { getSocket } from '@/lib/socketClient';
import type { TagOption } from '@/components/ui/TagMultiCombobox';
import DeviceEditModal from './DeviceEditModal';
import DeviceDetailModal from './DeviceDetailModal';
import DeviceCreateModal from './DeviceCreateModal';

export type AccessorySummary = {
  inventoryNumber: string;
  name: string | null;
};

export type DeviceDetail = {
  inventoryNumber: string;
  name: string | null;
  manufacturer: string | null;
  model: string | null;
  serialNumber: string | null;
  productNumber: string | null;
  comment: string | null;
  ipv4Address: string | null;
  ipv6Address: string | null;
  macAddress: string | null;
  username: string | null;
  passwordHash: string | null;
  group: string | null;
  location: string | null;
  tags: string[];
  loanedTo: string | null;
  loanedFrom: string | null;
  loanedUntil: string | null;
  loanComment: string | null;
  parentInventoryNumber: string | null;
  parentName: string | null;
  accessories: {
    inventoryNumber: string;
    name: string | null;
  }[];
  createdAt: string | null;
  updatedAt: string | null;
};

function formatDate(iso: string | null | undefined) {
  if (!iso) return '–'; // oder '' wenn du es leer willst

  return new Intl.DateTimeFormat('de-DE', {
    dateStyle: 'short',
    timeStyle: 'short',
  }).format(new Date(iso));
}

const columns: TableColumn<DeviceDetail>[] = [
  {
    key: 'inventoryNumber',
    header: 'Nr.',
    sortable: true,
    canHide: false,
  },
  {
    key: 'name',
    header: 'Bezeichnung',
    sortable: true,
    canHide: true,
    cellClassName: 'font-medium text-gray-900 dark:text-white',
  },
  {
    key: 'manufacturer',
    header: 'Hersteller',
    sortable: true,
    canHide: false,
  },
  {
    key: 'model',
    header: 'Modell',
    sortable: true,
    canHide: false,
  },
  {
    key: 'serialNumber',
    header: 'Seriennummer',
    sortable: true,
    canHide: true,
  },
  {
    key: 'productNumber',
    header: 'Produktnummer',
    sortable: true,
    canHide: true,
  },
  {
    key: 'group',
    header: 'Gruppe',
    sortable: true,
    canHide: true,
  },
  {
    key: 'location',
    header: 'Standort / Raum',
    sortable: true,
    canHide: true,
  },
  {
    key: 'comment',
    header: 'Kommentar',
    sortable: false,
    canHide: true,
    cellClassName: 'whitespace-normal max-w-xs',
  },
  {
    key: 'tags',
    header: 'Tags',
    sortable: false,
    canHide: true,
    render: (row) =>
      row.tags && row.tags.length > 0 ? row.tags.join(', ') : '',
  },
  {
    key: 'updatedAt',
    header: 'Geändert am',
    sortable: true,
    canHide: true,
    render: (row) => formatDate(row.updatedAt),
  },
];

export default function DevicesPage() {
  const [devices, setDevices] = useState<DeviceDetail[]>([]);
  const [listLoading, setListLoading] = useState(false);
  const [listError, setListError] = useState<string | null>(null);

  const [editInventoryNumber, setEditInventoryNumber] = useState<string | null>(null);
  const [detailInventoryNumber, setDetailInventoryNumber] = useState<string | null>(null);
  const [createOpen, setCreateOpen] = useState(false);

  const [allTags, setAllTags] = useState<TagOption[]>([]);

  const searchParams = useSearchParams();
  const router = useRouter();

    // TODO: Ersetze das durch deinen echten User-/Gruppen-Mechanismus
  // Beispiel: aktuelle Benutzergruppen (z.B. aus Context oder eigenem Hook)
  const currentUserGroups: string[] = []; // Platzhalter

  // Nur User in dieser Gruppe sollen Geräte bearbeiten dürfen
  const canEditDevices = currentUserGroups.includes('INVENTAR_ADMIN');

  // 🔹 Tab-Filter: Hauptgeräte / Zubehör / Alle
  const [activeTab, setActiveTab] =
    useState<'main' | 'accessories' | 'all'>('main');

  // 🔹 Counters für Badges
  const mainCount = devices.filter((d) => !d.parentInventoryNumber).length;
  const accessoriesCount = devices.filter((d) => !!d.parentInventoryNumber).length;
  const allCount = devices.length;

  /* ───────── Geräte-Liste laden ───────── */

  const loadDevices = useCallback(async () => {
    setListLoading(true);
    setListError(null);
    try {
      const res = await fetch('/api/devices', {
        method: 'GET',
        headers: { 'Content-Type': 'application/json' },
        cache: 'no-store',
      });

      if (!res.ok) {
        setListError('Geräte konnten nicht geladen werden.');
        return;
      }

      const data = (await res.json()) as DeviceDetail[];
      setDevices(data);

      const tagSet = new Map<string, TagOption>();
      for (const d of data) {
        (d.tags ?? []).forEach((name) => {
          const key = name.toLowerCase();
          if (!tagSet.has(key)) {
            tagSet.set(key, { name });
          }
        });
      }
      setAllTags(Array.from(tagSet.values()));
    } catch (err) {
      console.error('Error loading devices', err);
      setListError('Netzwerkfehler beim Laden der Geräte.');
    } finally {
      setListLoading(false);
    }
  }, []);

  useEffect(() => {
    loadDevices();
  }, [loadDevices]);

  useEffect(() => {
    if (!searchParams) return; // TS happy

    const fromDevice = searchParams.get('device');
    const fromInventory =
      searchParams.get('inventoryNumber') ?? searchParams.get('inv');

    const fromUrl = fromDevice || fromInventory;

    if (fromUrl) {
      setDetailInventoryNumber(fromUrl);
    }
  }, [searchParams]);

  /* ───────── Live-Updates via Socket.IO ───────── */

  useEffect(() => {
    const socket = getSocket();

    const handleUpdated = (payload: DeviceDetail) => {
      setDevices((prev) => {
        const exists = prev.some(
          (d) => d.inventoryNumber === payload.inventoryNumber,
        );
        if (!exists) {
          return [...prev, payload];
        }
        return prev.map((d) =>
          d.inventoryNumber === payload.inventoryNumber ? payload : d,
        );
      });
    };

    const handleCreated = (payload: DeviceDetail) => {
      setDevices((prev) => {
        if (prev.some((d) => d.inventoryNumber === payload.inventoryNumber)) {
          return prev;
        }
        return [...prev, payload];
      });
    };

    const handleDeleted = (data: { inventoryNumber: string }) => {
      setDevices((prev) =>
        prev.filter((d) => d.inventoryNumber !== data.inventoryNumber),
      );
    };

    socket.on('device:updated', handleUpdated);
    socket.on('device:created', handleCreated);
    socket.on('device:deleted', handleDeleted);

    return () => {
      socket.off('device:updated', handleUpdated);
      socket.off('device:created', handleCreated);
      socket.off('device:deleted', handleDeleted);
    };
  }, []);

  /* ───────── Edit-/Detail-/Create-Modal Trigger ───────── */

  const handleEdit = useCallback((inventoryNumber: string) => {
    setEditInventoryNumber(inventoryNumber);
  }, []);

  const closeEditModal = useCallback(() => {
    setEditInventoryNumber(null);
  }, []);

  const handleDelete = useCallback(
    async (inventoryNumber: string) => {
      const confirmed = window.confirm(
        `Gerät ${inventoryNumber} wirklich löschen?`,
      );
      if (!confirmed) return;

      try {
        const res = await fetch(
          `/api/devices/${encodeURIComponent(inventoryNumber)}`,
          {
            method: 'DELETE',
          },
        );

        if (!res.ok) {
          let message = 'Löschen des Geräts ist fehlgeschlagen.';

          try {
            const data = await res.json();
            if (data?.error) {
              if (data.error === 'HAS_ACCESSORIES') {
                message =
                  'Das Gerät hat noch Zubehör und kann nicht gelöscht werden. Entferne oder verschiebe zuerst das Zubehör.';
              } else if (data.error === 'NOT_FOUND') {
                message =
                  'Gerät wurde nicht gefunden (evtl. bereits gelöscht).';
              } else if (typeof data.error === 'string') {
                message = data.error;
              }
            }
          } catch {
            // ignore JSON-Parse-Error
          }

          alert(message);
          return;
        }

        // Optimistisch aus lokaler Liste entfernen
        // (zusätzlich kommt noch der Socket-Event device:deleted)
        setDevices((prev) =>
          prev.filter((d) => d.inventoryNumber !== inventoryNumber),
        );
      } catch (err) {
        console.error('Error deleting device', err);
        alert('Netzwerkfehler beim Löschen des Geräts.');
      }
    },
    [setDevices],
  );

  const handleDetails = useCallback((inventoryNumber: string) => {
    setDetailInventoryNumber(inventoryNumber);
  }, []);

  const openCreateModal = useCallback(() => {
    setCreateOpen(true);
  }, []);

  const closeCreateModal = useCallback(() => {
    setCreateOpen(false);
  }, []);

  const closeDetailModal = useCallback(() => {
    setDetailInventoryNumber(null);

    if (!searchParams) {
      // Fallback: einfach auf /devices ohne Query
      router.replace('/devices', { scroll: false });
      return;
    }

    // ReadonlyURLSearchParams → string → URLSearchParams kopieren
    const params = new URLSearchParams(searchParams.toString());

    // alle möglichen Detail-Parameter entfernen
    params.delete('device');
    params.delete('inventoryNumber');
    params.delete('inv');

    const queryString = params.toString();
    const newUrl = queryString ? `/devices?${queryString}` : '/devices';

    router.replace(newUrl, { scroll: false });
  }, [router, searchParams]);

  const handleEditFromDetail = useCallback(
    (inventoryNumber: string) => {
      // Detail-Modal schließen + URL /device-Query aufräumen
      closeDetailModal();
      // danach Edit-Modal öffnen
      setEditInventoryNumber(inventoryNumber);
    },
    [closeDetailModal],
  );


  /* ───────── Filter nach Tab ───────── */

  const filteredDevices = devices.filter((d) => {
    if (activeTab === 'main') {
      // Hauptgeräte: kein parent → eigenständig
      return !d.parentInventoryNumber;
    }
    if (activeTab === 'accessories') {
      // Zubehör: hat ein Hauptgerät
      return !!d.parentInventoryNumber;
    }
    // "all"
    return true;
  });

  /* ───────── Render ───────── */

  return (
    <>
      {/* Header über der Tabelle */}
      <div className="flex items-center justify-between gap-4">
        <div>
          <h1 className="text-2xl font-semibold text-gray-900 dark:text-white">
            Geräte
          </h1>
          <p className="mt-1 text-sm text-gray-600 dark:text-gray-400">
            Übersicht aller erfassten Geräte im Inventar.
          </p>
        </div>

        {canEditDevices && (
          <Button
            variant="soft"
            tone="indigo"
            size="md"
            icon={<PlusIcon className="size-5" />}
            aria-label="Neues Gerät anlegen"
            onClick={openCreateModal}
            title="Neues Gerät anlegen"
          >
            Neues Gerät anlegen
          </Button>
        )}
      </div>

      {/* 🔹 Tabs für Hauptgeräte/Zubehör/Alle */}
      <div className="mt-6">
        <Tabs
          tabs={[
            {
              id: 'main',
              label: 'Hauptgeräte',
              count: mainCount,
            },
            {
              id: 'accessories',
              label: 'Zubehör',
              count: accessoriesCount,
            },
            {
              id: 'all',
              label: 'Alle Geräte',
              count: allCount,
            },
          ]}
          value={activeTab}
          onChange={(id) =>
            setActiveTab(id as 'main' | 'accessories' | 'all')
          }
          ariaLabel="Geräteliste filtern"
        />
      </div>

      {listLoading && (
        <p className="mt-4 text-sm text-gray-500 dark:text-gray-400">
          Geräte werden geladen …
        </p>
      )}

      {listError && (
        <p className="mt-4 text-sm text-red-600 dark:text-red-400">
          {listError}
        </p>
      )}

      {/* Tabelle */}
      <div className="mt-8">
        <Table<DeviceDetail>
          data={filteredDevices}
          columns={columns}
          getRowId={(row) => row.inventoryNumber}
          selectable
          actionsHeader=""
          renderActions={(row) => (
            <div className="flex justify-end">
              {/* Desktop: drei Icon-Buttons nebeneinander */}
              <div className="hidden gap-2 lg:flex">
                <Button
                  variant="soft"
                  tone="indigo"
                  size="md"
                  icon={<BookOpenIcon className="size-5" />}
                  aria-label={`Details zu ${row.inventoryNumber}`}
                  onClick={() => handleDetails(row.inventoryNumber)}
                />

                <Button
                  variant="soft"
                  tone="gray"
                  size="md"
                  icon={<PencilIcon className="size-5" />}
                  aria-label={`Gerät ${row.inventoryNumber} bearbeiten`}
                  onClick={() => handleEdit(row.inventoryNumber)}
                />

                <Button
                  variant="soft"
                  tone="rose"
                  size="md"
                  icon={<TrashIcon className="size-5" />}
                  aria-label={`Gerät ${row.inventoryNumber} löschen`}
                  onClick={() => handleDelete(row.inventoryNumber)}
                />
              </div>

              {/* Mobile / kleine Screens: kompaktes Dropdown */}
              <div className="lg:hidden">
                <Dropdown
                  triggerVariant="icon"
                  ariaLabel={`Aktionen für ${row.inventoryNumber}`}
                  sections={[
                    {
                      items: [
                        {
                          label: 'Details',
                          icon: <BookOpenIcon className="size-4" />,
                          onClick: () => handleDetails(row.inventoryNumber),
                        },
                        {
                          label: 'Bearbeiten',
                          icon: <PencilIcon className="size-4" />,
                          onClick: () => handleEdit(row.inventoryNumber),
                        },
                        {
                          label: 'Löschen',
                          icon: <TrashIcon className="size-4" />,
                          tone: 'danger',
                          onClick: () => handleDelete(row.inventoryNumber),
                        },
                      ],
                    },
                  ]}
                />
              </div>
            </div>
          )}
        />
      </div>

      {/* Modals */}
      <DeviceEditModal
        open={editInventoryNumber !== null}
        inventoryNumber={editInventoryNumber}
        onClose={closeEditModal}
        allTags={allTags}
        setAllTags={setAllTags}
        onSaved={(updated) => {
          setDevices((prev) =>
            prev.map((d) =>
              d.inventoryNumber === updated.inventoryNumber
                ? { ...d, ...updated }
                : d,
            ),
          );
        }}
      />

      <DeviceCreateModal
        open={createOpen}
        onClose={closeCreateModal}
        allTags={allTags}
        setAllTags={setAllTags}
        onCreated={(created) => {
          setDevices((prev) => {
            if (prev.some((d) => d.inventoryNumber === created.inventoryNumber)) {
              return prev;
            }
            return [...prev, created];
          });
        }}
      />

      <DeviceDetailModal
        open={detailInventoryNumber !== null}
        inventoryNumber={detailInventoryNumber}
        onClose={closeDetailModal}
        canEdit={canEditDevices}
        onEdit={handleEditFromDetail}
      />
    </>
  );
}
