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

import { useCall } from '../context/CallContext';
import { useNickname } from '../lib/friendNicknames';
import type { PeerPresence } from '../lib/usePeerPresence';
import { Avatar } from './Avatar';
import {
  GridIcon,
  InfoIcon,
  PhoneIcon,
  SearchIcon,
  UsersIcon,
  VideoIcon,
} from './icons';
import { PinnedMessagesPill } from './PinnedMessagesPill';

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

interface Props {
  conversation: ConversationSummary | null;
  peerPresence: PeerPresence | null;
  onInfoClick?: () => void;
  onMediaClick?: () => void;
  onProfileClick?: (ev: React.MouseEvent) => void;
  onSearchClick?: () => void;
  pinnedCount?: number;
  onOpenPinned?: () => void;
}

export function ConversationHeader({
  conversation,
  peerPresence,
  onInfoClick,
  onMediaClick,
  onProfileClick,
  onSearchClick,
  pinnedCount = 0,
  onOpenPinned,
}: Props) {
  if (!conversation) {
    return <header className="h-[65px] border-b border-line px-6 py-3" aria-busy="true" />;
  }

  return (
    <>
      <HeaderBar
        conversation={conversation}
        peerPresence={peerPresence}
        pinnedCount={pinnedCount}
        {...(onInfoClick ? { onInfoClick } : {})}
        {...(onMediaClick ? { onMediaClick } : {})}
        {...(onProfileClick ? { onProfileClick } : {})}
        {...(onSearchClick ? { onSearchClick } : {})}
        {...(onOpenPinned ? { onOpenPinned } : {})}
      />
      {/* Voice-channel rail rendered separately in ConversationPage so it
          can sit between the message surface and the in-call dock. */}
    </>
  );
}

interface HeaderBarProps {
  conversation: ConversationSummary;
  peerPresence: PeerPresence | null;
  onInfoClick?: () => void;
  onMediaClick?: () => void;
  onProfileClick?: (ev: React.MouseEvent) => void;
  onSearchClick?: () => void;
  pinnedCount?: number;
  onOpenPinned?: () => void;
}

