import { acceptDm, type ConversationSummary } from '@chat-app/shared/chat';
import { extractErrorCode } from '@chat-app/shared/i18n';
import { useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { NavLink, Outlet, useParams } from 'react-router-dom';

import { CreateGroupDialog } from '../components/CreateGroupDialog';
import { ChatBubbleIcon, PlusIcon, SpinnerIcon, UsersIcon } from '../components/icons';
import { useConversationsContext } from '../context/ConversationsContext';
import { supabase } from '../lib/supabase';

export function ChatsPage() {
  const { conversations, loading, error, refresh, unread } = useConversationsContext();
  const { id: activeId } = useParams<{ id: string }>();
  const [createOpen, setCreateOpen] = useState(false);

  const sorted = useMemo(() => {
    return [...conversations].sort((a, b) => {
      const ta = a.lastMessageAt ?? a.createdAt;
      const tb = b.lastMessageAt ?? b.createdAt;
      return tb.localeCompare(ta);
    });
  }, [conversations]);

  return (
    <div className="flex h-full">
      <ConversationList
        items={sorted}
        loading={loading}
        error={error}
        activeId={activeId}
        unread={unread}
        onAccept={async (id) => {
          try {
            await acceptDm(supabase, id);
            await refresh();
          } catch (err: unknown) {
            const code = extractErrorCode(err);
            console.error('acceptDm failed', code ?? err);
          }
        }}
        onNewGroup={() => setCreateOpen(true)}
      />
      <div className="flex-1 border-l border-white/5">
        <Outlet />
      </div>
      <CreateGroupDialog open={createOpen} onClose={() => setCreateOpen(false)} />
    </div>
  );
}

function ConversationList({
  items,
  loading,
  error,
  activeId,
  unread,
  onAccept,
  onNewGroup,
}: {
  items: ConversationSummary[];
  loading: boolean;
  error: string | null;
  activeId: string | undefined;
  unread: Record<string, number>;
  onAccept: (id: string) => void;
  onNewGroup: () => void;
}) {
  const { t } = useTranslation(['app']);

  return (
    <aside
      aria-label="Conversations"
      className="flex h-full w-[320px] shrink-0 flex-col bg-ink-900/40"
    >
      <header className="flex items-center justify-between px-4 pb-3 pt-5">
        <h2 className="font-display text-base font-semibold tracking-tight text-white">
          {t('app:nav.chats')}
        </h2>
        <button
          type="button"
          onClick={onNewGroup}
          aria-label={t('app:chats.new_group')}
          title={t('app:chats.new_group')}
          className="flex h-8 cursor-pointer items-center gap-1.5 rounded-lg border border-white/10 bg-white/5 px-2.5 text-xs font-medium text-neutral-300 transition hover:bg-white/10 hover:text-neutral-100 focus:outline-none focus-visible:ring-2 focus-visible:ring-brand-400/40"
        >
          <UsersIcon className="h-3.5 w-3.5" />
          <PlusIcon className="h-3 w-3" />
        </button>
      </header>

      {loading ? (
        <div className="flex items-center gap-2 px-4 py-2 text-xs text-neutral-500">
          <SpinnerIcon className="h-3.5 w-3.5 text-brand-400" />
        </div>
      ) : error ? (
        <p className="px-4 py-2 text-xs text-rose-300">{error}</p>
      ) : items.length === 0 ? (
        <div className="flex flex-1 flex-col items-center justify-center gap-3 px-6 text-center">
          <div className="flex h-12 w-12 items-center justify-center rounded-2xl border border-white/10 bg-white/5 text-brand-300">
            <ChatBubbleIcon className="h-5 w-5" />
          </div>
          <p className="text-sm text-neutral-400">{t('app:chats.empty_title')}</p>
          <p className="text-xs text-neutral-500">{t('app:chats.empty_subtitle')}</p>
        </div>
      ) : (
        <ul className="flex-1 overflow-y-auto px-2 pb-4">
          {items.map((c) => (
            <li key={c.id}>
              <ConversationRow
                item={c}
                active={c.id === activeId}
                unreadCount={unread[c.id] ?? 0}
                onAccept={onAccept}
              />
            </li>
          ))}
        </ul>
      )}
    </aside>
  );
}

function ConversationRow({
  item,
  active,
  unreadCount,
  onAccept,
}: {
  item: ConversationSummary;
  active: boolean;
  unreadCount: number;
  onAccept: (id: string) => void;
}) {
  const { t } = useTranslation(['app']);
  const title =
    item.type === 'dm' ? (item.peer?.displayName ?? '?') : (item.name ?? '?');
  const handle = item.type === 'dm' ? '@' + (item.peer?.username ?? '?') : '';
  const letter = title.trim().charAt(0).toUpperCase() || '?';

  if (!item.acceptedByMe) {
    return (
      <div className="my-1 rounded-xl border border-amber-500/20 bg-amber-500/5 p-3">
        <div className="flex items-center gap-3">
          <Avatar letter={letter} />
          <div className="min-w-0 flex-1">
            <p className="truncate text-sm font-semibold text-white">{title}</p>
            <p className="truncate text-xs text-amber-200/80">
              {t('app:friends.incoming_request')}
            </p>
          </div>
        </div>
        <button
          type="button"
          onClick={() => onAccept(item.id)}
          className="mt-3 w-full cursor-pointer rounded-md bg-amber-500/20 px-3 py-1.5 text-xs font-semibold text-amber-100 transition hover:bg-amber-500/30 focus:outline-none focus-visible:ring-2 focus-visible:ring-amber-400/40"
        >
          {t('app:friends.action_accept')}
        </button>
      </div>
    );
  }

  return (
    <NavLink
      to={'/chats/' + item.id}
      className={
        'my-1 flex cursor-pointer items-center gap-3 rounded-xl px-3 py-2.5 transition focus:outline-none focus-visible:ring-2 focus-visible:ring-brand-400/40 ' +
        (active ? 'bg-brand-500/15 ring-1 ring-brand-400/30' : 'hover:bg-white/5')
      }
    >
      <Avatar letter={letter} />
      <div className="min-w-0 flex-1">
        <p
          className={
            'truncate text-sm ' +
            (unreadCount > 0 ? 'font-bold text-white' : 'font-semibold text-white')
          }
        >
          {title}
        </p>
        <p className="truncate text-xs text-neutral-500">{handle}</p>
      </div>
      {unreadCount > 0 && (
        <span
          aria-label={'Unread: ' + unreadCount}
          className="inline-flex min-w-[20px] items-center justify-center rounded-full bg-rose-500 px-1.5 text-[10px] font-bold leading-tight text-white"
        >
          {unreadCount > 99 ? '99+' : unreadCount}
        </span>
      )}
    </NavLink>
  );
}

function Avatar({ letter }: { letter: string }) {
  return (
    <div className="flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-brand-500/30 text-sm font-semibold text-white ring-1 ring-brand-400/30">
      {letter}
    </div>
  );
}

export function ChatsEmptyState() {
  const { t } = useTranslation(['app']);
  return (
    <div className="flex h-full items-center justify-center p-10">
      <div className="max-w-md text-center">
        <div className="mx-auto mb-4 flex h-14 w-14 items-center justify-center rounded-2xl border border-white/10 bg-white/5 text-brand-300">
          <ChatBubbleIcon className="h-6 w-6" />
        </div>
        <h2 className="font-display text-2xl font-semibold tracking-tight text-white">
          {t('app:chats.select_prompt')}
        </h2>
        <p className="mt-2 text-sm text-neutral-400">{t('app:chats.select_subtitle')}</p>
      </div>
    </div>
  );
}
