import { DataGrid, SortModel } from '@gouvfr-lasuite/cunningham-react';
import type { InfiniteData } from '@tanstack/react-query';
import { useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';

import { Box, Tag, Text, TextErrors } from '@/components';
import { useAuthStore } from '@/core/auth';
import { MailDomain } from '@/features/mail-domains/domains';
import {
  MailDomainMailbox,
  ViewMailbox,
} from '@/features/mail-domains/mailboxes/types';

import { useMailboxesInfinite } from '../../api/useMailboxesInfinite';

import { PanelActions } from './PanelActions';

type MailDomainMailboxesResponse = {
  count: number;
  next: string | null;
  previous: string | null;
  results: MailDomainMailbox[];
};

interface MailBoxesListViewProps {
  mailDomain: MailDomain;
  querySearch: string;
}

type SortModelItem = {
  field: string;
  sort: 'asc' | 'desc' | null;
};

function formatSortModel(sortModel: SortModelItem) {
  return sortModel.sort === 'desc' ? `-${sortModel.field}` : sortModel.field;
}

export function MailBoxesListView({
  mailDomain,
  querySearch,
}: MailBoxesListViewProps) {
  const { t } = useTranslation();
  const { userData } = useAuthStore();

  const [sortModel, setSortModel] = useState<SortModel>([
    {
      field: 'local_part',
      sort: 'desc',
    },
  ]);

  const ordering = sortModel.length ? formatSortModel(sortModel[0]) : undefined;
  const {
    data,
    isLoading,
    error,
    fetchNextPage,
    hasNextPage,
    isFetchingNextPage,
  } = useMailboxesInfinite({
    mailDomainSlug: mailDomain.slug,
    ordering,
  }) as {
    data: InfiniteData<MailDomainMailboxesResponse, number> | undefined;
    isLoading: boolean;
    error: { cause?: string[] };
    fetchNextPage: () => void;
    hasNextPage: boolean | undefined;
    isFetchingNextPage: boolean;
  };

  const mailboxes: ViewMailbox[] = useMemo(() => {
    if (!mailDomain || !data?.pages?.length) {
      return [];
    }

    const capitalize = (value: string) =>
      value ? value.charAt(0).toUpperCase() + value.slice(1) : value;

    return data.pages.flatMap((page) =>
      page.results.map((mailbox: MailDomainMailbox) => {
        const email = `${mailbox.local_part}@${mailDomain.name}`;
        const isCurrentUser = userData?.email === email;

        return {
          id: mailbox.id,
          email,
          name: `${capitalize(mailbox.last_name)} ${capitalize(
            mailbox.first_name,
          )}`,
          first_name: mailbox.first_name,
          last_name: mailbox.last_name,
          local_part: mailbox.local_part,
          secondary_email: mailbox.secondary_email,
          status: mailbox.status,
          mailbox,
          isCurrentUser,
        };
      }),
    );
  }, [data, mailDomain, userData?.email]);

  const filteredMailboxes = useMemo(() => {
    if (!querySearch) {
      return mailboxes;
    }
    const lowerCaseSearch = querySearch.toLowerCase();
    return mailboxes.filter((mailbox) =>
      mailbox.email.toLowerCase().includes(lowerCaseSearch),
    );
  }, [querySearch, mailboxes]);

  const loadMoreRef = useRef<HTMLDivElement | null>(null);

  useEffect(() => {
    if (!hasNextPage) {
      return;
    }
    const ref = loadMoreRef.current;
    const observer = new IntersectionObserver(
      (entries) => {
        if (entries[0].isIntersecting && hasNextPage && !isFetchingNextPage) {
          fetchNextPage();
        }
      },
      { threshold: 1 },
    );
    if (ref) {
      observer.observe(ref);
    }
    return () => {
      if (ref) {
        observer.unobserve(ref);
      }
    };
  }, [hasNextPage, isFetchingNextPage, fetchNextPage]);

  return (
    <div>
      {error && <TextErrors causes={error.cause ?? []} />}

      {!filteredMailboxes.length && (
        <Box $align="center" $margin={{ top: 'base', bottom: 'base' }}>
          <Text $size="small">
            {t('No mail box was created with this mail domain.')}
          </Text>
        </Box>
      )}

      {filteredMailboxes && filteredMailboxes.length ? (
        <>
          <DataGrid
            aria-label="listbox"
            rows={filteredMailboxes}
            columns={[
              {
                field: 'local_part',
                headerName: `${t('Address')} • ${filteredMailboxes.length}`,
                renderCell: ({ row }) => (
                  <Text
                    $weight={row.isCurrentUser ? '600' : '400'}
                    $theme={row.isCurrentUser ? 'primary' : 'gray'}
                  >
                    {row.email}
                  </Text>
                ),
              },
              {
                field: 'last_name',
                headerName: t('User'),
                renderCell: ({ row }) => (
                  <Text
                    $weight="500"
                    $theme="gray"
                    $css="text-transform: capitalize;"
                  >
                    {row.name}
                  </Text>
                ),
              },
              {
                field: 'status',
                id: 'status',
                headerName: t('Status'),
                renderCell({ row }) {
                  return (
                    <Box $direction="row" $align="center">
                      <Tag
                        showTooltip={true}
                        status={row.status}
                        tooltipType="mail"
                      ></Tag>
                    </Box>
                  );
                },
              },
              {
                id: 'actions',
                renderCell: ({ row }) => (
                  <PanelActions mailDomain={mailDomain} mailbox={row} />
                ),
              },
            ]}
            isLoading={isLoading}
            sortModel={sortModel}
            onSortModelChange={setSortModel}
          />

          {isFetchingNextPage && <div>{t('Loading more...')}</div>}
        </>
      ) : null}
      <div ref={loadMoreRef} style={{ height: 0 }} />
    </div>
  );
}