function HeaderBar({
  conversation,
  peerPresence,
  onInfoClick,
  onMediaClick,
  onProfileClick,
  onSearchClick,
  pinnedCount = 0,
  onOpenPinned,
}: HeaderBarProps) {
  const { t } = useTranslation(['app']);

  const isDm = conversation.type === 'dm';
  // For DMs, route the peer's display name through the per-viewer nickname
  // override. Falls back to the real displayName when no nickname is set.
  const peerName = useNickname(
    conversation.peer?.userId,
    conversation.peer?.displayName ?? '?',
  );
  const title = isDm ? peerName : (conversation.name ?? '?');
  const handle = isDm ? '@' + (conversation.peer?.username ?? '?') : '';
  const peerAvatar = isDm
    ? (conversation.peer?.avatarUrl ?? null)
    : (conversation.avatarUrl ?? null);

  // Hide presence when peer chose invisible — reciprocal privacy.
  const peerState = peerPresence?.state ?? null;
  const showPresence = isDm && peerState && peerState !== 'invisible';
  // Subtitle priority: custom status_message when online (or idle/dnd), else
  // the localized presence label. Offline always wins → just "Offline".
  const presenceLabel = (() => {
    if (!peerState) return '';
    if (peerState === 'offline') return t('app:presence.offline');
    if (peerPresence?.statusMessage && peerPresence.statusMessage.trim().length > 0) {
      return peerPresence.statusMessage.trim();
    }
    return t('app:presence.' + peerState);
  })();

  return (
    <header className="discord-chat-surface flex min-h-[65px] items-center gap-3 border-b border-line bg-surface-3 px-5 py-3">
      <button
        type="button"
        data-user-popover-trigger={isDm ? true : undefined}
        onClick={isDm ? onProfileClick : undefined}
        disabled={!isDm || !onProfileClick}
        aria-label={isDm ? 'Profil öffnen' : title}
        title={isDm ? 'Profil öffnen' : title}
        className="relative shrink-0 rounded-full text-left transition enabled:cursor-pointer enabled:hover:ring-2 enabled:hover:ring-accent/50 focus:outline-none focus-visible:ring-2 focus-visible:ring-accent/50 disabled:cursor-default"
      >
        {isDm ? (
          <Avatar url={peerAvatar} displayName={title} className="h-10 w-10 text-base" />
        ) : peerAvatar ? (
          <Avatar url={peerAvatar} displayName={title} className="h-10 w-10 text-base" />
        ) : (
          <div className="flex h-10 w-10 items-center justify-center rounded-full bg-accent/20 text-accent">
            <UsersIcon className="h-5 w-5" />
          </div>
        )}
        {showPresence && peerState && (
          <span
            aria-hidden="true"
            className={
              'absolute -bottom-0.5 -right-0.5 h-3 w-3 rounded-full ring-2 ring-surface-3 ' +
              PRESENCE_DOT[peerState]
            }
          />
        )}
      </button>
      <div className="min-w-0 flex-1">
        <div className="flex min-w-0 items-center gap-2">
          {!isDm && <UsersIcon className="h-4 w-4 shrink-0 text-fg-muted" />}
          <p className="truncate font-display text-base font-semibold text-fg">{title}</p>
          <PinnedMessagesPill count={pinnedCount} onClick={() => onOpenPinned?.()} />
        </div>
        <p className="truncate text-xs text-fg-muted">
          {isDm ? (
            <>
              <span>{handle}</span>
              {showPresence && (
                <>
                  <span className="mx-1.5 text-fg-muted/50">·</span>
                  <span>{presenceLabel}</span>
                </>
              )}
            </>
          ) : (
            <>
              {conversation.members.length} {t('app:nav.friends').toLowerCase()}
            </>
          )}
        </p>
      </div>

      <HeaderActionButton
        label={t('app:chats.search', { defaultValue: 'Suche' })}
        icon={SearchIcon}
        {...(onSearchClick ? { onClick: onSearchClick } : {})}
      />
      <HeaderActionButton
        label="Medien & Dateien"
        icon={GridIcon}
        {...(onMediaClick ? { onClick: onMediaClick } : {})}
      />
      <CallHeaderButton conversationId={conversation.id} kind="audio" />
      <CallHeaderButton conversationId={conversation.id} kind="video" />
      {!isDm && onInfoClick && (
        <HeaderActionButton
          label={t('app:group.info_title')}
          icon={InfoIcon}
          onClick={onInfoClick}
        />
      )}
    </header>
  );
}

interface HeaderActionButtonProps {
  label: string;
  icon: (props: React.SVGProps<SVGSVGElement>) => React.JSX.Element;
  onClick?: () => void;
  disabled?: boolean;
  tone?: 'default' | 'accent';
}

function HeaderActionButton({
  label,
  icon: Icon,
  onClick,
  disabled,
  tone = 'default',
}: HeaderActionButtonProps) {
  const toneClass =
    tone === 'accent'
      ? 'text-accent hover:bg-accent/10'
      : 'text-fg-muted hover:bg-surface-2 hover:text-fg dark:hover:bg-[#383a40]';
  return (
    <button
      type="button"
      onClick={onClick}
      disabled={disabled}
      aria-label={label}
      title={label}
      className={
        'flex h-9 w-9 cursor-pointer items-center justify-center rounded-lg transition focus:outline-none focus-visible:ring-2 focus-visible:ring-accent/40 disabled:cursor-not-allowed disabled:opacity-50 ' +
        toneClass
      }
    >
      <Icon className="h-4 w-4" />
    </button>
  );
}

function CallHeaderButton({
  conversationId,
  kind,
}: {
  conversationId: string;
  kind: 'audio' | 'video';
}) {
  const { t } = useTranslation(['app']);
  const { state, startCall } = useCall();
  const busy = state.kind !== 'idle';
  const label =
    kind === 'video'
      ? t('app:call.start_video', { defaultValue: 'Video-Anruf' })
      : t('app:call.start_audio');
  const Icon = kind === 'video' ? VideoIcon : PhoneIcon;
  return (
    <HeaderActionButton
      label={busy ? t('app:call.busy') : label}
      icon={Icon}
      onClick={() => void startCall(conversationId, kind)}
      disabled={busy}
    />
  );
}

