/**
 * Mail list component with pagination and virtual scrolling.
 * Shows list of mails in selected folder with seen/flagged indicators.
 */

import React, { useRef } from 'react';
import clsx from 'clsx';
import { useTranslation } from 'react-i18next';
import { useVirtualizer } from '@tanstack/react-virtual';
import type { Mail } from '@/api/mail';
import { decodeMimeHeader } from '@/api/mail';
import { EmptyState } from '@/components/ui/EmptyState';
import { Pagination } from '@/components/ui/Pagination';
import { ChevronUp, Loader2, Paperclip, Star } from 'lucide-react';
import { formatSmartDate } from '@/utils/date';

export interface MailListProps {
  mails: Mail[];
  selectedMailId: string | null;
  onSelectMail: (mail: Mail) => void;
  loading: boolean;
  currentPage: number;
  total: number;
  pageSize: number;
  onPageChange: (page: number) => void;
  selectedMailIds: Set<string>;
  onToggleSelect: (mailId: string) => void;
  onSelectAll: () => void;
  sortBy?: 'date' | 'from' | 'subject';
  sortOrder?: 'asc' | 'desc';
  onSortChange?: (sortBy: 'date' | 'from' | 'subject', sortOrder: 'asc' | 'desc') => void;
}

function formatDate(dateStr: string): string {
  return formatSmartDate(dateStr) || dateStr;
}

