import React, { useRef } from 'react';
import clsx from 'clsx';
import { useTranslation } from 'react-i18next';
import { useVirtualizer } from '@tanstack/react-virtual';
import { Badge } from '@/components/ui/Badge';
import { Pagination } from '@/components/ui/Pagination';
import { EmptyState } from '@/components/ui/EmptyState';
import type { UnifiedContact } from '@/api/hooks';

import { Loader2 } from 'lucide-react';

export type ContactViewMode = 'list' | 'table' | 'cards';

export interface ContactListProps {
  contacts: UnifiedContact[];
  selectedContactId: string | null;
  onSelectContact: (contact: UnifiedContact) => void;
  loading?: boolean;
  currentPage: number;
  total: number;
  pageSize: number;
  onPageChange: (page: number) => void;
  viewMode: ContactViewMode;
  sortBy: string;
  sortOrder: 'asc' | 'desc';
  onSortChange: (sortBy: string, sortOrder: 'asc' | 'desc') => void;
}

function TypeBadge({ type }: { type: string }) {
  const { t } = useTranslation();
  return (
    <Badge variant={type === 'company' ? 'primary' : 'info'}>
      {type === 'company' ? t('contacts.companies') : t('contacts.persons')}
    </Badge>
  );
}

function getDisplayName(c: UnifiedContact): string {
  return c.displayname || c.name || [c.firstname, c.surname].filter(Boolean).join(' ') || c.email_1 || c.id;
}

function getInitials(c: UnifiedContact): string {
  const name = getDisplayName(c);
  return name.charAt(0).toUpperCase();
}

function getCity(c: UnifiedContact): string {
  return c.mailing_city || c.visit_city || c.invoice_city || '—';
}

function getEmail(c: UnifiedContact): string {
  return c.email_1 || c.email_2 || '—';
}

function getPhone(c: UnifiedContact): string {
  return c.phone_1 || c.phone_2 || '—';
}

function getTags(c: UnifiedContact): string[] {
  if (!c.tags) return [];
  return c.tags.split(',').map((t) => t.trim()).filter(Boolean);
}

