import { useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { useLocation, useNavigate } from 'react-router-dom';

import { useCall } from '../context/CallContext';
import { useConversationsContext } from '../context/ConversationsContext';
import { useFriendshipsContext } from '../context/FriendshipsContext';
import { ringtone } from '../lib/ringtone';
import { AvatarColorKey, colorKeyFor } from './CallParticipantTile';
import { LockIcon, MonitorShareIcon, PhoneIcon, PhoneOffIcon } from './icons';

// Shell-level mount. Responsibilities:
//   - Start/stop ringtones by call-state transition.
//   - Toast-style incoming-call banner for conversations the user isn't in
//     (clicking the toast routes to the docked IncomingCallPanel).
//   - PiP widget when an active call is live but the user is looking at a
//     different route.
export function CallUI() {
  const { state } = useCall();

  useEffect(() => {
    if (state.kind === 'outgoing') ringtone.start('outgoing');
    else if (state.kind === 'incoming') ringtone.start('incoming');
    else ringtone.stop();
  }, [state.kind]);

  useEffect(() => {
    return () => ringtone.stop();
  }, []);

  return (
    <>
      <IncomingCallToast />
      <PipCall />
    </>
  );
}

// ---------------------------------------------------------------------------

const TOAST_AVATAR: Record<AvatarColorKey, string> = {
  violet: 'bg-violet-500/90 text-white',
  amber: 'bg-amber-500/90 text-white',
  rose: 'bg-rose-500/90 text-white',
  teal: 'bg-teal-500/90 text-white',
};

function IncomingCallToast() {
  const { t } = useTranslation(['app']);
  const { state, acceptIncoming, rejectIncoming } = useCall();
  const { friendships } = useFriendshipsContext();
  const { conversations } = useConversationsContext();
  const navigate = useNavigate();
  const location = useLocation();

  if (state.kind !== 'incoming') return null;

  // When the user is already looking at the target conversation, the docked
  // IncomingCallPanel handles the UI; hide the toast to avoid double chrome.
  if (location.pathname === '/chats/' + state.conversationId) return null;

  const conv = conversations.find((c) => c.id === state.conversationId) ?? null;
  const callerName =
    conv?.members.find((m) => m.userId === state.fromUserId)?.profile?.displayName ??
    friendships.find((f) => f.peer.userId === state.fromUserId)?.peer.displayName ??
    '?';
  const isGroup = conv?.type === 'group';
  const groupName = isGroup ? (conv?.name ?? t('app:chats.new_group')) : null;
  const title = isGroup ? groupName ?? callerName : callerName;
  const letter = title.trim().charAt(0).toUpperCase() || '?';
  const color = colorKeyFor(state.fromUserId);

  return (
    <div
      role="dialog"
      aria-modal="false"
      aria-label={t('app:call.incoming_title')}
      className="fixed bottom-6 right-6 z-50 w-80 animate-slide-up overflow-hidden rounded-2xl border border-line bg-surface-3 shadow-call-card-dark"
    >
      <button
        type="button"
        onClick={() => navigate('/chats/' + state.conversationId)}
        className="group block w-full cursor-pointer p-5 text-left transition hover:bg-surface-2 focus:outline-none focus-visible:ring-2 focus-visible:ring-accent/40"
      >
        <p className="text-[10px] font-semibold uppercase tracking-[0.12em] text-fg-muted">
          {t('app:call.incoming_title')}
        </p>
        <div className="mt-2 flex items-center gap-3">
          <div
            className={
              'flex h-11 w-11 shrink-0 items-center justify-center rounded-full font-semibold ' +
              TOAST_AVATAR[color]
            }
          >
            {letter}
          </div>
          <div className="min-w-0 flex-1">
            <p className="truncate font-display text-base font-semibold text-fg">{title}</p>
            <p className="flex items-center gap-1.5 truncate text-xs text-fg-muted">
              <LockIcon className="h-3 w-3" />
              <span>
                {isGroup
                  ? t('app:call.incoming_group_from', {
                      name: callerName,
                      defaultValue: callerName + ' ruft Gruppe',
                    })
                  : t('app:call.incoming_from', { name: callerName })}
              </span>
            </p>
          </div>
        </div>
      </button>
      <div className="flex gap-2 px-5 pb-5">
        <button
          type="button"
          onClick={rejectIncoming}
          className="inline-flex flex-1 cursor-pointer items-center justify-center gap-2 rounded-lg border border-rose-500/40 bg-transparent px-3 py-2 text-sm font-semibold text-rose-600 transition hover:bg-rose-500/10 focus:outline-none focus-visible:ring-2 focus-visible:ring-rose-500/40 dark:text-rose-400"
        >
          <PhoneOffIcon className="h-4 w-4" />
          <span>{t('app:call.decline')}</span>
        </button>
        <button
          type="button"
          onClick={() => void acceptIncoming()}
          className="inline-flex flex-1 cursor-pointer items-center justify-center gap-2 rounded-lg bg-emerald-600 px-3 py-2 text-sm font-semibold text-white transition hover:bg-emerald-500 focus:outline-none focus-visible:ring-2 focus-visible:ring-emerald-500/50"
        >
          <PhoneIcon className="h-4 w-4" />
          <span>{t('app:call.accept')}</span>
        </button>
      </div>
    </div>
  );
}

// ---------------------------------------------------------------------------
// PiP widget — shown when the user has an active call but is browsing
// somewhere else. Clicking expands back to the call's conversation.
// ---------------------------------------------------------------------------

function PipCall() {
  const { t } = useTranslation(['app']);
  const {
    state,
    remoteParticipants,
    remoteScreenShares,
    hangup,
  } = useCall();
  const navigate = useNavigate();
  const location = useLocation();
  const { conversations } = useConversationsContext();

  const active =
    state.kind === 'connected' ||
    state.kind === 'connecting' ||
    state.kind === 'outgoing';
  if (!active) return null;

  // Only render when the user is NOT currently viewing the call's
  // conversation. Inside that conversation the full dock is visible already.
  if (location.pathname === '/chats/' + state.conversationId) return null;

  const conv = conversations.find((c) => c.id === state.conversationId) ?? null;
  const title =
    conv?.type === 'group'
      ? conv?.name ?? t('app:chats.new_group')
      : conv?.peer?.displayName ?? '—';
  const participantCount = 1 + remoteParticipants.length;
  const someoneSharing = remoteScreenShares.length > 0;

  return (
    <div
      role="dialog"
      aria-label={t('app:call.active_in_conv', { defaultValue: 'Aktiver Anruf' })}
      onClick={() => navigate('/chats/' + state.conversationId)}
      className="fixed bottom-5 right-5 z-40 flex w-[260px] animate-slide-in-call cursor-pointer items-center gap-2.5 rounded-[14px] border border-accent bg-surface-3 p-2.5 shadow-pip-call transition hover:-translate-y-0.5"
    >
      <div className="flex h-11 w-11 shrink-0 items-center justify-center overflow-hidden rounded-[10px] bg-surface-2">
        {someoneSharing ? (
          <MonitorShareIcon className="h-5 w-5 text-accent" />
        ) : (
          <PhoneIcon className="h-5 w-5 text-accent" />
        )}
      </div>
      <div className="min-w-0 flex-1">
        <p className="truncate text-[13px] font-semibold text-fg">
          {title} · {participantCount}
        </p>
        <p className="mt-0.5 flex items-center gap-1.5 text-[11px] text-fg-muted">
          <span
            aria-hidden="true"
            className="h-1.5 w-1.5 rounded-full bg-rose-500 animate-live-dot"
          />
          <span>Live · {t('app:call.tap_to_open', { defaultValue: 'tippe zum Öffnen' })}</span>
        </p>
      </div>
      <button
        type="button"
        onClick={(e) => {
          e.stopPropagation();
          void hangup();
        }}
        aria-label={t('app:call.hangup')}
        className="flex h-8 w-8 shrink-0 cursor-pointer items-center justify-center rounded-full bg-rose-600 text-white transition hover:bg-rose-500 focus:outline-none focus-visible:ring-2 focus-visible:ring-rose-400/60"
      >
        <PhoneOffIcon className="h-4 w-4" />
      </button>
    </div>
  );
}
