// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only

import type { FunctionComponent, JSX } from 'react';
import { useMemo, useState, memo } from 'react';

import { HEADER_CONTACT_NAME_CLASS_NAME } from './BaseConversationListItem.dom.tsx';
import type { ConversationType } from '../../state/ducks/conversations.preload.ts';
import type { BadgeType } from '../../badges/types.std.ts';
import type { LocalizerType, ThemeType } from '../../types/Util.std.ts';
import { ContactName } from '../conversation/ContactName.dom.tsx';
import { About } from '../conversation/About.dom.tsx';
import { ListTile } from '../ListTile.dom.tsx';
import { Avatar, AvatarSize } from '../Avatar.dom.tsx';
import { ContextMenu } from '../ContextMenu.dom.tsx';
import { I18n } from '../I18n.dom.tsx';
import { isSignalConversation } from '../../util/isSignalConversation.dom.ts';
import { isInSystemContacts } from '../../util/isInSystemContacts.std.ts';
import { InContactsIcon } from '../InContactsIcon.dom.tsx';
import { AxoConfirmDialog } from '../../axo/AxoConfirmDialog.dom.tsx';

export type ContactListItemConversationType = Pick<
  ConversationType,
  | 'about'
  | 'acceptedMessageRequest'
  | 'avatarUrl'
  | 'badges'
  | 'color'
  | 'groupId'
  | 'id'
  | 'name'
  | 'isMe'
  | 'phoneNumber'
  | 'profileName'
  | 'systemGivenName'
  | 'systemFamilyName'
  | 'title'
  | 'type'
  | 'username'
  | 'e164'
  | 'serviceId'
>;

type PropsDataType = ContactListItemConversationType & {
  badge: undefined | BadgeType;
};

type PropsHousekeepingType = {
  i18n: LocalizerType;
  onClick?: (id: string) => void;
  onAudioCall?: (id: string) => void;
  onVideoCall?: (id: string) => void;
  onRemove?: (id: string) => void;
  onBlock?: (id: string) => void;
  hasContextMenu: boolean;
  theme: ThemeType;
};

type PropsType = PropsDataType & PropsHousekeepingType;

