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

import { useCallback, useEffect, useState } from 'react';

import Button from '@/components/ui/Button';
import Table, { TableColumn } from '@/components/ui/Table';
import { Dropdown } from '@/components/ui/Dropdown';
import {
  BookOpenIcon,
  PencilIcon,
  TrashIcon,
} from '@heroicons/react/24/outline';
import { getSocket } from '@/lib/socketClient';
import type { TagOption } from '@/components/ui/TagMultiCombobox';
import DeviceEditModal from './DeviceEditModal';

export type DeviceRow = {
  inventoryNumber: string;

  name: string;
  manufacturer: string;
  model: string;
  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[] | null;

  updatedAt: string;
};

export type DeviceDetail = DeviceRow & {
  createdAt?: string;
};

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

const columns: TableColumn<DeviceRow>[] = [
  {
    key: 'inventoryNumber',
    header: 'Inventar-Nr.',
    sortable: true,
    canHide: false,
    headerClassName: 'min-w-32',
  },
  {
    key: 'name',
    header: 'Bezeichnung',
    sortable: true,
    canHide: true,
    headerClassName: 'min-w-48',
    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() {
  // Liste aus der API
  const [devices, setDevices] = useState<DeviceRow[]>([]);
  const [listLoading, setListLoading] = useState(false);
  const [listError, setListError] = useState<string | null>(null);

  // welches Gerät ist gerade im Edit-Modal geöffnet?
  const [editInventoryNumber, setEditInventoryNumber] = useState<string | null>(
    null,
  );

  // Alle bekannten Tags (kannst du später auch aus eigener /api/tags laden)
  const [allTags, setAllTags] = useState<TagOption[]>([]);

  /* ───────── Geräte-Liste laden (auch für "live"-Updates) ───────── */

  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 DeviceRow[];
      setDevices(data);

      // 🔹 alle Tags aus der Liste ableiten
      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);
    }
  }, []);

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

  // ✅ Echte Live-Updates via Socket.IO
  useEffect(() => {
    const socket = getSocket();

    const handleUpdated = (payload: DeviceRow) => {
      setDevices((prev) => {
        const exists = prev.some(
          (d) => d.inventoryNumber === payload.inventoryNumber,
        );
        if (!exists) {
          // falls du Updates & Creates über das gleiche Event schickst
          return [...prev, payload];
        }
        return prev.map((d) =>
          d.inventoryNumber === payload.inventoryNumber ? payload : d,
        );
      });
    };

    const handleCreated = (payload: DeviceRow) => {
      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-Modal Trigger ───────── */

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

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

  /* ───────── 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>

        <button
          type="button"
          className="inline-flex items-center rounded-md bg-indigo-600 px-3.5 py-2.5 text-sm font-semibold text-white shadow-xs hover:bg-indigo-500 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600 dark:bg-indigo-500 dark:hover:bg-indigo-400 dark:focus-visible:outline-indigo-500"
        >
          Neues Gerät anlegen
        </button>
      </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<DeviceRow>
          data={devices}
          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={() => console.log('Details', 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={() =>
                    console.log('Löschen', 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: () =>
                            console.log('Details', row.inventoryNumber),
                        },
                        {
                          label: 'Bearbeiten',
                          icon: <PencilIcon className="size-4" />,
                          onClick: () => handleEdit(row.inventoryNumber),
                        },
                        {
                          label: 'Löschen',
                          icon: <TrashIcon className="size-4" />,
                          tone: 'danger',
                          onClick: () =>
                            console.log('Löschen', row.inventoryNumber),
                        },
                      ],
                    },
                  ]}
                />
              </div>
            </div>
          )}
        />
      </div>

      {/* Edit-/Details-Modal */}
      <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,
            ),
          );
        }}
      />
    </>
  );
}
