import {
  createColumnHelper,
  getCoreRowModel,
  getSortedRowModel,
  useReactTable,
} from '@tanstack/react-table';
import { useMemo, useState } from 'react';
import { m } from '../../../../paraglide/messages';
import api from '../../../../shared/api/api';
import type { GroupInfo, NetworkLocation, User } from '../../../../shared/api/types';
import { Badge } from '../../../../shared/defguard-ui/components/Badge/Badge';
import { Button } from '../../../../shared/defguard-ui/components/Button/Button';
import type { MenuItemProps } from '../../../../shared/defguard-ui/components/Menu/types';
import { Search } from '../../../../shared/defguard-ui/components/Search/Search';
import { tableEditColumnSize } from '../../../../shared/defguard-ui/components/table/consts';
import { TableBody } from '../../../../shared/defguard-ui/components/table/TableBody/TableBody';
import { TableCell } from '../../../../shared/defguard-ui/components/table/TableCell/TableCell';
import { TableEditCell } from '../../../../shared/defguard-ui/components/table/TableEditCell/TableEditCell';
import { TableTop } from '../../../../shared/defguard-ui/components/table/TableTop/TableTop';
import { Snackbar } from '../../../../shared/defguard-ui/providers/snackbar/snackbar';
import { openModal } from '../../../../shared/hooks/modalControls/modalsSubjects';
import { ModalName } from '../../../../shared/hooks/modalControls/modalTypes';

type Props = {
  groups: GroupInfo[];
  locations: NetworkLocation[];
  users: User[];
};

type RowData = GroupInfo;

const columnHelper = createColumnHelper<RowData>();

export const GroupsTable = ({ groups, locations, users }: Props) => {
  const [search, setSearch] = useState('');
  const reservedNames = useMemo(() => groups.map((g) => g.name), [groups]);

  const transformedData = useMemo(() => {
    let data = groups;
    if (search.length) {
      data = data.filter((g) => g.name.toLowerCase().includes(search.toLowerCase()));
    }
    return data;
  }, [groups, search]);

  const columns = useMemo(
    () => [
      columnHelper.accessor('name', {
        header: m.groups_col_name(),
        minSize: 250,
        enableSorting: true,
        sortingFn: 'text',
        cell: (info) => (
          <TableCell>
            <span>{info.getValue()}</span>
          </TableCell>
        ),
      }),
      columnHelper.display({
        size: 108,
        id: 'users_count',
        header: m.groups_col_users_count(),
        cell: (info) => {
          const row = info.row.original;
          return (
            <TableCell>
              <span>{row.members.length}</span>
            </TableCell>
          );
        },
      }),
      columnHelper.accessor('is_admin', {
        size: 108,
        header: m.groups_col_type(),
        cell: (info) => (
          <TableCell>
            {info.getValue() ? (
              <Badge variant="success" text={m.groups_type_admin()} />
            ) : (
              <Badge text={m.groups_type_user()} />
            )}
          </TableCell>
        ),
      }),
      columnHelper.accessor('vpn_locations', {
        minSize: 350,
        header: m.groups_col_locations(),
        meta: {
          flex: true,
        },
        cell: (info) => (
          <TableCell>
            <span>{info.getValue().join(', ')}</span>
          </TableCell>
        ),
      }),
      columnHelper.display({
        id: 'edit',
        size: tableEditColumnSize,
        header: '',
        enableResizing: false,
        cell: (info) => {
          const rowData = info.row.original;
          const menuItems: MenuItemProps[] = [
            {
              text: m.controls_edit(),
              icon: 'edit',
              onClick: () => {
                openModal(ModalName.CreateEditGroup, {
                  reservedNames,
                  users: users,
                  groupInfo: rowData,
                });
              },
            },
            {
              text: m.controls_delete(),
              icon: 'delete',
              variant: 'danger',
              onClick: () => {
                const affectedLocations = locations.filter(
                  (location) =>
                    !location.allow_all_groups &&
                    location.allowed_groups.includes(rowData.name),
                );
                const blockedLocations = affectedLocations.filter(
                  (location) => location.allowed_groups.length === 1,
                );
                if (blockedLocations.length > 0) {
                  openModal(ModalName.ConfirmAction, {
                    title: m.modal_delete_group_title(),
                    contentMd: m.modal_delete_group_blocked_body({ name: rowData.name }),
                    actionPromise: () => api.group.deleteGroup(rowData.id),
                    cancelProps: { text: m.controls_close() },
                  });
                  return;
                }
                openModal(ModalName.ConfirmAction, {
                  title: m.modal_delete_group_title(),
                  contentMd:
                    affectedLocations.length > 0
                      ? m.modal_delete_group_affected_locations_body({
                          name: rowData.name,
                        })
                      : m.modal_delete_group_body({ name: rowData.name }),
                  actionPromise: () => api.group.deleteGroup(rowData.id),
                  invalidateKeys: [['group'], ['group-info'], ['network']],
                  submitProps: { text: m.controls_delete(), variant: 'critical' },
                  onSuccess: () => Snackbar.default(m.modal_delete_group_success()),
                  onError: () => Snackbar.error(m.modal_delete_group_error()),
                });
              },
            },
          ];
          return <TableEditCell menuItems={[{ items: menuItems }]} />;
        },
      }),
    ],
    [locations, reservedNames, users],
  );

  const table = useReactTable({
    columns,
    data: transformedData,
    getCoreRowModel: getCoreRowModel(),
    getSortedRowModel: getSortedRowModel(),
    enableSorting: true,
    enableRowSelection: false,
    columnResizeMode: 'onChange',
  });

  return (
    <>
      <TableTop text={m.groups_table_title()}>
        <Search
          initialValue={search}
          onChange={setSearch}
          placeholder={m.groups_search_placeholder()}
        />
        <Button
          iconLeft="add-user"
          text={m.groups_add()}
          testId="add-new-group"
          onClick={() => {
            openModal(ModalName.CreateEditGroup, {
              reservedNames,
              users,
            });
          }}
        />
      </TableTop>
      <TableBody table={table} />
    </>
  );
};
