import type { ConversationSummary } from '@chat-app/shared/chat';
import type { PresenceState } from '@chat-app/shared/supabase';
import { useTranslation } from 'react-i18next';

import { useAuth } from '../context/AuthContext';
import { useCall } from '../context/CallContext';
import { useCallPresence } from '../lib/useCallPresence';
import { InfoIcon, PhoneIcon, SpinnerIcon, UsersIcon } from './icons';

const PRESENCE_DOT: Record<PresenceState, string> = {
  online: 'bg-emerald-400',
  idle: 'bg-amber-400',
  dnd: 'bg-rose-500',
  invisible: 'bg-neutral-500',
  offline: 'bg-neutral-600',
};

interface Props {
  conversation: ConversationSummary | null;
  peerPresence: PresenceState | null;
  onInfoClick?: () => void;
}

export function ConversationHeader({ conversation, peerPresence, onInfoClick }: Props) {
  if (!conversation) {
    return (
      <header className="h-[57px] border-b border-white/5 px-6 py-3" aria-busy="true" />
    );
  }

  return (
    <>
      <HeaderBar
        conversation={conversation}
        peerPresence={peerPresence}
        {...(onInfoClick ? { onInfoClick } : {})}
      />
      <ActiveCallBanner conversationId={conversation.id} />
    </>
  );
}

interface HeaderBarProps {
  conversation: ConversationSummary;
  peerPresence: PresenceState | null;
  onInfoClick?: () => void;
}

function HeaderBar({ conversation, peerPresence, onInfoClick }: HeaderBarProps) {
  const { t } = useTranslation(['app']);

  const isDm = conversation.type === 'dm';
  const title = isDm ? (conversation.peer?.displayName ?? '?') : (conversation.name ?? '?');
  const handle = isDm ? '@' + (conversation.peer?.username ?? '?') : '';
  const letter = title.trim().charAt(0).toUpperCase() || '?';

  // Hide presence when peer chose invisible — reciprocal privacy.
  const showPresence = isDm && peerPresence && peerPresence !== 'invisible';
  const presenceLabel = peerPresence ? t('app:presence.' + peerPresence) : '';

  return (
    <header className="flex items-center gap-3 border-b border-white/5 px-6 py-3">
      <div className="relative flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-brand-500/30 text-base font-semibold text-white ring-1 ring-brand-400/30">
        {isDm ? letter : <UsersIcon className="h-5 w-5" />}
        {showPresence && peerPresence && (
          <span
            aria-hidden="true"
            className={
              'absolute -bottom-0.5 -right-0.5 h-3 w-3 rounded-full ring-2 ring-ink-950 ' +
              PRESENCE_DOT[peerPresence]
            }
          />
        )}
      </div>
      <div className="min-w-0 flex-1">
        <p className="truncate font-display text-base font-semibold text-white">{title}</p>
        <p className="truncate text-xs text-neutral-500">
          {isDm ? (
            <>
              <span>{handle}</span>
              {showPresence && (
                <>
                  <span className="mx-1.5 text-neutral-700">·</span>
                  <span>{presenceLabel}</span>
                </>
              )}
            </>
          ) : (
            <>
              {conversation.members.length} {t('app:nav.friends').toLowerCase()}
            </>
          )}
        </p>
      </div>

      <CallHeaderButton conversationId={conversation.id} />
      {!isDm && onInfoClick && (
        <button
          type="button"
          onClick={onInfoClick}
          aria-label={t('app:group.info_title')}
          title={t('app:group.info_title')}
          className="flex h-9 w-9 cursor-pointer items-center justify-center rounded-lg text-neutral-400 transition hover:bg-white/10 hover:text-neutral-100 focus:outline-none focus-visible:ring-2 focus-visible:ring-brand-400/40"
        >
          <InfoIcon className="h-4 w-4" />
        </button>
      )}
    </header>
  );
}

function CallHeaderButton({ conversationId }: { conversationId: string }) {
  const { t } = useTranslation(['app']);
  const { state, startCall } = useCall();
  const busy = state.kind !== 'idle';
  return (
    <button
      type="button"
      onClick={() => void startCall(conversationId, 'audio')}
      disabled={busy}
      aria-label={t('app:call.start_audio')}
      title={busy ? t('app:call.busy') : t('app:call.start_audio')}
      className="flex h-9 w-9 cursor-pointer items-center justify-center rounded-lg text-neutral-400 transition hover:bg-white/10 hover:text-brand-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-brand-400/40 disabled:cursor-not-allowed disabled:opacity-50"
    >
      <PhoneIcon className="h-4 w-4" />
    </button>
  );
}

function ActiveCallBanner({ conversationId }: { conversationId: string }) {
  const { t } = useTranslation(['app']);
  const { session } = useAuth();
  const { state, joinActiveCall } = useCall();
  const active = useCallPresence(conversationId);

  const myId = session?.user.id;
  // Source of truth for "am I in this call" is the CallContext state, not
  // presence — my own presence entry can lag behind the room join, which
  // would otherwise make the banner flash while I'm already connected.
  const iAmIn =
    (state.kind === 'connected' ||
      state.kind === 'connecting' ||
      state.kind === 'outgoing') &&
    state.conversationId === conversationId;

  // Only show banner when other people are in it and I'm not.
  const othersIn = active.filter((u) => u !== myId);
  if (iAmIn || othersIn.length === 0) return null;

  const busy = state.kind !== 'idle';
  return (
    <div className="flex items-center gap-3 border-b border-emerald-500/20 bg-emerald-500/10 px-6 py-2.5 text-sm text-emerald-100">
      <PhoneIcon className="h-4 w-4 text-emerald-300" />
      <span className="flex-1">
        {t('app:call.active_in_conv', {
          defaultValue: 'Active call · {{count}} in room',
          count: othersIn.length,
        })}
      </span>
      <button
        type="button"
        onClick={() => void joinActiveCall(conversationId, 'audio')}
        disabled={busy}
        className="inline-flex cursor-pointer items-center gap-1.5 rounded-md bg-emerald-500/90 px-3 py-1.5 text-xs font-semibold text-white transition hover:bg-emerald-400 focus:outline-none focus-visible:ring-2 focus-visible:ring-emerald-400/40 disabled:cursor-not-allowed disabled:opacity-60"
      >
        {busy ? (
          <SpinnerIcon className="h-3.5 w-3.5" />
        ) : (
          <PhoneIcon className="h-3.5 w-3.5" />
        )}
        <span>{t('app:call.join', { defaultValue: 'Join' })}</span>
      </button>
    </div>
  );
}
