import { useCallback, useEffect } from 'react';

import { FormattedMessage } from 'react-intl';

import { useHistory } from 'react-router';

import { List as ImmutableList } from 'immutable';

import { fetchEndorsedAccounts } from '@/mastodon/actions/accounts';
import { AccountHeader } from '@/mastodon/components/account_header';
import { AccountListItem } from '@/mastodon/components/account_list_item';
import { Column } from '@/mastodon/components/column';
import { ColumnBackButton } from '@/mastodon/components/column/back_button';
import { LoadingIndicator } from '@/mastodon/components/loading_indicator';
import { RemoteHint } from '@/mastodon/components/remote_hint';
import {
  Article,
  ItemList,
  Scrollable,
} from '@/mastodon/components/scrollable_list/components';
import type { TruncatedListItemInfo } from '@/mastodon/components/truncated_list';
import { TruncatedListItems } from '@/mastodon/components/truncated_list';
import { BundleColumnError } from '@/mastodon/features/ui/components/bundle_column_error';
import { useAccount } from '@/mastodon/hooks/useAccount';
import { useAccountId } from '@/mastodon/hooks/useAccountId';
import { useAccountVisibility } from '@/mastodon/hooks/useAccountVisibility';
import { me } from '@/mastodon/initial_state';
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
import AddIcon from '@/material-icons/400-24px/add.svg?react';

import { CollectionListItem } from '../collections/components/collection_list_item';
import { useCollectionsCreatedBy } from '../collections/overview/created_by_account';

import { EmptyMessage } from './components/empty_message';
import { Subheading, SubheadingLink } from './components/subheading';

const AccountFeatured: React.FC<{ multiColumn: boolean }> = ({
  multiColumn,
}) => {
  const accountId = useAccountId();
  const account = useAccount(accountId);
  const { suspended, blockedBy, hidden } = useAccountVisibility(accountId);
  const forceEmptyState = suspended || blockedBy || hidden;
  const isOwnProfile = accountId === me;

  const dispatch = useAppDispatch();

  const history = useHistory();
  useEffect(() => {
    if (account && !account.show_featured) {
      history.push(`/@${account.acct}`);
    }
  }, [account, history]);

  useEffect(() => {
    if (accountId) {
      void dispatch(fetchEndorsedAccounts({ accountId }));
    }
  }, [accountId, dispatch]);

  const featuredAccountIds = useAppSelector(
    (state) =>
      state.user_lists.getIn(
        ['featured_accounts', accountId, 'items'],
        ImmutableList(),
      ) as ImmutableList<string>,
  );
  const { collections, status: collectionsLoadStatus } =
    useCollectionsCreatedBy(accountId);

  const { listedCollections = [], unlistedCollections = [] } = Object.groupBy(
    collections,
    (item) => (item.discoverable ? 'listedCollections' : 'unlistedCollections'),
  );

  const renderListItem = useCallback(
    ({
      item,
      index,
      totalListLength,
      isLastElement,
    }: TruncatedListItemInfo<(typeof listedCollections)[number]>) => (
      <CollectionListItem
        key={item.id}
        collection={item}
        withoutBorder={isLastElement}
        withAuthorHandle={false}
        positionInList={index}
        listSize={totalListLength}
      />
    ),
    [],
  );

  const hasCollections =
    collectionsLoadStatus === 'idle' && listedCollections.length > 0;

  const hasFeaturedAccounts = !featuredAccountIds.isEmpty();

  const isLoading = !accountId || collectionsLoadStatus !== 'idle';

  if (accountId === null) {
    return <BundleColumnError multiColumn={multiColumn} errorType='routing' />;
  }

  if (isLoading) {
    return (
      <AccountFeaturedWrapper accountId={accountId}>
        <div className='scrollable__append'>
          <LoadingIndicator />
        </div>
      </AccountFeaturedWrapper>
    );
  }

  if (!hasFeaturedAccounts && !hasCollections) {
    return (
      <AccountFeaturedWrapper accountId={accountId}>
        <EmptyMessage
          blockedBy={blockedBy}
          hidden={hidden}
          suspended={suspended}
          accountId={accountId}
        />
        <RemoteHint accountId={accountId} />
      </AccountFeaturedWrapper>
    );
  }

  return (
    <Column>
      <ColumnBackButton />

      <Scrollable>
        {accountId && (
          <AccountHeader accountId={accountId} hideTabs={forceEmptyState} />
        )}
        {!featuredAccountIds.isEmpty() && (
          <>
            <Subheading as='h2'>
              <FormattedMessage
                id='account.featured.accounts'
                defaultMessage='Profiles'
              />
            </Subheading>
            <ItemList>
              {featuredAccountIds.map((featuredAccountId, index) => (
                <Article
                  focusable
                  key={featuredAccountId}
                  aria-posinset={index + 1}
                  aria-setsize={featuredAccountIds.size}
                >
                  <AccountListItem accountId={featuredAccountId} />
                </Article>
              ))}
            </ItemList>
          </>
        )}
        <Subheading as='header'>
          <h2>
            <FormattedMessage
              id='account.featured.collections'
              defaultMessage='Collections'
            />
          </h2>
          {isOwnProfile && (
            <SubheadingLink to='/collections/new' icon={AddIcon}>
              <FormattedMessage
                id='account.featured.new_collection'
                defaultMessage='New collection'
              />
            </SubheadingLink>
          )}
        </Subheading>
        {hasCollections ? (
          <ItemList>
            <TruncatedListItems
              visibleItems={listedCollections}
              truncatedItems={isOwnProfile ? unlistedCollections : []}
              toggleButton={{
                title: (
                  <FormattedMessage
                    id='collections.unlisted_collections_with_count'
                    defaultMessage='Unlisted collections ({count})'
                    values={{ count: unlistedCollections.length }}
                  />
                ),
                subtitle: (
                  <FormattedMessage
                    id='collections.unlisted_collections_description'
                    defaultMessage='These don’t appear on your profile to others. Anyone with the link can discover them.'
                  />
                ),
              }}
              renderListItem={renderListItem}
            />
          </ItemList>
        ) : (
          <EmptyMessage
            withoutAddCollectionButton
            blockedBy={blockedBy}
            hidden={hidden}
            suspended={suspended}
            accountId={accountId}
          />
        )}
        <RemoteHint accountId={accountId} />
      </Scrollable>
    </Column>
  );
};

const AccountFeaturedWrapper = ({
  children,
  accountId,
}: React.PropsWithChildren<{ accountId?: string }>) => {
  return (
    <Column>
      <ColumnBackButton />
      <div className='scrollable scrollable--flex'>
        {accountId && <AccountHeader accountId={accountId} />}
        {children}
      </div>
    </Column>
  );
};

// eslint-disable-next-line import/no-default-export
export default AccountFeatured;
