import React from 'react';
import { Avatar, Box, Button, Icon, Icons, Text } from 'folds';
import classNames from 'classnames';
import { useTranslation } from 'react-i18next';
import { Room } from 'matrix-js-sdk';
import { useSetAtom } from 'jotai';
import { useNavigate } from 'react-router-dom';
import * as css from './styles.css';
import { isNativePlatform } from '../../utils/capacitor';
import { useMatrixClient } from '../../hooks/useMatrixClient';
import { useMediaAuthentication } from '../../hooks/useMediaAuthentication';
import { UserAvatar } from '../../components/user-avatar';
import { getMemberAvatarMxc, getMemberDisplayName } from '../../utils/room';
import { getCanonicalAliasOrRoomId, getMxIdLocalPart, mxcUrlToHttp } from '../../utils/matrix';
import { useSwitchOrStartDmCall } from '../../hooks/useSwitchOrStartDmCall';
import { getDirectRoomPath } from '../../pages/pathUtils';
import { IncomingCall, incomingCallsAtom } from '../../state/incomingCalls';
import { getIncomingCallKey } from '../../utils/rtcNotification';
import { CallPhoneDownIcon, CallPhoneIcon } from './callIcons';

const DECLINE_RETRY_DELAY_MS = 500;

type IncomingCallStripProps = {
  call: IncomingCall;
  room: Room;
};
export function IncomingCallStrip({ call, room }: IncomingCallStripProps) {
  const { t } = useTranslation();
  const mx = useMatrixClient();
  const navigate = useNavigate();
  const useAuthentication = useMediaAuthentication();
  const switchOrStartDmCall = useSwitchOrStartDmCall();
  const setIncoming = useSetAtom(incomingCallsAtom);

  const senderId = call.notifEvent.getSender();
  const displayName =
    (senderId && getMemberDisplayName(room, senderId)) ||
    (senderId && getMxIdLocalPart(senderId)) ||
    senderId ||
    t('Call.unknown_caller');
  // Display names are peer-controlled and spoofable ("Mom", "IT Support"). On a
  // high-trust ring surface, also surface the unspoofable mxid whenever it isn't
  // already what we're showing, so the user can verify who is really calling.
  const senderMxidLabel = senderId && displayName !== senderId ? senderId : undefined;
  const avatarMxc = senderId ? getMemberAvatarMxc(room, senderId) : undefined;
  const avatarUrl = avatarMxc
    ? mxcUrlToHttp(mx, avatarMxc, useAuthentication, 96, 96, 'crop') ?? undefined
    : undefined;

  const callKey = getIncomingCallKey(call.callId, call.roomId);

  const handleAnswer = () => {
    // Mirror the native CallStyle Answer path (usePushNotifications
    // pushNotificationActionPerformed handler): in-app strip Answer is the
    // same semantic action — switch to the call room — so it should not
    // grow the back stack either.
    navigate(getDirectRoomPath(getCanonicalAliasOrRoomId(mx, call.roomId)), { replace: true });
    switchOrStartDmCall(call.roomId)
      .then(() => {
        const evId = call.notifEvent.getId();
        if (evId) {
          setIncoming({ type: 'REMOVE_BY_NOTIF_ID', notifEventId: evId });
          return;
        }
        setIncoming({ type: 'REMOVE', key: callKey });
      })
      .catch((err: unknown) => {
        // eslint-disable-next-line no-console
        console.warn('[call] strip answer switch/start failed', err);
      });
  };

  const handleDecline = async () => {
    setIncoming({ type: 'REMOVE', key: callKey });
    const evId = call.notifEvent.getId();
    if (!evId) return;
    try {
      await mx.sendRtcDecline(call.roomId, evId);
    } catch (err) {
      await new Promise((resolve) => {
        setTimeout(resolve, DECLINE_RETRY_DELAY_MS);
      });
      try {
        await mx.sendRtcDecline(call.roomId, evId);
      } catch (retryErr) {
        // eslint-disable-next-line no-console
        console.warn('[call] sendRtcDecline failed after retry', retryErr);
      }
    }
  };

  const native = isNativePlatform();

  const buttons = (
    <div className={classNames(css.RingButtons, native && css.RingButtonsFull)}>
      <Button
        className={native ? css.RingButtonGrow : undefined}
        variant="Success"
        fill="Solid"
        size={native ? '500' : '400'}
        radii="400"
        onClick={handleAnswer}
        before={<Icon size="200" src={CallPhoneIcon} filled />}
      >
        <Text size={native ? 'B500' : 'B400'} truncate>
          {t('Call.accept')}
        </Text>
      </Button>
      <Button
        className={native ? css.RingButtonGrow : undefined}
        variant="Critical"
        fill="Soft"
        size={native ? '500' : '400'}
        radii="400"
        onClick={handleDecline}
        before={<Icon size="200" src={CallPhoneDownIcon} />}
      >
        <Text size={native ? 'B500' : 'B400'} truncate>
          {t('Call.decline')}
        </Text>
      </Button>
    </div>
  );

  const avatar = (
    <Avatar
      className={classNames(native ? css.CallAvatar : css.CallAvatarCompact, css.CallerPulse)}
    >
      <UserAvatar
        userId={senderId ?? ''}
        src={avatarUrl}
        alt={displayName}
        renderFallback={() => <Icon size="400" src={Icons.User} filled />}
      />
    </Avatar>
  );

  // Native (phone): tall vertical card with a full-width Decline/Accept pair.
  // Web (desktop): the original compact row, same size as before.
  if (native) {
    return (
      <Box className={classNames(css.CallCard, css.CallCardNative)} shrink="No" direction="Column">
        <div className={css.CallCardInner}>
          <div className={css.CallIdentity}>
            {avatar}
            <Box direction="Column" gap="100" alignItems="Center" style={{ maxWidth: '100%' }}>
              <Text size="H4" truncate>
                {displayName}
              </Text>
              {senderMxidLabel && (
                <Text size="T200" priority="300" truncate style={{ maxWidth: '100%' }}>
                  {senderMxidLabel}
                </Text>
              )}
              <span className={css.Eyebrow}>{t('Call.incoming_label')}</span>
            </Box>
          </div>
          {buttons}
        </div>
      </Box>
    );
  }

  return (
    <Box
      className={classNames(css.CallCard, css.CallCardCompact)}
      shrink="No"
      direction="Row"
      alignItems="Center"
    >
      <div className={css.CallIdentityCompact}>
        {avatar}
        <Box grow="Yes" direction="Column" gap="100" style={{ minWidth: 0 }}>
          <Text size="H4" truncate>
            {displayName}
          </Text>
          <Text size="T200" priority="300" truncate>
            {senderMxidLabel ?? t('Call.incoming')}
          </Text>
        </Box>
      </div>
      {buttons}
    </Box>
  );
}
