import styled, { CSSProperties } from 'styled-components';

import {
  useIsPrivate,
  useIsPublic,
  useNicknameOrProfileNameOrShortenedPubkey,
} from '../../hooks/useParamSelector';
import { isUsAnySogsFromCache } from '../../session/apis/open_group_api/sogsv3/knownBlindedkeys';
import { PubKey } from '../../session/types';
import { UserUtils } from '../../session/utils';
import { getOurPubKeyStrFromCache } from '../../session/utils/User';
import { openConversationToSpecificMessage } from '../../state/ducks/conversations';
import { MessageResultProps } from '../../types/message';
import { Avatar, AvatarSize } from '../avatar/Avatar';
import { MessageBodyHighlight } from '../basic/MessageBodyHighlight';
import { ContactName } from '../conversation/ContactName';
import { Timestamp } from '../conversation/Timestamp';
import { leftPaneListWidth } from '../leftpane/LeftPane';

const StyledConversationTitleResults = styled.div`
  flex-grow: 1;
  flex-shrink: 1;
  font-size: 14px;
  line-height: 18px;
  overflow-x: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  color: var(--conversation-tab-text-color);
  /* We don't want this to overflow horizontally past the timestamp */
  width: 90px;
`;

const StyledConversationFromUserInGroup = styled(StyledConversationTitleResults)`
  display: inline;
  font-size: 12px;
  line-height: 14px;
  overflow-x: hidden;
  font-weight: 700;
  color: var(--conversation-tab-text-color);
`;

const StyledSearchResults = styled.div`
  padding: var(--margins-sm) var(--margins-md);
  height: var(--contact-row-height);
  max-width: ${leftPaneListWidth}px;

  display: flex;
  flex-direction: row;
  align-items: flex-start;

  cursor: pointer;

  &:hover {
    background-color: var(--conversation-tab-background-hover-color);
  }
`;

const StyledResultText = styled.div`
  flex-grow: 1;
  margin-inline-start: 12px;
  display: inline-flex;
  flex-direction: column;
  align-items: stretch;
  min-width: 0;
`;

const ResultsHeader = styled.div`
  display: flex;
  flex-direction: row;
  align-items: center;
`;

const StyledMessageResultsHeaderName = styled.span`
  font-weight: 300;
`;

const FromName = (props: { source: string; conversationId: string }) => {
  const { conversationId, source } = props;

  const isNoteToSelf = conversationId === getOurPubKeyStrFromCache() && source === conversationId;

  if (isNoteToSelf) {
    return (
      <StyledMessageResultsHeaderName>{window.i18n('noteToSelf')}</StyledMessageResultsHeaderName>
    );
  }

  if (source === getOurPubKeyStrFromCache()) {
    return <StyledMessageResultsHeaderName>{window.i18n('you')}</StyledMessageResultsHeaderName>;
  }

  return (
    <ContactName
      pubkey={conversationId}
      module="module-message-search-result__header__name"
      shouldShowPubkey={false}
    />
  );
};

const ConversationHeader = (props: { source: string; conversationId: string }) => {
  const { source, conversationId } = props;

  const ourKey = getOurPubKeyStrFromCache();

  if (conversationId !== ourKey) {
    return (
      <StyledConversationTitleResults>
        <StyledMessageResultsHeaderName>
          <ContactName pubkey={conversationId} shouldShowPubkey={false} boldProfileName={false} />
        </StyledMessageResultsHeaderName>
      </StyledConversationTitleResults>
    );
  }

  return (
    <StyledConversationTitleResults>
      <FromName source={source} conversationId={conversationId} />
    </StyledConversationTitleResults>
  );
};

const FromUserInGroup = (props: { authorPubkey: string; conversationId: string }) => {
  const { authorPubkey, conversationId } = props;

  const ourKey = getOurPubKeyStrFromCache();
  const isPublic = useIsPublic(conversationId);
  const convoIsPrivate = useIsPrivate(conversationId);
  const authorConvoName = useNicknameOrProfileNameOrShortenedPubkey(authorPubkey);

  if (convoIsPrivate) {
    return null;
  }

  if (
    authorPubkey === ourKey ||
    (isPublic && PubKey.isBlinded(authorPubkey) && isUsAnySogsFromCache(authorPubkey))
  ) {
    return (
      <StyledConversationFromUserInGroup>{window.i18n('you')}: </StyledConversationFromUserInGroup>
    );
  }
  return <StyledConversationFromUserInGroup>{authorConvoName}: </StyledConversationFromUserInGroup>;
};

const AvatarItem = (props: { source: string }) => {
  return <Avatar size={AvatarSize.S} pubkey={props.source} />;
};

const ResultBody = styled.div`
  margin-top: 1px;
  flex-shrink: 1;

  font-size: var(--font-size-sm);

  color: var(--conversation-tab-text-color);

  max-height: 3.6em;

  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
`;

const StyledTimestampContaimer = styled.div`
  flex-shrink: 0;
  margin-inline-start: 6px;

  font-size: var(--font-size-xs);
  line-height: 16px;
  letter-spacing: 0.3px;

  overflow-x: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;

  text-transform: uppercase;

  color: var(--conversation-tab-text-color);
`;

type MessageSearchResultProps = MessageResultProps & { style: CSSProperties };

export const MessageSearchResult = (props: MessageSearchResultProps) => {
  const {
    id,
    conversationId,
    received_at,
    snippet,
    source,
    sent_at,
    serverTimestamp,
    timestamp,
    direction,
    style,
  } = props;

  /** destination is only used for search results (showing the `from:` and `to`)
   *  1.  for messages we sent or synced from another of our devices
   *    - the conversationId for a private convo
   *    - the conversationId for a closed group convo
   *    - the conversationId for an opengroup
   *
   *  2. for messages we received
   *    - our own pubkey for a private conversation
   *    - the conversationID for a closed group
   *    - the conversationID for a public group
   */
  const me = UserUtils.getOurPubKeyStrFromCache();
  const convoIsPrivate = useIsPrivate(conversationId);

  const destination =
    direction === 'incoming' ? conversationId : convoIsPrivate ? me : conversationId;

  if (!source && !destination) {
    return null;
  }

  return (
    <StyledSearchResults
      key={`div-msg-searchresult-${id}`}
      style={style}
      role="button"
      onClick={() => {
        void openConversationToSpecificMessage({
          conversationKey: conversationId,
          messageIdToNavigateTo: id,
          shouldHighlightMessage: true,
        });
      }}
    >
      <AvatarItem source={conversationId} />
      <StyledResultText>
        <ResultsHeader>
          <ConversationHeader source={destination} conversationId={conversationId} />
          <StyledTimestampContaimer>
            <Timestamp
              timestamp={serverTimestamp || timestamp || sent_at || received_at}
              isConversationSearchResult={true}
            />
          </StyledTimestampContaimer>
        </ResultsHeader>
        <ResultBody>
          <FromUserInGroup authorPubkey={source} conversationId={conversationId} />
          <MessageBodyHighlight text={snippet || ''} isGroup={!convoIsPrivate} />
        </ResultBody>
      </StyledResultText>
    </StyledSearchResults>
  );
};
