// app/(app)/users/UsersTablesClient.tsx

'use client';

import {
  useMemo,
  useState,
  useTransition,
  useCallback,
} from 'react';
import { useRouter } from 'next/navigation';
import { useSession } from 'next-auth/react';
import Table, { type TableColumn } from '@/components/ui/Table';
import Tabs, { type TabItem } from '@/components/ui/Tabs';
import UserAvatar from '@/components/ui/UserAvatar';
import Button from '@/components/ui/Button';
import Badge from '@/components/ui/Badge';
import type { User } from '@/generated/prisma/client';
import type {
  GroupWithUsers,
  SimpleGroup,
  UserWithAvatar,
} from './types';
import AssignGroupForm from './AssignGroupForm';
import UserRowActions from './UserRowActions';
import EditUserModal from './EditUserModal';
import ChangePasswordModal from './ChangePasswordModal';
import { evaluatePassword } from './passwordUtils';
import Card from '@/components/ui/Card';

type Props = {
  groups: GroupWithUsers[];
  ungrouped: User[];
  allGroups: SimpleGroup[];
};

type GroupCluster = {
  baseKey: string; // z.B. "Gruppe" oder "Test"
  label: string; // Anzeige-Label im Haupt-Tab
  groups: GroupWithUsers[]; // alle Gruppen wie "Gruppe1", "Gruppe1-Test", "Test1", "Test2" ...
  totalCount: number; // Summe aller User in diesem Cluster
};

/* ───────── Helper: Cluster-Key aus Gruppennamen ───────── */
function getBaseGroupName(name: string): string {
  const trimmed = name.trim();
  if (!trimmed) return '';

  const beforeDash = trimmed.split('-')[0].trim() || trimmed;
  const withoutDigits = beforeDash.replace(/\d+$/, '').trim();

  return withoutDigits || beforeDash;
}

/* ───────── Haupt-Client ───────── */

