import { updateOwnProfile } from '@chat-app/shared/auth';
import type { PresenceState } from '@chat-app/shared/supabase';
import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';

import { useAuth } from '../context/AuthContext';
import { supabase } from '../lib/supabase';
import { Avatar } from './Avatar';
import { ChevronDownIcon } from './icons';

const STATUS_MAX = 128;

const PRESENCE_OPTIONS: PresenceState[] = ['online', 'idle', 'dnd', 'invisible', 'offline'];

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',
};

export function UserBar() {
  const { t } = useTranslation(['app']);
  const { profile, refreshProfile } = useAuth();
  const [open, setOpen] = useState(false);
  const [busy, setBusy] = useState(false);

  const presence = profile?.presenceState ?? 'offline';
  const persistedStatus = profile?.statusMessage ?? '';
  const [statusDraft, setStatusDraft] = useState(persistedStatus);

  // Re-sync local draft with the server when the profile refreshes (e.g. after
  // a successful save) — without this the input would forget any incoming
  // updates from another device.
  useEffect(() => {
    setStatusDraft(persistedStatus);
  }, [persistedStatus]);

  // Subtitle priority: custom status when online and set, else label, else "Offline".
  const subtitle =
    presence === 'offline'
      ? t('app:presence.offline')
      : persistedStatus.trim().length > 0
        ? persistedStatus.trim()
        : t('app:presence.' + presence);

  async function changePresence(next: PresenceState) {
    if (busy || next === presence) {
      setOpen(false);
      return;
    }
    setBusy(true);
    try {
      await updateOwnProfile(supabase, { presenceState: next });
      await refreshProfile();
    } catch (err: unknown) {
      console.error('updatePresence failed', err);
    } finally {
      setBusy(false);
      setOpen(false);
    }
  }

  async function saveStatus() {
    const next = statusDraft.trim().slice(0, STATUS_MAX);
    if (next === persistedStatus) return;
    setBusy(true);
    try {
      await updateOwnProfile(supabase, { statusMessage: next.length === 0 ? null : next });
      await refreshProfile();
    } catch (err: unknown) {
      console.error('updateStatusMessage failed', err);
    } finally {
      setBusy(false);
    }
  }

  return (
    <div className="relative">
      <button
        type="button"
        onClick={() => setOpen((v) => !v)}
        aria-haspopup="menu"
        aria-expanded={open}
        className="flex w-full cursor-pointer items-center gap-3 rounded-lg px-2 py-2 text-left transition hover:bg-surface-3 focus:outline-none focus-visible:ring-2 focus-visible:ring-accent/40 dark:hover:bg-[#383a40]"
      >
        <div className="relative">
          <Avatar
            url={profile?.avatarUrl ?? null}
            displayName={profile?.displayName ?? profile?.username}
            className="h-10 w-10 text-sm"
          />
          <span
            className={
              'absolute -bottom-0.5 -right-0.5 h-3 w-3 rounded-full ring-2 ring-surface-2 ' +
              PRESENCE_DOT[presence]
            }
          />
        </div>
        <div className="min-w-0 flex-1">
          <p className="truncate text-sm font-medium text-fg">{profile?.displayName ?? '—'}</p>
          <p className="truncate text-xs text-fg-muted">{subtitle}</p>
        </div>
        <ChevronDownIcon
          className={'h-4 w-4 text-fg-muted transition ' + (open ? 'rotate-180' : '')}
        />
      </button>

      {open && (
        <div
          role="menu"
          className="absolute bottom-full left-0 right-0 mb-2 overflow-hidden rounded-lg border border-line bg-surface-3 shadow-xl dark:bg-[#313338]"
        >
          <div className="border-b border-line p-2">
            <input
              type="text"
              value={statusDraft}
              onChange={(e) => setStatusDraft(e.target.value.slice(0, STATUS_MAX))}
              onBlur={() => void saveStatus()}
              onKeyDown={(e) => {
                if (e.key === 'Enter') {
                  e.preventDefault();
                  void saveStatus();
                  setOpen(false);
                }
                if (e.key === 'Escape') {
                  setStatusDraft(persistedStatus);
                  setOpen(false);
                }
              }}
              placeholder={t('app:presence.status_placeholder', {
                defaultValue: 'Status setzen…',
              })}
              maxLength={STATUS_MAX}
              className="w-full rounded-md border border-line bg-surface-2 px-2 py-1.5 text-sm text-fg placeholder-fg-muted outline-none focus:border-accent dark:bg-[#383a40]"
            />
          </div>
          {PRESENCE_OPTIONS.map((opt) => (
            <button
              key={opt}
              type="button"
              role="menuitemradio"
              aria-checked={opt === presence}
              onClick={() => void changePresence(opt)}
              disabled={busy}
              className="flex w-full cursor-pointer items-center gap-3 px-3 py-2 text-left text-sm text-fg transition hover:bg-surface-2 disabled:opacity-50 dark:hover:bg-[#383a40]"
            >
              <span className={'h-2.5 w-2.5 rounded-full ' + PRESENCE_DOT[opt]} />
              <span className="flex-1">{t('app:presence.' + opt)}</span>
              {opt === presence && <span className="text-xs text-accent">●</span>}
            </button>
          ))}
        </div>
      )}
    </div>
  );
}