export function MailList({
  mails,
  selectedMailId,
  onSelectMail,
  loading,
  currentPage,
  total,
  pageSize,
  onPageChange,
  selectedMailIds,
  onToggleSelect,
  onSelectAll,
  sortBy = 'date',
  sortOrder = 'desc',
  onSortChange,
}: MailListProps) {
  const { t } = useTranslation();
  const totalPages = Math.ceil(total / pageSize);
  const allSelected = mails.length > 0 && mails.every((m) => selectedMailIds.has(m.id));
  const scrollRef = useRef<HTMLUListElement>(null);

  // Auto-skip virtualization for small datasets
  const shouldVirtualize = mails.length >= 50;

  const rowVirtualizer = useVirtualizer({
    count: shouldVirtualize ? mails.length : 0,
    getScrollElement: () => scrollRef.current,
    estimateSize: () => 80, // approx mail item height
    overscan: 8,
    enabled: shouldVirtualize,
  });

  const handleSortFieldChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
    const newSortBy = e.target.value as 'date' | 'from' | 'subject';
    onSortChange?.(newSortBy, sortOrder);
  };

  const handleSortOrderToggle = () => {
    const newOrder = sortOrder === 'asc' ? 'desc' : 'asc';
    onSortChange?.(sortBy, newOrder);
  };

  if (loading) {
    return (
      <div className="flex items-center justify-center py-12" data-testid="mail-list-loading">
        <Loader2 className="animate-spin h-5 w-5 text-secondary-400" aria-hidden="true" />
        <span className="ml-2 text-sm text-secondary-500">{t('common.loading')}</span>
      </div>
    );
  }

  if (mails.length === 0) {
    return (
      <EmptyState
        title={t('mail.noMails')}
        description={t('mail.noMailsDesc')}
        data-testid="mail-list-empty"
      />
    );
  }

  const renderMailItem = (mail: Mail) => (
    <li key={mail.id} role="listitem" className={clsx(selectedMailIds.has(mail.id) && 'bg-primary-50')}>
      <div className="flex items-start gap-2">
        <div className="flex items-center pt-3 pl-3 md:pl-4">
          <input
            type="checkbox"
            checked={selectedMailIds.has(mail.id)}
            onChange={() => onToggleSelect(mail.id)}
            className="w-4 h-4 rounded border-secondary-300 text-primary-600 focus:ring-primary-500"
            aria-label={t('mail.selectMail')}
            data-testid={`mail-checkbox-${mail.id}`}
          />
        </div>
        <button
          onClick={() => onSelectMail(mail)}
          className={clsx(
            'w-full text-left px-1 py-2 md:px-2 md:py-3 hover:bg-secondary-50 min-h-touch motion-safe:transition-colors',
            'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500',
            mail.id === selectedMailId && 'bg-primary-50',
            !mail.is_seen && 'font-semibold',
          )}
          aria-selected={mail.id === selectedMailId}
          data-testid={`mail-item-${mail.id}`}
        >
          <div className="flex items-center gap-2">
            {!mail.is_seen && (
              <span className="w-2 h-2 rounded-full bg-primary-500 flex-shrink-0" aria-label={t('mail.unread')} />
            )}
            {mail.is_flagged && (
              <span className="flex-shrink-0" aria-label={t('mail.flagged')}>
                {mail.flag_type === 'star' && <span className="text-sm">⭐</span>}
                {mail.flag_type === 'flag' && <span className="text-sm">🚩</span>}
                {mail.flag_type === 'bookmark' && <span className="text-sm">🔖</span>}
                {mail.flag_type === 'important' && <span className="text-sm">❗</span>}
                {mail.flag_type === 'question' && <span className="text-sm">❓</span>}
                {(!mail.flag_type || mail.flag_type === '') && (
                  <Star className="w-4 h-4 text-warning-500" fill="currentColor" />
                )}
              </span>
            )}
            {mail.has_attachments && (
              <Paperclip className="w-4 h-4 text-secondary-400 flex-shrink-0" aria-hidden="true" strokeWidth={2} />
            )}
            <div className="flex-1 min-w-0">
              <div className="flex items-center justify-between gap-2">
                <span className={clsx('text-sm truncate', !mail.is_seen ? 'text-secondary-900 font-semibold' : 'text-secondary-700')}>
                  {decodeMimeHeader(mail.from_name) || mail.from_address}
                </span>
                <span className="text-xs text-secondary-400 flex-shrink-0">{formatDate(mail.date)}</span>
              </div>
              <p className={clsx('text-sm truncate mt-0.5', !mail.is_seen ? 'text-secondary-800' : 'text-secondary-600')}>
                {decodeMimeHeader(mail.subject) || t('mail.noSubject')}
              </p>
              {mail.labels && mail.labels.length > 0 && (
                <div className="flex gap-1 mt-1">
                  {mail.labels.map((label) => (
                    <span key={label.id} className="inline-flex items-center px-2 py-0.5 rounded-full text-xs text-white" style={{ backgroundColor: label.color }}>
                      {label.name}
                    </span>
                  ))}
                </div>
              )}
            </div>
          </div>
        </button>
      </div>
    </li>
  );

  return (
    <div className="flex flex-col h-full" data-testid="mail-list" role="listbox" aria-label={t('mail.selectMail')}>
      {/* Select-all + Sort header in one row */}
      <div className="flex items-center justify-between gap-2 px-3 py-2 md:px-4 md:py-2 border-b border-secondary-200 bg-secondary-50 flex-shrink-0">
        <div className="flex items-center gap-2">
          <input
            type="checkbox"
            checked={allSelected}
            onChange={onSelectAll}
            className="w-4 h-4 rounded border-secondary-300 text-primary-600 focus:ring-primary-500"
            aria-label={t('mail.selectAll')}
            data-testid="mail-select-all"
          />
          {selectedMailIds.size > 0 && (
            <span className="text-xs text-secondary-600">
              {t('mail.selectedCount', { count: selectedMailIds.size })}
            </span>
          )}
        </div>
        {onSortChange && (
          <div className="flex items-center gap-2" data-testid="mail-sort-bar">
            <label htmlFor="mail-sort-by" className="text-xs text-secondary-600">
              {t('mail.sortBy')}:
            </label>
            <select
              id="mail-sort-by"
              value={sortBy}
              onChange={handleSortFieldChange}
              className="text-xs rounded border border-secondary-300 bg-white px-1.5 py-0.5 text-secondary-700 focus:outline-none focus:ring-1 focus:ring-primary-500"
              aria-label={t('mail.sortBy')}
              data-testid="mail-sort-by"
            >
              <option value="date">{t('mail.sortDate')}</option>
              <option value="from">{t('mail.sortFrom')}</option>
              <option value="subject">{t('mail.sortSubject')}</option>
            </select>
            <button
              onClick={handleSortOrderToggle}
              className="inline-flex items-center gap-1 text-xs rounded border border-secondary-300 bg-white px-1.5 py-0.5 text-secondary-700 hover:bg-secondary-100 focus:outline-none focus:ring-1 focus:ring-primary-500"
              aria-label={sortOrder === 'asc' ? t('mail.sortAsc') : t('mail.sortDesc')}
              title={sortOrder === 'asc' ? t('mail.sortAsc') : t('mail.sortDesc')}
              data-testid="mail-sort-order"
            >
              <ChevronUp className="w-3 h-3" aria-hidden="true" strokeWidth={2} />
              <span>{sortOrder === 'asc' ? t('mail.sortAsc') : t('mail.sortDesc')}</span>
            </button>
          </div>
        )}
      </div>
      {/* Mail list — scrolls, pagination stays fixed */}
      {shouldVirtualize ? (
        <ul
          ref={scrollRef}
          className="divide-y divide-secondary-100 flex-1 overflow-y-auto"
          role="list"
          style={{ contain: 'strict' }}
        >
          <li
            key="__virtual-spacer"
            style={{
              height: rowVirtualizer.getTotalSize(),
              position: 'relative',
              width: '100%',
            }}
          >
            {rowVirtualizer.getVirtualItems().map((virtualRow) => {
              const mail = mails[virtualRow.index];
              return (
                <div
                  key={mail.id}
                  style={{
                    position: 'absolute',
                    top: 0,
                    left: 0,
                    width: '100%',
                    transform: `translateY(${virtualRow.start}px)`,
                  }}
                >
                  {renderMailItem(mail)}
                </div>
              );
            })}
          </li>
        </ul>
      ) : (
        <ul className="divide-y divide-secondary-100 flex-1 overflow-y-auto" role="list">
          {mails.map((mail) => renderMailItem(mail))}
        </ul>
      )}
      {totalPages > 1 && (
        <div className="flex-shrink-0">
          <Pagination
            currentPage={currentPage}
            totalPages={totalPages}
            total={total}
            pageSize={pageSize}
            onPageChange={onPageChange}
          />
        </div>
      )}
    </div>
  );
}