export default function UsersTablesClient({
  groups,
  ungrouped,
  allGroups,
}: Props) {
  const router = useRouter();
  const { data: session } = useSession();

  const [deleteGroupPending, startDeleteGroupTransition] =
    useTransition();

  // 🔹 Ausgewählte Benutzer in der Tabelle
  const [selectedUserIds, setSelectedUserIds] = useState<string[]>([]);

  // 🔹 Bulk-Delete-Transition
  const [bulkDeleting, startBulkDeleteTransition] = useTransition();

  // 🔹 Edit-Dialog (global, nicht pro Zeile)
  const [editUser, setEditUser] = useState<UserWithAvatar | null>(null);
  const [editArbeitsname, setEditArbeitsname] = useState('');
  const [editFirstName, setEditFirstName] = useState('');
  const [editLastName, setEditLastName] = useState('');
  const [savingEdit, startEditTransition] = useTransition();

  const openEditForUser = useCallback((user: UserWithAvatar) => {
    setEditUser(user);
    setEditArbeitsname(user.arbeitsname ?? '');
    setEditFirstName(user.firstName ?? '');
    setEditLastName(user.lastName ?? '');
  }, []);

  function handleSaveEdit() {
    if (!editUser) return;

    startEditTransition(async () => {
      try {
        const res = await fetch(
          `/api/users/${encodeURIComponent(editUser.nwkennung)}`,
          {
            method: 'PATCH',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
              arbeitsname: editArbeitsname,
              firstName: editFirstName,
              lastName: editLastName,
            }),
          },
        );

        if (!res.ok) {
          console.error(
            'Fehler beim Aktualisieren der User',
            await res.text(),
          );
          return;
        }

        setEditUser(null);
        router.refresh();
      } catch (err) {
        console.error('Fehler beim Aktualisieren der User', err);
      }
    });
  }

  // 🔹 Passwort-Dialog (global)
  const [pwUser, setPwUser] = useState<UserWithAvatar | null>(null);
  const [newPassword, setNewPassword] = useState('');
  const [newPasswordConfirm, setNewPasswordConfirm] = useState('');
  const [pwError, setPwError] = useState<string | null>(null);
  const [savingPw, startPwTransition] = useTransition();

  const openPwForUser = useCallback((user: UserWithAvatar) => {
    setPwUser(user);
    setNewPassword('');
    setNewPasswordConfirm('');
    setPwError(null);
  }, []);

  const pwChecks = useMemo(
    () => evaluatePassword(newPassword),
    [newPassword],
  );

  const passwordsMatch =
    newPassword.length > 0 && newPassword === newPasswordConfirm;

  const canSubmitPw = pwChecks.allOk && passwordsMatch && !savingPw;

  function handleChangePassword() {
    if (!pwUser) return;

    setPwError(null);

    if (!pwChecks.allOk) {
      setPwError(
        'Das Passwort erfüllt noch nicht alle Sicherheitskriterien.',
      );
      return;
    }

    if (!passwordsMatch) {
      setPwError('Die Passwörter stimmen nicht überein.');
      return;
    }

    startPwTransition(async () => {
      try {
        const res = await fetch(
          `/api/users/${encodeURIComponent(pwUser.nwkennung)}/password`,
          {
            method: 'PATCH',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ password: newPassword }),
          },
        );

        if (!res.ok) {
          const data = await res.json().catch(() => null);
          console.error(
            'Fehler beim Ändern des Passworts',
            res.status,
            data,
          );
          setPwError(
            data?.error ??
              'Fehler beim Ändern des Passworts. Details in der Konsole.',
          );
          return;
        }

        setPwUser(null);
        setNewPassword('');
        setNewPasswordConfirm('');
        setPwError(null);

        router.refresh();
        window.alert('Passwort wurde aktualisiert.');
      } catch (err) {
        console.error('Fehler beim Ändern des Passworts', err);
        setPwError('Fehler beim Ändern des Passworts.');
      }
    });
  }

  // 🔹 Single-User-Delete (global, nicht pro Zeile)
  const [deleteUserPending, startDeleteUserTransition] = useTransition();
  const [deletingUserId, setDeletingUserId] = useState<string | null>(
    null,
  );

  function handleDeleteUser(user: UserWithAvatar) {
    const ok = window.confirm(
      `User "${user.arbeitsname || user.firstName || user.lastName}" wirklich löschen?`,
    );
    if (!ok) return;

    setDeletingUserId(user.nwkennung);

    startDeleteUserTransition(async () => {
      try {
        const res = await fetch(
          `/api/users/${encodeURIComponent(user.nwkennung)}`,
          { method: 'DELETE' },
        );

        if (!res.ok) {
          console.error(
            'Fehler beim Löschen der User',
            await res.text(),
          );
          return;
        }

        router.refresh();
      } catch (err) {
        console.error('Fehler beim Löschen der User', err);
      } finally {
        setDeletingUserId(null);
      }
    });
  }

  // User-ID aus der Session – passe das ggf. an dein Session-Objekt an
  const currentUserId =
    (session?.user as any)?.userId ??
    (session?.user as any)?.id ??
    null;

  // Cluster nach Basis-Key bauen
  const { clustersList, clustersByBaseKey } = useMemo(() => {
    const byKey = new Map<string, GroupCluster>();

    for (const g of groups) {
      const baseKey = getBaseGroupName(g.name);
      let cluster = byKey.get(baseKey);

      if (!cluster) {
        cluster = {
          baseKey,
          label: baseKey,
          groups: [],
          totalCount: 0,
        };
        byKey.set(baseKey, cluster);
      }

      cluster.groups.push(g);
      cluster.totalCount += g.users.length;
    }

    for (const cluster of byKey.values()) {
      const root = cluster.baseKey;
      const dashedNames = cluster.groups.map((g) =>
        g.name.split('-')[0].trim(),
      );

      if (dashedNames.includes(root)) {
        cluster.label = root;
      } else {
        const candidates =
          dashedNames.length > 0
            ? dashedNames
            : cluster.groups.map((g) => g.name);

        cluster.label = candidates.reduce(
          (shortest, curr) =>
            curr.length < shortest.length ? curr : shortest,
          candidates[0],
        );
      }
    }

    const list = Array.from(byKey.values()).sort((a, b) =>
      a.label.localeCompare(b.label, 'de'),
    );

    return { clustersList: list, clustersByBaseKey: byKey };
  }, [groups]);

  // Haupt-Tabs: pro Cluster + "Ohne Gruppe"
  const mainTabs: TabItem[] = useMemo(() => {
    const baseTabs: TabItem[] = clustersList.map((cluster) => ({
      id: cluster.baseKey,
      label: cluster.label,
      count: cluster.totalCount,
    }));

    baseTabs.push({
      id: 'ungrouped',
      label: 'Ohne Gruppe',
      count: ungrouped.length,
    });

    return baseTabs;
  }, [clustersList, ungrouped.length]);

  // Aktiver Haupt-Tab (State) + "sicherer" Wert
  const [activeMainTab, setActiveMainTab] = useState<string>(() =>
    mainTabs[0]?.id ? mainTabs[0].id : 'ungrouped',
  );

  const safeActiveMainTab = useMemo(() => {
    if (!mainTabs.length) return 'ungrouped';
    const exists = mainTabs.some((t) => t.id === activeMainTab);
    if (!exists) {
      return mainTabs[0].id;
    }
    return activeMainTab;
  }, [mainTabs, activeMainTab]);

  // Unter-Tabs: pro Cluster z.B. [Alle, Test1, Test2, Test-Test, …]
  const subTabs: TabItem[] = useMemo(() => {
    if (safeActiveMainTab === 'ungrouped') return [];

    const cluster = clustersByBaseKey.get(safeActiveMainTab);
    if (!cluster) return [];

    const items: TabItem[] = [];

    items.push({
      id: '__all',
      label: 'Alle',
      count: cluster.totalCount,
    });

    const sortedGroups = [...cluster.groups].sort((a, b) =>
      a.name.localeCompare(b.name, 'de'),
    );

    for (const g of sortedGroups) {
      items.push({
        id: g.id,
        label: g.name,
        count: g.users.length,
      });
    }

    return items;
  }, [safeActiveMainTab, clustersByBaseKey]);

  // Aktiver Unter-Tab (State) + "sicherer" Wert
  const [activeSubTab, setActiveSubTab] = useState<string>('__all');

  const safeActiveSubTab = useMemo(() => {
    // Wenn "Ohne Gruppe" oder keine Sub-Tabs: immer "__all"
    if (safeActiveMainTab === 'ungrouped' || subTabs.length === 0) {
      return '__all';
    }

    // Wenn der aktuelle Sub-Tab existiert, nutzen
    const exists = subTabs.some((t) => t.id === activeSubTab);
    if (exists) return activeSubTab;

    // Sonst erster Sub-Tab
    return subTabs[0]?.id ?? '__all';
  }, [safeActiveMainTab, subTabs, activeSubTab]);

  // Tabelle: Daten nach aktivem Haupt-Tab + Sub-Tab filtern
  const tableData: UserWithAvatar[] = useMemo(() => {
    let rows: UserWithAvatar[] = [];

    if (safeActiveMainTab === 'ungrouped') {
      rows = ungrouped as UserWithAvatar[];
    } else {
      const cluster = clustersByBaseKey.get(safeActiveMainTab);
      if (!cluster) return [];

      if (safeActiveSubTab === '__all') {
        rows = cluster.groups.flatMap(
          (g) => g.users,
        ) as UserWithAvatar[];
      } else {
        const group = cluster.groups.find(
          (g) => g.id === safeActiveSubTab,
        );
        if (!group) return [];
        rows = group.users as UserWithAvatar[];
      }
    }

    // Standard-Sortierung nach Arbeitsname (auf Kopie arbeiten)
    return [...rows].sort((a, b) => {
      const aName = (a.arbeitsname ?? '').toLocaleLowerCase('de-DE');
      const bName = (b.arbeitsname ?? '').toLocaleLowerCase('de-DE');
      return aName.localeCompare(bName, 'de', {
        sensitivity: 'base',
      });
    });
  }, [
    safeActiveMainTab,
    safeActiveSubTab,
    ungrouped,
    clustersByBaseKey,
  ]);

  // Gruppe löschen (konkrete Untergruppe, nicht der ganze Cluster)
  function handleDeleteActiveGroup() {
    if (safeActiveMainTab === 'ungrouped') return;
    if (safeActiveSubTab === '__all') {
      alert(
        'Bitte zuerst eine konkrete Untergruppe auswählen, bevor du sie löschen kannst.',
      );
      return;
    }

    const group = allGroups.find((g) => g.id === safeActiveSubTab);
    if (!group) return;

    const ok = window.confirm(
      `Gruppe "${group.name}" wirklich löschen?\n\nAlle Benutzer dieser Gruppe werden NICHT gelöscht, aber ihre Gruppen-Zuordnung wird entfernt (sie landen unter "Ohne Gruppe").`,
    );
    if (!ok) return;

    startDeleteGroupTransition(async () => {
      try {
        const res = await fetch(`/api/user-groups/${group.id}`, {
          method: 'DELETE',
        });

        if (!res.ok) {
          console.error(
            'Fehler beim Löschen der Gruppe',
            await res.text(),
          );
          alert('Gruppe konnte nicht gelöscht werden.');
          return;
        }

        router.refresh();
      } catch (err) {
        console.error('Fehler beim Löschen der Gruppe', err);
        alert('Fehler beim Löschen der Gruppe.');
      }
    });
  }

  // Ausgewählte Benutzer löschen
  function handleDeleteSelectedUsers() {
    if (selectedUserIds.length === 0) return;

    const selectedUsers = tableData.filter((u) =>
      selectedUserIds.includes(u.nwkennung),
    );

    const deletableUsers = selectedUsers.filter(
      (u) => !currentUserId || u.nwkennung !== currentUserId,
    );

    if (deletableUsers.length === 0) {
      alert(
        'Die Auswahl enthält nur deinen eigenen Benutzer. Dieser kann nicht gelöscht werden.',
      );
      return;
    }

    const previewNames = deletableUsers
      .slice(0, 5)
      .map(
        (u) =>
          u.arbeitsname ||
          [u.firstName, u.lastName].filter(Boolean).join(' ') ||
          u.nwkennung,
      )
      .join(', ');

    const moreCount = deletableUsers.length - 5;

    const msg =
      `Möchtest du wirklich ${deletableUsers.length} Benutzer löschen?\n\n` +
      previewNames +
      (moreCount > 0 ? ` … und ${moreCount} weitere` : '') +
      `\n\nHinweis: Dein eigener Benutzer wird, falls ausgewählt, nicht gelöscht.`;

    const ok = window.confirm(msg);
    if (!ok) return;

    startBulkDeleteTransition(async () => {
      try {
        for (const u of deletableUsers) {
          const res = await fetch(
            `/api/users/${encodeURIComponent(u.nwkennung)}`,
            { method: 'DELETE' },
          );

          if (!res.ok) {
            console.error(
              'Fehler beim Löschen des Users',
              u.nwkennung,
              await res.text(),
            );
          }
        }

        setSelectedUserIds([]);
        router.refresh();
      } catch (err) {
        console.error('Fehler beim Bulk-Löschen der Benutzer', err);
        alert('Fehler beim Löschen der Benutzer.');
      }
    });
  }

  // ganzen Cluster löschen
  function handleDeleteActiveCluster() {
    if (safeActiveMainTab === 'ungrouped') return;

    const cluster = clustersByBaseKey.get(safeActiveMainTab);
    if (!cluster || cluster.groups.length === 0) return;

    const groupNames = cluster.groups.map((g) => g.name).join(', ');

    const ok = window.confirm(
      `Cluster "${cluster.label}" wirklich löschen?\n\nEs werden alle folgenden Gruppen gelöscht:\n${groupNames}\n\nAlle Benutzer dieser Gruppen werden NICHT gelöscht, aber ihre Gruppen-Zuordnung wird entfernt (sie landen unter "Ohne Gruppe").`,
    );
    if (!ok) return;

    startDeleteGroupTransition(async () => {
      try {
        for (const g of cluster.groups) {
          const res = await fetch(`/api/user-groups/${g.id}`, {
            method: 'DELETE',
          });

          if (!res.ok) {
            console.error(
              'Fehler beim Löschen der Gruppe',
              g.name,
              await res.text(),
            );
          }
        }

        router.refresh();
      } catch (err) {
        console.error('Fehler beim Löschen des Clusters', err);
        alert('Fehler beim Löschen des Clusters.');
      }
    });
  }

  // Columns inkl. Gruppen-Spalte
    const userColumns: TableColumn<UserWithAvatar>[] = useMemo(
    () => [
      {
        key: 'avatarUrl',
        header: '',
        sortable: false,
        headerClassName: 'w-10',
        cellClassName: 'w-10',
        render: (row) => (
          <UserAvatar
            name={row.arbeitsname as any}
            avatarUrl={row.avatarUrl}
            size="md"
          />
        ),
      },
      {
        key: 'arbeitsname',
        header: 'Arbeitsname',
        sortable: true,
        render: (row) => {
          const isCurrent =
            !!currentUserId && row.nwkennung === currentUserId;

          return (
            <div className="flex items-center gap-2">
              <span>{row.arbeitsname}</span>
              {isCurrent && (
                <Badge size="sm" tone="green" variant="flat">
                  Du
                </Badge>
              )}
            </div>
          );
        },
      },
      {
        key: 'lastName',
        header: 'Nachname',
        sortable: true,
      },
      {
        key: 'firstName',
        header: 'Vorname',
        sortable: true,
      },

      // 🔹 NEUE SPALTE: Darf Geräte bearbeiten
      {
        key: 'canEditDevices',
        header: 'Geräte bearbeiten',
        sortable: false,
        headerClassName: 'w-40',
        cellClassName: 'w-40',
        render: (row) => {
          const group = allGroups.find((g) => g.id === row.groupId);
          const canEdit = !!group?.canEditDevices;

          if (!row.groupId) {
            return (
              <span className="text-xs text-gray-400 dark:text-gray-500">
                Keine Gruppe
              </span>
            );
          }

          return (
            <span
              className={
                'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium ' +
                (canEdit
                  ? 'bg-green-50 text-green-700 dark:bg-green-500/10 dark:text-green-300'
                  : 'bg-gray-100 text-gray-600 dark:bg-gray-800 dark:text-gray-300')
              }
            >
              {canEdit ? 'Ja' : 'Nein'}
            </span>
          );
        },
      },

      {
        key: 'groupId',
        header: 'Gruppe',
        sortable: false,
        render: (row) => (
          <AssignGroupForm
            user={row}
            defaultGroupId={row.groupId ?? null}
            allGroups={allGroups}
          />
        ),
      },
    ],
    [allGroups, currentUserId],
  );

  const canDeleteCurrentGroup =
    safeActiveMainTab !== 'ungrouped' &&
    safeActiveSubTab !== '__all' &&
    subTabs.length > 0;

  const canDeleteCurrentCluster =
    safeActiveMainTab !== 'ungrouped' &&
    !!clustersByBaseKey.get(safeActiveMainTab)?.groups.length;

  const handleSelectionChange = useCallback((rows: unknown[]) => {
    const typed = rows as UserWithAvatar[];
    const nextIds = typed.map((r) => r.nwkennung);

    setSelectedUserIds((prev) => {
      if (
        prev.length === nextIds.length &&
        prev.every((id, idx) => id === nextIds[idx])
      ) {
        return prev;
      }
      return nextIds;
    });
  }, []);

  return (
    <div className="space-y-4">
      {/* 1. Tab-Reihe: Hauptgruppen (Cluster) + Cluster-Löschen-Button */}
      <div className="mt-2 space-y-2">
        <div className="flex items-center justify-between gap-3">
          <Tabs
            tabs={mainTabs}
            variant='pillsBrand'
            value={safeActiveMainTab}
            onChange={setActiveMainTab}
            ariaLabel="Usergruppen (Cluster) auswählen"
          />

          {canDeleteCurrentCluster && (
            <Button
              type="button"
              variant="soft"
              tone="rose"
              size="lg"
              onClick={handleDeleteActiveCluster}
              disabled={deleteGroupPending}
            >
              {deleteGroupPending
                ? 'Lösche Cluster …'
                : 'Cluster löschen'}
            </Button>
          )}
        </div>

        {/* 2. Tab-Reihe: Untergruppen + Untergruppe-löschen-Button */}
        {safeActiveMainTab !== 'ungrouped' && subTabs.length > 0 && (
          <div className="flex items-center justify-between gap-3">
            <Tabs
              tabs={subTabs}
              variant='pillsBrand'
              value={safeActiveSubTab}
              onChange={setActiveSubTab}
              ariaLabel="Untergruppen auswählen"
            />

            {canDeleteCurrentGroup && (
              <Button
                type="button"
                variant="soft"
                tone="rose"
                size="lg"
                onClick={handleDeleteActiveGroup}
                disabled={deleteGroupPending}
              >
                {deleteGroupPending
                  ? 'Lösche Gruppe …'
                  : 'Untergruppe löschen'}
              </Button>
            )}
          </div>
        )}
      </div>

      <div className="relative">
        <Table<UserWithAvatar>
          data={tableData}
          columns={userColumns}
          getRowId={(row) => row.nwkennung}
          actionsHeader="Aktionen"
          selectable
          onSelectionChange={handleSelectionChange}
          renderActions={(row) => (
            <UserRowActions
              user={row}
              currentUserId={currentUserId}
              onEdit={() => openEditForUser(row)}
              onChangePassword={() => openPwForUser(row)}
              onDelete={() => handleDeleteUser(row)}
              isDeleting={
                deleteUserPending && deletingUserId === row.nwkennung
              }
              isSavingPassword={
                savingPw && pwUser?.nwkennung === row.nwkennung
              }
            />
          )}
          defaultSortKey="arbeitsname"
          defaultSortDirection="asc"
        />

        {/* Floating Actions in Card, unten mittig über der Tabelle */}
        {selectedUserIds.length > 0 && (
          <div className="pointer-events-none fixed inset-x-0 bottom-4 z-40 flex justify-center">
            <Card className="pointer-events-auto shadow-lg bg-white dark:bg-gray-900">
              <div className="flex items-center gap-3 px-4 py-3">
                <span className="text-sm text-gray-700 dark:text-gray-200">
                  {selectedUserIds.length === 1
                    ? '1 Benutzer ausgewählt'
                    : `${selectedUserIds.length} Benutzer ausgewählt`}
                </span>

                <Button
                  type="button"
                  variant="soft"
                  tone="rose"
                  size="sm"
                  onClick={handleDeleteSelectedUsers}
                  disabled={bulkDeleting}
                >
                  {bulkDeleting
                    ? 'Lösche ausgewählte …'
                    : 'Ausgewählte Benutzer löschen'}
                </Button>
              </div>
            </Card>
          </div>
        )}
      </div>

      {/* Edit-Modal */}
      {editUser && (
        <EditUserModal
          open={!!editUser}
          user={editUser}
          arbeitsname={editArbeitsname}
          firstName={editFirstName}
          lastName={editLastName}
          saving={savingEdit}
          onArbeitsnameChange={setEditArbeitsname}
          onFirstNameChange={setEditFirstName}
          onLastNameChange={setEditLastName}
          onClose={() => setEditUser(null)}
          onSubmit={handleSaveEdit}
          canEditDevices={(() => {
            const group = allGroups.find((g) => g.id === editUser.groupId);
            return !!group?.canEditDevices;
          })()}
        />
      )}

      {/* Passwort-Modal */}
      {pwUser && (
        <ChangePasswordModal
          open={!!pwUser}
          user={pwUser}
          newPassword={newPassword}
          newPasswordConfirm={newPasswordConfirm}
          pwChecks={pwChecks}
          pwError={pwError}
          saving={savingPw}
          canSubmitPw={canSubmitPw}
          onNewPasswordChange={(value) => {
            setNewPassword(value);
            setPwError(null);
          }}
          onNewPasswordConfirmChange={(value) => {
            setNewPasswordConfirm(value);
            setPwError(null);
          }}
          onClose={() => setPwUser(null)}
          onSubmit={handleChangePassword}
        />
      )}
    </div>
  );
}
