import { useMemo } from 'react';

import { Trans, t } from '@grafana/i18n';
import {
  Avatar,
  type CellProps,
  type Column,
  type FetchDataFunc,
  Icon,
  InteractiveTable,
  LinkButton,
  Pagination,
  Stack,
  Tag,
  Text,
  TextLink,
  Tooltip,
} from '@grafana/ui';
import { TagBadge } from 'app/core/components/TagFilter/TagBadge';
import { type UserDTO } from 'app/types/user';

import { OrgUnits } from './OrgUnits';

type Cell<T extends keyof UserDTO = keyof UserDTO> = CellProps<UserDTO, UserDTO[T]>;

export interface UsersTableProps {
  users: UserDTO[];
  showPaging?: boolean;
  totalPages: number;
  onChangePage: (page: number) => void;
  currentPage: number;
  fetchData?: FetchDataFunc<UserDTO>;
}

export const UsersTable = ({
  users,
  showPaging,
  totalPages,
  onChangePage,
  currentPage,
  fetchData,
}: UsersTableProps) => {
  const showLicensedRole = useMemo(() => users.some((user) => user.licensedRole), [users]);
  const showBelongsTo = useMemo(() => users.some((user) => user.orgs), [users]);

  const columns: Array<Column<UserDTO>> = useMemo(
    () => [
      {
        id: 'avatarUrl',
        header: '',
        cell: ({ cell: { value } }: Cell<'avatarUrl'>) => value && <Avatar src={value} alt={'User avatar'} />,
      },
      {
        id: 'login',
        header: 'Login',
        cell: ({ row: { original } }: Cell<'login'>) => {
          return (
            <TextLink
              color="primary"
              inline={false}
              href={`/admin/users/edit/${original.uid}`}
              title={t('admin.users-table.columns.title-edit-user', 'Edit user')}
            >
              {original.login}
            </TextLink>
          );
        },
        sortType: 'string',
      },
      {
        id: 'email',
        header: 'Email',
        cell: ({ cell: { value } }: Cell<'email'>) => value,
        sortType: 'string',
      },
      {
        id: 'name',
        header: 'Name',
        cell: ({ cell: { value } }: Cell<'name'>) => value,
        sortType: 'string',
      },
      ...(showBelongsTo
        ? [
            {
              id: 'orgs',
              header: 'Belongs to',
              cell: ({ cell: { value, row } }: Cell<'orgs'>) => {
                return (
                  <Stack alignItems={'center'}>
                    <OrgUnits units={value} icon={'building'} />
                    {row.original.isAdmin && (
                      <Tooltip
                        placement="top"
                        content={t('admin.users-table.columns.content-grafana-admin', 'Grafana Admin')}
                      >
                        <Icon name="shield" />
                      </Tooltip>
                    )}
                  </Stack>
                );
              },
            },
          ]
        : []),
      ...(showLicensedRole
        ? [
            {
              id: 'licensedRole',
              header: 'Licensed role',
              cell: ({ cell: { value } }: Cell<'licensedRole'>) => {
                return value === 'None' ? (
                  <Text color={'disabled'}>
                    <Trans i18nKey="admin.users-table.no-licensed-roles">Not assigned</Trans>
                    <Tooltip
                      placement="top"
                      content={t(
                        'admin.users-table.tooltip-assigned-role',
                        'A licensed role will be assigned when this user signs in'
                      )}
                    >
                      <Icon name="question-circle" style={{ margin: '0 0 4 4' }} />
                    </Tooltip>
                  </Text>
                ) : (
                  value
                );
              },
            },
          ]
        : []),
      {
        id: 'lastSeenAtAge',
        header: 'Last active',
        headerTooltip: {
          content: 'Time since user was seen using Grafana',
          iconName: 'question-circle',
        },
        cell: ({
          cell: { value },
          row: {
            original: { lastSeenAt, created },
          },
        }: Cell<'lastSeenAtAge'>) => {
          // The user has never logged in if lastSeenAt is before its creation date.
          const neverLoggedIn = lastSeenAt && created && new Date(lastSeenAt) < new Date(created);
          return (
            <>
              {value && (
                <>
                  {neverLoggedIn ? (
                    <Text color={'disabled'}>
                      <Trans i18nKey="admin.users-table.last-seen-never">Never</Trans>
                    </Text>
                  ) : (
                    value
                  )}
                </>
              )}
            </>
          );
        },
        sortType: (a, b) => new Date(a.original.lastSeenAt!).getTime() - new Date(b.original.lastSeenAt!).getTime(),
      },
      {
        id: 'authLabels',
        header: 'Origin',
        cell: ({ cell: { value } }: Cell<'authLabels'>) => (
          <>{Array.isArray(value) && value.length > 0 && <TagBadge label={value[0]} removeIcon={false} count={0} />}</>
        ),
      },
      {
        id: 'isProvisioned',
        header: 'Provisioned',
        cell: ({ cell: { value } }: Cell<'isProvisioned'>) => (
          <>{value && <Tag colorIndex={14} name={'Provisioned'} />}</>
        ),
      },
      {
        id: 'isDisabled',
        header: '',
        cell: ({ cell: { value } }: Cell<'isDisabled'>) => <>{value && <Tag colorIndex={9} name={'Disabled'} />}</>,
      },
      {
        id: 'edit',
        header: '',
        cell: ({ row: { original } }: Cell) => {
          return (
            <LinkButton
              variant="secondary"
              size="sm"
              icon="pen"
              href={`admin/users/edit/${original.uid}`}
              aria-label={t('admin.users-table.edit-aria-label', 'Edit user: {{name}}', { name: original.name })}
              tooltip={t('admin.users-table.edit-tooltip', 'Edit user')}
            />
          );
        },
      },
    ],
    [showLicensedRole, showBelongsTo]
  );
  return (
    <Stack direction={'column'} gap={2}>
      <InteractiveTable columns={columns} data={users} getRowId={(user) => String(user.id)} fetchData={fetchData} />
      {showPaging && (
        <Stack justifyContent={'flex-end'}>
          <Pagination numberOfPages={totalPages} currentPage={currentPage} onNavigate={onChangePage} />
        </Stack>
      )}
    </Stack>
  );
};
