'use client';

import { useCallback, useEffect, useState } from 'react';
import { useSearchParams, useRouter } from 'next/navigation';
import { useSession } from 'next-auth/react';
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';
import Badge from '@/components/ui/Badge';

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;
};

type PrimaryTab = 'main' | 'accessories' | 'all';
type StatusTab = 'all' | 'loaned' | 'dueToday' | 'overdue';

function formatDate(iso: string | null | undefined) {
  if (!iso) return '–';

  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,
    cellClassName: 'whitespace-normal max-w-xs',
    render: (row) => {
      const tags = row.tags ?? [];

      if (!tags.length) return null;

      return (
        <div className="flex flex-wrap gap-1">
          {tags.map((tag) => (
            <Badge
              key={tag}
              size="sm"
              tone="indigo"
              variant="flat"
              shape="pill"
            >
              {tag}
            </Badge>
          ))}
        </div>
      );
    },
  },
  {
    key: 'updatedAt',
    header: 'Geändert am',
    sortable: true,
    canHide: true,
    render: (row) => formatDate(row.updatedAt),
  },
];

export default function DevicesPage() {
  const { data: session } = useSession();

  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();

  // Nur User in dieser Gruppe sollen Geräte bearbeiten dürfen
  const canEditDevices = Boolean(
    (session?.user as any)?.groupCanEditDevices,
  );

  // 🔹 Oberste Tabs: Hauptgeräte / Zubehör / Alle Geräte
  const [primaryTab, setPrimaryTab] = useState<PrimaryTab>('all');
  // 🔹 Untere Tabs: Leihstatus
  const [statusTab, setStatusTab] = useState<StatusTab>('all');

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

    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;
        }

        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) {
      router.replace('/devices', { scroll: false });
      return;
    }

    const params = new URLSearchParams(searchParams.toString());

    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) => {
      closeDetailModal();
      setEditInventoryNumber(inventoryNumber);
    },
    [closeDetailModal],
  );

  /* ───────── Counter & Filter ───────── */

  // Tag-Grenzen für "heute"
  const todayStart = new Date();
  todayStart.setHours(0, 0, 0, 0);
  const tomorrowStart = new Date(todayStart);
  tomorrowStart.setDate(tomorrowStart.getDate() + 1);

  // Counts für oberste Tabs (immer über alle Geräte)
  const mainCount = devices.filter((d) => !d.parentInventoryNumber).length;
  const accessoriesCount = devices.filter((d) => !!d.parentInventoryNumber).length;
  const allCount = devices.length;

  // Zuerst nach primaryTab filtern → Basis-Menge für Status-Tabs
  const baseDevices = devices.filter((d) => {
    const hasParent = !!d.parentInventoryNumber;
    switch (primaryTab) {
      case 'main':
        return !hasParent;
      case 'accessories':
        return hasParent;
      case 'all':
      default:
        return true;
    }
  });

  // Counts für Status-Tabs (abhängig vom gewählten primaryTab)
  const loanedCount = baseDevices.filter((d) => !!d.loanedTo).length;
  const overdueCount = baseDevices.filter((d) => {
    if (!d.loanedTo || !d.loanedUntil) return false;
    const until = new Date(d.loanedUntil);
    return until < todayStart;
  }).length;
  const dueTodayCount = baseDevices.filter((d) => {
    if (!d.loanedTo || !d.loanedUntil) return false;
    const until = new Date(d.loanedUntil);
    return until >= todayStart && until < tomorrowStart;
  }).length;

  // Endgültige Filterung nach StatusTab
  const filteredDevices = baseDevices.filter((d) => {
    const isLoaned = !!d.loanedTo;
    const until = d.loanedUntil ? new Date(d.loanedUntil) : null;

    switch (statusTab) {
      case 'all':
        return true;
      case 'loaned':
        return isLoaned;
      case 'overdue':
        return (
          isLoaned &&
          !!until &&
          until < todayStart
        );
      case 'dueToday':
        return (
          isLoaned &&
          !!until &&
          until >= todayStart &&
          until < tomorrowStart
        );
      default:
        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: oben Gerätetyp, darunter Leihstatus */}
      <div className="mt-6 space-y-3">
        {/* Oberste Ebene */}
        <Tabs
          variant='pillsBrand'
          tabs={[
            {
              id: 'all',
              label: 'Alle Geräte',
              count: allCount,
            },
            {
              id: 'main',
              label: 'Hauptgeräte',
              count: mainCount,
            },
            {
              id: 'accessories',
              label: 'Zubehör',
              count: accessoriesCount,
            },
          ]}
          value={primaryTab}
          onChange={(id) => setPrimaryTab(id as PrimaryTab)}
          ariaLabel="Geräte-Typ filtern"
        />

        {/* Untere Ebene: Leihstatus (abhängig von primaryTab, Counts basieren auf baseDevices) */}
        <Tabs
          variant='pillsBrand'
          tabs={[
            {
              id: 'all',
              label: 'Alle',
              count: baseDevices.length,
            },
            {
              id: 'loaned',
              label: 'Verliehen',
              count: loanedCount,
            },
            {
              id: 'dueToday',
              label: 'Heute fällig',
              count: dueTodayCount,
            },
            {
              id: 'overdue',
              label: 'Überfällig',
              count: overdueCount,
            },
          ]}
          value={statusTab}
          onChange={(id) => setStatusTab(id as StatusTab)}
          ariaLabel="Leihstatus filtern"
        />
      </div>

      {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=""
          isLoading={listLoading}
          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)}
                />

                {canEditDevices && (
                  <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}
      />
    </>
  );
}
