import { addGroupMember, type ConversationSummary, leaveGroup } from '@chat-app/shared/chat';
import { extractErrorCode } from '@chat-app/shared/i18n';
import { useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';

import { useAuth } from '../context/AuthContext';
import { useFriendshipsContext } from '../context/FriendshipsContext';
import { supabase } from '../lib/supabase';
import { AlertIcon, PlusIcon, SignOutIcon, SpinnerIcon, UsersIcon, XIcon } from './icons';

interface Props {
  open: boolean;
  onClose: () => void;
  conversation: ConversationSummary;
}

export function GroupInfoPanel({ open, onClose, conversation }: Props) {
  const { t } = useTranslation(['app', 'errors']);
  const { session } = useAuth();
  const { friendships } = useFriendshipsContext();
  const navigate = useNavigate();
  const [busyLeave, setBusyLeave] = useState(false);
  const [busyAddId, setBusyAddId] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);

  const myId = session?.user.id;
  const myRole =
    conversation.members.find((m) => m.userId === myId)?.role ?? conversation.myRole;
  const canAdd = myRole === 'admin' || myRole === 'mod';

  const addableFriends = useMemo(() => {
    const memberIds = new Set(conversation.members.map((m) => m.userId));
    return friendships
      .filter((f) => f.status === 'accepted')
      .map((f) => f.peer)
      .filter((p) => !memberIds.has(p.userId));
  }, [friendships, conversation.members]);

  async function handleAdd(userId: string) {
    if (busyAddId) return;
    setBusyAddId(userId);
    setError(null);
    try {
      await addGroupMember(supabase, conversation.id, userId);
    } catch (err: unknown) {
      const code = extractErrorCode(err);
      setError(
        code
          ? t('errors:' + code, { defaultValue: t('errors:generic') })
          : err instanceof Error
            ? err.message
            : t('errors:generic'),
      );
    } finally {
      setBusyAddId(null);
    }
  }

  async function handleLeave() {
    if (busyLeave) return;
    if (!window.confirm(t('app:group.info_leave_confirm'))) return;
    setBusyLeave(true);
    setError(null);
    try {
      await leaveGroup(supabase, conversation.id);
      onClose();
      navigate('/chats');
    } catch (err: unknown) {
      const code = extractErrorCode(err);
      setError(
        code
          ? t('errors:' + code, { defaultValue: t('errors:generic') })
          : err instanceof Error
            ? err.message
            : t('errors:generic'),
      );
    } finally {
      setBusyLeave(false);
    }
  }

  if (!open) return null;

  const roleLabel = (role: string) =>
    role === 'admin'
      ? t('app:group.info_role_admin')
      : role === 'mod'
        ? t('app:group.info_role_mod')
        : t('app:group.info_role_member');

  return (
    <aside
      role="dialog"
      aria-label={t('app:group.info_title')}
      className="flex w-[320px] shrink-0 flex-col border-l border-white/5 bg-ink-900/95"
    >
      <header className="flex items-center justify-between border-b border-white/5 px-5 py-4">
        <div>
          <p className="text-xs uppercase tracking-wide text-neutral-500">
            {t('app:group.info_title')}
          </p>
          <h3 className="mt-0.5 font-display text-base font-semibold text-white">
            {conversation.name ?? '—'}
          </h3>
        </div>
        <button
          type="button"
          onClick={onClose}
          aria-label="Close"
          className="flex h-8 w-8 cursor-pointer items-center justify-center rounded-lg text-neutral-400 transition hover:bg-white/10 hover:text-neutral-100"
        >
          <XIcon className="h-4 w-4" />
        </button>
      </header>

      <div className="flex-1 space-y-6 overflow-y-auto p-5">
        <section>
          <h4 className="mb-2 text-xs font-medium uppercase tracking-wide text-neutral-500">
            {t('app:group.info_members')} ({conversation.members.length})
          </h4>
          <ul className="space-y-1">
            {conversation.members.map((m) => {
              const name = m.profile?.displayName ?? '?';
              const handle = m.profile?.username ? '@' + m.profile.username : '';
              const avatarUrl = m.profile?.avatarUrl ?? null;
              const letter = name.trim().charAt(0).toUpperCase() || '?';
              return (
                <li
                  key={m.userId}
                  className="flex items-center gap-3 rounded-lg px-2 py-1.5"
                >
                  {avatarUrl ? (
                    <img
                      src={avatarUrl}
                      alt=""
                      className="h-8 w-8 shrink-0 rounded-full object-cover"
                      draggable={false}
                    />
                  ) : (
                    <div className="flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-brand-500/30 text-xs font-semibold text-white ring-1 ring-brand-400/30">
                      {letter}
                    </div>
                  )}
                  <div className="min-w-0 flex-1">
                    <p className="truncate text-sm text-white">
                      {name}
                      {m.userId === myId && (
                        <span className="ml-1.5 text-xs text-neutral-500">· you</span>
                      )}
                    </p>
                    <p className="truncate text-xs text-neutral-500">{handle}</p>
                  </div>
                  <span
                    className={
                      'rounded-full border px-2 py-0.5 text-[10px] font-medium ' +
                      (m.role === 'admin'
                        ? 'border-brand-400/30 bg-brand-500/15 text-brand-200'
                        : m.role === 'mod'
                          ? 'border-amber-500/30 bg-amber-500/10 text-amber-200'
                          : 'border-white/10 bg-white/5 text-neutral-300')
                    }
                  >
                    {roleLabel(m.role)}
                  </span>
                </li>
              );
            })}
          </ul>
        </section>

        {canAdd && (
          <section>
            <h4 className="mb-2 text-xs font-medium uppercase tracking-wide text-neutral-500">
              {t('app:group.info_add_title')}
            </h4>
            {addableFriends.length === 0 ? (
              <div className="flex items-center gap-3 rounded-lg border border-white/5 bg-ink-800/60 p-3 text-xs text-neutral-400">
                <UsersIcon className="h-4 w-4" />
                <span>{t('app:group.info_add_empty')}</span>
              </div>
            ) : (
              <>
                <p className="mb-2 text-xs text-neutral-500">
                  {t('app:group.info_add_help')}
                </p>
                <ul className="space-y-1">
                  {addableFriends.map((f) => {
                    const letter =
                      (f.displayName ?? f.username ?? '?').trim().charAt(0).toUpperCase() || '?';
                    const busy = busyAddId === f.userId;
                    return (
                      <li key={f.userId}>
                        <button
                          type="button"
                          disabled={busy}
                          onClick={() => void handleAdd(f.userId)}
                          className="flex w-full cursor-pointer items-center gap-3 rounded-lg px-2 py-1.5 text-left transition hover:bg-white/5 focus:outline-none focus-visible:ring-2 focus-visible:ring-brand-400/40 disabled:opacity-60"
                        >
                          {f.avatarUrl ? (
                            <img
                              src={f.avatarUrl}
                              alt=""
                              className="h-8 w-8 shrink-0 rounded-full object-cover"
                              draggable={false}
                            />
                          ) : (
                            <div className="flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-brand-500/30 text-xs font-semibold text-white ring-1 ring-brand-400/30">
                              {letter}
                            </div>
                          )}
                          <div className="min-w-0 flex-1">
                            <p className="truncate text-sm text-white">{f.displayName}</p>
                            <p className="truncate text-xs text-neutral-500">@{f.username}</p>
                          </div>
                          {busy ? (
                            <SpinnerIcon className="h-4 w-4 text-brand-400" />
                          ) : (
                            <PlusIcon className="h-4 w-4 text-neutral-400" />
                          )}
                        </button>
                      </li>
                    );
                  })}
                </ul>
              </>
            )}
          </section>
        )}

        {error && (
          <div
            role="alert"
            className="flex items-start gap-3 rounded-lg border border-rose-500/20 bg-rose-500/10 p-3 text-sm text-rose-100"
          >
            <AlertIcon className="mt-0.5 h-5 w-5 shrink-0 text-rose-400" />
            <p className="min-w-0 flex-1 break-words">{error}</p>
          </div>
        )}
      </div>

      <footer className="border-t border-white/5 p-4">
        <button
          type="button"
          onClick={() => void handleLeave()}
          disabled={busyLeave}
          className="inline-flex w-full cursor-pointer items-center justify-center gap-2 rounded-lg border border-rose-500/30 bg-rose-500/10 px-3 py-2 text-xs font-medium text-rose-200 transition hover:bg-rose-500/20 disabled:opacity-60"
        >
          {busyLeave ? (
            <SpinnerIcon className="h-3.5 w-3.5" />
          ) : (
            <SignOutIcon className="h-3.5 w-3.5" />
          )}
          <span>{t('app:group.info_leave')}</span>
        </button>
      </footer>
    </aside>
  );
}