export const ContactListItem: FunctionComponent<PropsType> = memo(
  function ContactListItem({
    about,
    avatarUrl,
    badge,
    color,
    hasContextMenu,
    i18n,
    id,
    isMe,
    name,
    onClick,
    onAudioCall,
    onVideoCall,
    onRemove,
    onBlock,
    phoneNumber,
    profileName,
    systemGivenName,
    systemFamilyName,
    theme,
    title,
    type,
    serviceId,
  }) {
    const [isConfirmingBlocking, setConfirmingBlocking] = useState(false);
    const [isConfirmingRemoving, setConfirmingRemoving] = useState(false);

    const menuOptions = useMemo(
      () => [
        ...(onClick
          ? [
              {
                icon: 'ContactListItem__context-menu__chat-icon',
                label: i18n('icu:ContactListItem__menu__message'),
                onClick: () => onClick(id),
              },
            ]
          : []),
        ...(!isMe && onAudioCall
          ? [
              {
                icon: 'ContactListItem__context-menu__phone-icon',
                label: i18n('icu:ContactListItem__menu__audio-call'),
                onClick: () => onAudioCall(id),
              },
            ]
          : []),
        ...(!isMe && onVideoCall
          ? [
              {
                icon: 'ContactListItem__context-menu__video-icon',
                label: i18n('icu:ContactListItem__menu__video-call'),
                onClick: () => onVideoCall(id),
              },
            ]
          : []),
        ...(!isMe && onRemove
          ? [
              {
                icon: 'ContactListItem__context-menu__delete-icon',
                label: i18n('icu:ContactListItem__menu__remove'),
                onClick: () => setConfirmingRemoving(true),
              },
            ]
          : []),
        ...(!isMe && onBlock
          ? [
              {
                icon: 'ContactListItem__context-menu__block-icon',
                label: i18n('icu:ContactListItem__menu__block'),
                onClick: () => setConfirmingBlocking(true),
              },
            ]
          : []),
      ],
      [id, i18n, isMe, onClick, onAudioCall, onVideoCall, onRemove, onBlock]
    );

    const headerName = isMe ? (
      <ContactName
        isMe={isMe}
        module={HEADER_CONTACT_NAME_CLASS_NAME}
        title={i18n('icu:noteToSelf')}
      />
    ) : (
      <ContactName
        isSignalConversation={isSignalConversation({ id, serviceId })}
        module={HEADER_CONTACT_NAME_CLASS_NAME}
        title={title}
      />
    );

    const messageText =
      about && !isMe ? <About className="" text={about} /> : undefined;

    let trailing: JSX.Element | undefined;
    if (hasContextMenu) {
      trailing = (
        <ContextMenu
          i18n={i18n}
          menuOptions={menuOptions}
          popperOptions={{ placement: 'bottom-start', strategy: 'absolute' }}
          moduleClassName="ContactListItem__context-menu"
          ariaLabel={i18n('icu:ContactListItem__menu')}
          portalToRoot
        />
      );
    }

    let blockConfirmation: JSX.Element | undefined;
    let removeConfirmation: JSX.Element | undefined;

    if (isConfirmingBlocking) {
      blockConfirmation = (
        <AxoConfirmDialog.Root
          open
          onOpenChange={() => setConfirmingBlocking(false)}
          title={
            <I18n
              i18n={i18n}
              id="icu:MessageRequests--block-direct-confirm-title"
              components={{
                title: <ContactName key="name" title={title} />,
              }}
            />
          }
          description={i18n('icu:MessageRequests--block-direct-confirm-body')}
        >
          <AxoConfirmDialog.Cancel />
          <AxoConfirmDialog.Action
            variant="strong-destructive"
            onClick={() => onBlock?.(id)}
          >
            {i18n('icu:MessageRequests--block')}
          </AxoConfirmDialog.Action>
        </AxoConfirmDialog.Root>
      );
    }

    if (isConfirmingRemoving) {
      if (
        isInSystemContacts({ type, name, systemGivenName, systemFamilyName })
      ) {
        removeConfirmation = (
          <AxoConfirmDialog.Root
            open
            onOpenChange={() => setConfirmingRemoving(false)}
            title={
              <I18n
                i18n={i18n}
                id="icu:ContactListItem__remove-system--title"
                components={{
                  title: <ContactName key="name" title={title} />,
                }}
              />
            }
            description={i18n('icu:ContactListItem__remove-system--body')}
          >
            <AxoConfirmDialog.Cancel>
              {i18n('icu:Confirmation--confirm')}
            </AxoConfirmDialog.Cancel>
          </AxoConfirmDialog.Root>
        );
      } else {
        removeConfirmation = (
          <AxoConfirmDialog.Root
            open
            onOpenChange={() => setConfirmingRemoving(false)}
            title={
              <I18n
                i18n={i18n}
                id="icu:ContactListItem__remove--title"
                components={{
                  title: <ContactName key="name" title={title} />,
                }}
              />
            }
            description={i18n('icu:ContactListItem__remove--body')}
          >
            <AxoConfirmDialog.Cancel />
            <AxoConfirmDialog.Action
              variant="strong-destructive"
              onClick={() => onRemove?.(id)}
            >
              {i18n('icu:ContactListItem__remove--confirm')}
            </AxoConfirmDialog.Action>
          </AxoConfirmDialog.Root>
        );
      }
    }

    return (
      <>
        <ListTile
          moduleClassName="ContactListItem"
          leading={
            <Avatar
              avatarUrl={avatarUrl}
              color={color}
              conversationType={type}
              noteToSelf={isMe}
              i18n={i18n}
              phoneNumber={phoneNumber}
              profileName={profileName}
              title={title}
              size={AvatarSize.THIRTY_TWO}
              // This is here to appease the type checker.
              {...(badge ? { badge, theme } : { badge: undefined })}
            />
          }
          trailing={trailing}
          title={
            <>
              {headerName}
              {isInSystemContacts({
                type,
                name,
                systemGivenName,
                systemFamilyName,
              }) && (
                <span>
                  {' '}
                  <InContactsIcon
                    className="ContactListItem__contact-icon"
                    i18n={i18n}
                  />
                </span>
              )}
            </>
          }
          subtitle={messageText}
          subtitleMaxLines={1}
          onClick={onClick ? () => onClick(id) : undefined}
        />

        {blockConfirmation}
        {removeConfirmation}
      </>
    );
  }
);
