import React, { useEffect, useState } from 'react';
import { Avatar, Box, Icon, Icons, Text } from 'folds';
import classNames from 'classnames';
import { useTranslation } from 'react-i18next';
import * as css from './styles.css';
import { CallControl } from './CallControl';
import { useCallMembers, useCallSession } from '../../hooks/useCall';
import { ScreenSize, useScreenSizeContext } from '../../hooks/useScreenSize';
import { CallEmbed } from '../../plugins/call/CallEmbed';
import { useCallJoined } from '../../hooks/useCallEmbed';
import { useCallDuration, formatCallTimer } from '../../hooks/useCallDuration';
import { useMatrixClient } from '../../hooks/useMatrixClient';
import { useMediaAuthentication } from '../../hooks/useMediaAuthentication';
import { useRoomAvatar, useRoomName } from '../../hooks/useRoomMeta';
import { useRoomNavigate } from '../../hooks/useRoomNavigate';
import { isNativePlatform } from '../../utils/capacitor';
import { UserAvatar } from '../../components/user-avatar';
import { RoomAvatar } from '../../components/room-avatar';
import { getMemberDisplayName } from '../../utils/room';
import { getMxIdLocalPart, guessDmRoomUserId, mxcUrlToHttp } from '../../utils/matrix';

type CallStatusProps = {
  callEmbed: CallEmbed;
};

export function CallStatus({ callEmbed }: CallStatusProps) {
  const { t } = useTranslation();
  const { room } = callEmbed;
  const mx = useMatrixClient();
  const useAuthentication = useMediaAuthentication();

  const callJoined = useCallJoined(callEmbed);
  const callSession = useCallSession(room);
  const callMembers = useCallMembers(room, callSession);
  const screenSize = useScreenSizeContext();
  const compact = screenSize === ScreenSize.Mobile;
  const { navigateRoom } = useRoomNavigate();

  // Member-count gate mirrors the rest of the post-P3c app: 1:1 chrome
  // surfaces the peer (their avatar + display name); group chrome
  // surfaces the room itself. Snapshot — call duration is short relative
  // to membership churn, and `useCallMembers` already reactively covers
  // the «who's actually live» count below, so peer chrome at most lags
  // one render behind a third joiner before re-painting.
  const isOneOnOne = room.getInvitedAndJoinedMemberCount() === 2;

  const myUserId = mx.getSafeUserId();
  const peerCandidate = isOneOnOne ? guessDmRoomUserId(room, myUserId) : undefined;
  const peerUserId = peerCandidate && peerCandidate !== myUserId ? peerCandidate : undefined;
  const peerName = peerUserId
    ? getMemberDisplayName(room, peerUserId) ?? getMxIdLocalPart(peerUserId) ?? peerUserId
    : undefined;

  const roomName = useRoomName(room);
  const avatarMxc = useRoomAvatar(room, isOneOnOne);
  const avatarUrl = avatarMxc
    ? mxcUrlToHttp(mx, avatarMxc, useAuthentication, 96, 96, 'crop') ?? undefined
    : undefined;

  // Defensive fallback chain — empty roomName + unresolved peer would
  // otherwise collapse the H4 to "" and leave the pill anonymous.
  const displayName = (isOneOnOne && peerName) || roomName || peerUserId || room.roomId;

  // Sub-text walks the real call lifecycle so the pill reads like a phone
  // call: «Соединение…» until the widget reports joined → «Вызов…» while we
  // wait for the other side to pick up (nobody else is live yet) → a live
  // m:ss timer once both parties are connected. Group calls keep the «N в
  // звонке» count and append the timer. The pulsing dot tracks `callJoined`.
  //
  // `everConnected` latches once ≥2 members are live and never un-latches for
  // the life of this pill (the renderer keys it by roomId, so a new call gets
  // a fresh latch). This keeps the timer counting through a transient peer
  // drop/rejoin (LiveKit reconnect / key rotation) instead of snapping back to
  // «Вызов…» and resetting to 0:00 — the call itself survives such blips via
  // `useCallerAutoHangup`'s peer-leave grace.
  const memberCount = callMembers.length;
  const [everConnected, setEverConnected] = useState(false);
  useEffect(() => {
    if (callJoined && memberCount >= 2) setEverConnected(true);
  }, [callJoined, memberCount]);

  const connected = callJoined && everConnected;
  const duration = useCallDuration(connected);
  const timer = duration !== null ? formatCallTimer(duration) : '';

  let subText: string;
  if (!callJoined) {
    subText = t('Call.connecting');
  } else if (!everConnected) {
    subText = t('Call.calling');
  } else if (isOneOnOne) {
    subText = timer || t('Call.in_call');
  } else {
    subText = timer
      ? `${t('Call.in_call_count', { count: memberCount })} · ${timer}`
      : t('Call.in_call_count', { count: memberCount });
  }

  const native = isNativePlatform();

  const avatar = (
    <Avatar className={native ? css.CallAvatar : css.CallAvatarCompact}>
      {isOneOnOne ? (
        <UserAvatar
          userId={peerUserId ?? ''}
          src={avatarUrl}
          alt={displayName}
          renderFallback={() => <Icon size="400" src={Icons.User} filled />}
        />
      ) : (
        <RoomAvatar
          roomId={room.roomId}
          src={avatarUrl}
          alt={displayName}
          renderFallback={() => <Icon size="400" src={Icons.Hash} filled />}
        />
      )}
    </Avatar>
  );

  const nameAndState = (
    <Box
      grow={native ? undefined : 'Yes'}
      direction="Column"
      gap="100"
      alignItems={native ? 'Center' : 'Start'}
      style={{ minWidth: 0, maxWidth: '100%' }}
    >
      <Text size="H4" truncate>
        {displayName}
      </Text>
      <span className={css.StateLine}>
        <span className={classNames(css.LiveDot, callJoined && css.LiveDotPulsing)} aria-hidden />
        <Text as="span" size="T200" priority="300" truncate className={css.Timer}>
          {subText}
        </Text>
      </span>
    </Box>
  );

  // Native (phone): tall vertical Dawn card. Web (desktop): the original
  // compact horizontal row, same size as before.
  if (native) {
    return (
      <Box className={classNames(css.CallCard, css.CallCardNative)} shrink="No" direction="Column">
        <div className={css.CallCardInner}>
          <button
            type="button"
            className={css.CallIdentityButton}
            onClick={() => navigateRoom(room.roomId)}
            aria-label={t('Call.open_call_room')}
          >
            {avatar}
            {nameAndState}
          </button>
          <CallControl native callJoined={callJoined} compact={compact} callEmbed={callEmbed} />
        </div>
      </Box>
    );
  }

  return (
    <Box
      className={classNames(css.CallCard, css.CallCardCompact)}
      shrink="No"
      direction="Row"
      alignItems="Center"
    >
      <button
        type="button"
        className={css.CallIdentityButtonCompact}
        onClick={() => navigateRoom(room.roomId)}
        aria-label={t('Call.open_call_room')}
      >
        {avatar}
        {nameAndState}
      </button>
      <CallControl native={false} callJoined={callJoined} compact={compact} callEmbed={callEmbed} />
    </Box>
  );
}