export function ContactList({
  contacts,
  selectedContactId,
  onSelectContact,
  loading,
  currentPage,
  total,
  pageSize,
  onPageChange,
  viewMode,
  sortBy,
  sortOrder,
  onSortChange,
}: ContactListProps) {
  const { t } = useTranslation();
  const scrollRef = useRef<HTMLDivElement>(null);

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

  const rowVirtualizer = useVirtualizer({
    count: shouldVirtualize ? contacts.length : 0,
    getScrollElement: () => scrollRef.current,
    estimateSize: () => viewMode === 'cards' ? 120 : 56,
    overscan: 8,
    enabled: shouldVirtualize,
  });

  if (loading) {
    return (
      <div className="flex items-center justify-center py-12" data-testid="contact-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 (contacts.length === 0) {
    return (
      <div data-testid="contact-list-empty">
        <EmptyState title={t('contacts.emptyTitle')} description={t('contacts.emptyDescription')} />
      </div>
    );
  }

  const totalPages = Math.ceil(total / pageSize);

  const handleSort = (field: string) => {
    if (sortBy === field) {
      onSortChange(field, sortOrder === 'asc' ? 'desc' : 'asc');
    } else {
      onSortChange(field, 'asc');
    }
  };

  // ── List View ──
  if (viewMode === 'list') {
    const renderContactItem = (contact: UnifiedContact) => (
      <li key={contact.id}>
        <button
          draggable
          onDragStart={(e) => {
            e.dataTransfer.setData('text/plain', contact.id);
            e.dataTransfer.effectAllowed = 'move';
          }}
          onClick={() => onSelectContact(contact)}
          className={clsx(
            'flex items-center gap-3 w-full px-3 py-2.5 text-left min-h-touch transition-colors',
            selectedContactId === contact.id
              ? 'bg-primary-50'
              : 'hover:bg-secondary-50',
          )}
          aria-current={selectedContactId === contact.id ? 'true' : undefined}
        >
          <div className="w-9 h-9 rounded-full bg-primary-100 flex items-center justify-center text-primary-700 font-semibold text-sm flex-shrink-0">
            {getInitials(contact)}
          </div>
          <div className="flex-1 min-w-0">
            <div className="flex items-center gap-2">
              <span className="font-medium text-sm text-secondary-900 truncate">{getDisplayName(contact)}</span>
              <TypeBadge type={contact.type} />
            </div>
            <div className="text-xs text-secondary-500 truncate">
              {getEmail(contact)} · {getCity(contact)}
            </div>
          </div>
        </button>
      </li>
    );

    return (
      <div className="flex flex-col h-full" data-testid="contact-list-view">
        <div ref={scrollRef} className="flex-1 overflow-y-auto">
          {shouldVirtualize ? (
            <ul className="divide-y divide-secondary-100" role="list" style={{ height: rowVirtualizer.getTotalSize(), position: 'relative' }}>
              {rowVirtualizer.getVirtualItems().map((virtualRow) => {
                const contact = contacts[virtualRow.index];
                return (
                  <div
                    key={contact.id}
                    style={{
                      position: 'absolute',
                      top: 0,
                      left: 0,
                      width: '100%',
                      transform: `translateY(${virtualRow.start}px)`,
                    }}
                  >
                    {renderContactItem(contact)}
                  </div>
                );
              })}
            </ul>
          ) : (
            <ul className="divide-y divide-secondary-100" role="list">
              {contacts.map((contact) => renderContactItem(contact))}
            </ul>
          )}
        </div>
        <Pagination
          currentPage={currentPage}
          totalPages={totalPages}
          total={total}
          pageSize={pageSize}
          onPageChange={onPageChange}
        />
      </div>
    );
  }

  // ── Table View ──
  if (viewMode === 'table') {
    const sortIcon = (field: string) => {
      if (sortBy !== field) return null;
      return sortOrder === 'asc' ? ' ▲' : ' ▼';
    };

    const renderContactRow = (contact: UnifiedContact) => (
      <tr
        key={contact.id}
        draggable
        onDragStart={(e) => {
          e.dataTransfer.setData('text/plain', contact.id);
          e.dataTransfer.effectAllowed = 'move';
        }}
        onClick={() => onSelectContact(contact)}
        className={clsx(
          'cursor-pointer transition-colors',
          selectedContactId === contact.id ? 'bg-primary-50' : 'hover:bg-secondary-50',
        )}
        aria-current={selectedContactId === contact.id ? 'true' : undefined}
      >
        <td className="px-3 py-2" onClick={(e) => e.stopPropagation()}>
          <input type="checkbox" className="rounded border-secondary-300" aria-label={getDisplayName(contact)} />
        </td>
        <td className="px-3 py-2"><TypeBadge type={contact.type} /></td>
        <td className="px-3 py-2 font-medium text-secondary-900">{getDisplayName(contact)}</td>
        <td className="px-3 py-2 text-secondary-600">{getEmail(contact)}</td>
        <td className="px-3 py-2 text-secondary-600">{getPhone(contact)}</td>
        <td className="px-3 py-2 text-secondary-600">{getCity(contact)}</td>
        <td className="px-3 py-2">
          <div className="flex flex-wrap gap-1">
            {getTags(contact).slice(0, 3).map((tag) => (
              <Badge key={tag} variant="secondary">{tag}</Badge>
            ))}
          </div>
        </td>
      </tr>
    );

    return (
      <div className="flex flex-col h-full" data-testid="contact-table-view">
        <div ref={scrollRef} className="flex-1 overflow-auto" style={shouldVirtualize ? { maxHeight: '70vh' } : undefined}>
          <table className="w-full text-sm">
            <thead className="sticky top-0 bg-white border-b border-secondary-200 z-10">
              <tr>
                <th className="px-3 py-2 text-left font-medium text-secondary-600 w-10">
                  <input type="checkbox" className="rounded border-secondary-300" aria-label={t('common.all')} />
                </th>
                <th
                  className="px-3 py-2 text-left font-medium text-secondary-600 cursor-pointer select-none"
                  onClick={() => handleSort('type')}
                  aria-sort={sortBy === 'type' ? (sortOrder === 'asc' ? 'ascending' : 'descending') : 'none'}
                >
                  {t('contacts.type')}{sortIcon('type')}
                </th>
                <th
                  className="px-3 py-2 text-left font-medium text-secondary-600 cursor-pointer select-none"
                  onClick={() => handleSort('displayname')}
                  aria-sort={sortBy === 'displayname' ? (sortOrder === 'asc' ? 'ascending' : 'descending') : 'none'}
                >
                  {t('contacts.fullName')}{sortIcon('displayname')}
                </th>
                <th
                  className="px-3 py-2 text-left font-medium text-secondary-600 cursor-pointer select-none"
                  onClick={() => handleSort('email_1')}
                  aria-sort={sortBy === 'email_1' ? (sortOrder === 'asc' ? 'ascending' : 'descending') : 'none'}
                >
                  {t('contacts.email')}{sortIcon('email_1')}
                </th>
                <th className="px-3 py-2 text-left font-medium text-secondary-600">{t('contacts.phone')}</th>
                <th
                  className="px-3 py-2 text-left font-medium text-secondary-600 cursor-pointer select-none"
                  onClick={() => handleSort('mailing_city')}
                  aria-sort={sortBy === 'mailing_city' ? (sortOrder === 'asc' ? 'ascending' : 'descending') : 'none'}
                >
                  {t('address.city')}{sortIcon('mailing_city')}
                </th>
                <th className="px-3 py-2 text-left font-medium text-secondary-600">{t('tags.title')}</th>
              </tr>
            </thead>
            <tbody className="divide-y divide-secondary-100">
              {shouldVirtualize ? (
                <>
                  {rowVirtualizer.getVirtualItems().map((virtualRow) => {
                    const contact = contacts[virtualRow.index];
                    return (
                      <React.Fragment key={contact.id}>
                        {virtualRow.index === 0 && (
                          <tr style={{ height: virtualRow.start }}>
                            <td colSpan={7} style={{ padding: 0, border: 'none' }} />
                          </tr>
                        )}
                        {renderContactRow(contact)}
                        {virtualRow.index === rowVirtualizer.getVirtualItems().length - 1 && (
                          <tr style={{ height: rowVirtualizer.getTotalSize() - virtualRow.end }}>
                            <td colSpan={7} style={{ padding: 0, border: 'none' }} />
                          </tr>
                        )}
                      </React.Fragment>
                    );
                  })}
                </>
              ) : (
                contacts.map((contact) => renderContactRow(contact))
              )}
            </tbody>
          </table>
        </div>
        <Pagination
          currentPage={currentPage}
          totalPages={totalPages}
          total={total}
          pageSize={pageSize}
          onPageChange={onPageChange}
        />
      </div>
    );
  }

  // ── Cards View ──
  const renderContactCard = (contact: UnifiedContact) => (
    <div
      key={contact.id}
      draggable
      onDragStart={(e) => {
        e.dataTransfer.setData('text/plain', contact.id);
        e.dataTransfer.effectAllowed = 'move';
      }}
      onClick={() => onSelectContact(contact)}
      className={clsx(
        'p-3 rounded-lg border cursor-pointer transition-colors min-h-touch',
        selectedContactId === contact.id
          ? 'border-primary-300 bg-primary-50'
          : 'border-secondary-200 bg-white hover:bg-secondary-50',
      )}
      role="button"
      tabIndex={0}
      aria-current={selectedContactId === contact.id ? 'true' : undefined}
    >
      <div className="flex items-center gap-3 mb-2">
        <div className="w-10 h-10 rounded-full bg-primary-100 flex items-center justify-center text-primary-700 font-semibold flex-shrink-0">
          {getInitials(contact)}
        </div>
        <div className="flex-1 min-w-0">
          <div className="flex items-center gap-2">
            <span className="font-medium text-sm text-secondary-900 truncate">{getDisplayName(contact)}</span>
          </div>
          <TypeBadge type={contact.type} />
        </div>
      </div>
      <div className="text-xs text-secondary-500 space-y-0.5">
        <div className="truncate">{getEmail(contact)}</div>
        <div className="truncate">{getPhone(contact)}</div>
        <div className="truncate">{getCity(contact)}</div>
      </div>
    </div>
  );

  return (
    <div className="flex flex-col h-full" data-testid="contact-cards-view">
      <div ref={scrollRef} className="flex-1 overflow-y-auto p-3">
        {shouldVirtualize ? (
          <div style={{ height: rowVirtualizer.getTotalSize(), position: 'relative' }}>
            <div className="grid grid-cols-1 sm:grid-cols-2 gap-3" style={{ position: 'absolute', top: 0, left: 0, right: 0 }}>
              {rowVirtualizer.getVirtualItems().map((virtualRow) => {
                const contact = contacts[virtualRow.index];
                return (
                  <div
                    key={contact.id}
                    style={{
                      position: 'absolute',
                      top: 0,
                      left: 0,
                      width: '100%',
                      transform: `translateY(${virtualRow.start}px)`,
                    }}
                  >
                    {renderContactCard(contact)}
                  </div>
                );
              })}
            </div>
          </div>
        ) : (
          <div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
            {contacts.map((contact) => renderContactCard(contact))}
          </div>
        )}
      </div>
      <Pagination
        currentPage={currentPage}
        totalPages={totalPages}
        total={total}
        pageSize={pageSize}
        onPageChange={onPageChange}
      />
    </div>
  );
}
