import { useMutation, useSuspenseQuery } from '@tanstack/react-query';
import {
  createColumnHelper,
  getCoreRowModel,
  getSortedRowModel,
  useReactTable,
} from '@tanstack/react-table';
import { useMemo } from 'react';
import { m } from '../../paraglide/messages';
import api from '../../shared/api/api';
import type { OpenIdClient } from '../../shared/api/types';
import { Badge } from '../../shared/defguard-ui/components/Badge/Badge';
import { Button } from '../../shared/defguard-ui/components/Button/Button';
import type { ButtonProps } from '../../shared/defguard-ui/components/Button/types';
import { EmptyStateFlexible } from '../../shared/defguard-ui/components/EmptyStateFlexible/EmptyStateFlexible';
import type { MenuItemsGroup } from '../../shared/defguard-ui/components/Menu/types';
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 { useClipboard } from '../../shared/defguard-ui/hooks/useClipboard';
import { Snackbar } from '../../shared/defguard-ui/providers/snackbar/snackbar';
import { openModal } from '../../shared/hooks/modalControls/modalsSubjects';
import { ModalName } from '../../shared/hooks/modalControls/modalTypes';
import { getOpenIdClientQueryOptions } from '../../shared/query';

type RowData = OpenIdClient;

const columnHelper = createColumnHelper<RowData>();

export const OpenIdClientTable = () => {
  const { data } = useSuspenseQuery(getOpenIdClientQueryOptions);

  const reservedNames = useMemo(
    () => data.map((c) => c.name.toLowerCase().replaceAll(' ', '')),
    [data],
  );

  const { writeToClipboard } = useClipboard();

  const { mutate: toggleClient } = useMutation({
    mutationFn: api.openIdClient.changeOpenIdClientState,
    meta: {
      invalidate: ['oauth'],
    },
  });

  const addButtonProps = useMemo(
    (): ButtonProps => ({
      text: m.openid_add_application(),
      iconLeft: 'openid',
      testId: 'add-new-app',
      onClick: () => {
        openModal(ModalName.CEOpenIdClient, {
          reservedNames,
        });
      },
    }),
    [reservedNames],
  );

  const columns = useMemo(
    () => [
      columnHelper.accessor('name', {
        header: m.openid_table_header_app_name(),
        enableSorting: true,
        sortingFn: 'text',
        size: 300,
        minSize: 300,
        meta: {
          flex: true,
        },
        cell: (info) => (
          <TableCell>
            <span>{info.getValue()}</span>
          </TableCell>
        ),
      }),
      columnHelper.accessor('enabled', {
        header: m.col_status(),
        minSize: 125,
        cell: (info) => (
          <TableCell>
            {info.getValue() ? (
              <Badge variant="success" text={m.state_enabled()} />
            ) : (
              <Badge variant="critical" text={m.state_disabled()} />
            )}
          </TableCell>
        ),
      }),
      columnHelper.display({
        id: 'edit',
        header: '',
        size: tableEditColumnSize,
        cell: (info) => {
          const row = info.row.original;
          const menuItems: MenuItemsGroup[] = [
            {
              items: [
                {
                  text: m.controls_edit(),
                  icon: 'edit',
                  onClick: () => {
                    openModal(ModalName.CEOpenIdClient, {
                      reservedNames,
                      openIdClient: row,
                    });
                  },
                },
                {
                  icon: 'activity-notes',
                  text: m.openid_edit_copy_id(),
                  testId: 'copy-id',
                  onClick: () => {
                    writeToClipboard(row.client_id);
                  },
                },
                {
                  icon: 'copy',
                  text: m.openid_edit_copy_secret(),
                  testId: 'copy-secret',
                  onClick: () => {
                    writeToClipboard(row.client_secret);
                  },
                },
                {
                  icon: row.enabled ? 'disabled' : 'check-circle',
                  text: row.enabled ? m.controls_disable() : m.controls_enable(),
                  onClick: () => {
                    toggleClient({
                      client_id: row.client_id,
                      enabled: !row.enabled,
                    });
                  },
                },
              ],
            },
            {
              items: [
                {
                  text: m.controls_delete(),
                  icon: 'delete',
                  variant: 'danger',
                  onClick: () => {
                    openModal(ModalName.ConfirmAction, {
                      title: m.modal_delete_openid_client_title(),
                      contentMd: m.modal_delete_openid_client_body(),
                      actionPromise: () =>
                        api.openIdClient.deleteOpenIdClient(row.client_id),
                      invalidateKeys: [['oauth']],
                      submitProps: { text: m.controls_delete(), variant: 'critical' },
                      onSuccess: () => Snackbar.default(m.openid_delete_success()),
                      onError: () => Snackbar.error(m.openid_delete_failed()),
                    });
                  },
                },
              ],
            },
          ];
          return <TableEditCell menuItems={menuItems} />;
        },
      }),
    ],
    [reservedNames, writeToClipboard, toggleClient],
  );

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

  return (
    <>
      {data.length > 0 && (
        <>
          <TableTop text={m.openid_table_top_title()}>
            <Button {...addButtonProps} />
          </TableTop>
          <TableBody table={table} />
        </>
      )}
      {data.length === 0 && (
        <EmptyStateFlexible
          icon="openid"
          title={m.openid_empty_title()}
          subtitle={m.openid_empty_subtitle()}
          primaryAction={addButtonProps}
        />
      )}
    </>
  );
};
