import React, { useEffect, useRef, useState, useMemo, useCallback } from 'react';
import { useNavigate, useSearchParams } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { useProjectList } from '../hooks/useProject';
import ListPagination from '../components/ListPagination';
import { FaSearch, FaFilter, FaChevronDown, FaChevronUp, FaSync, FaEye, FaPlus, FaTimes, FaFileExport, FaEdit, FaCopy, FaCheckSquare, FaSquare, FaMicrophone } from 'react-icons/fa';
import { useListPageSelection } from '../hooks/useListPageSelection';
import { buildDateRangeFilters } from '../utils/listFilterUtils';
import type { Project } from '../services/projectService';
import DynamicExportModal from '../components/DynamicExportModal';
import { fetchAllRowsForExport } from '../utils/frappeListExport';
import VoiceStatusModal, { PROJECT_STATUS_OPTIONS } from '../components/VoiceStatusModal';

const getStatusStyle = (status: string) => {
  switch (status?.toLowerCase()) {
    case 'open':
      return 'bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-300';
    case 'completed':
      return 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-300';
    case 'cancelled':
      return 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300';
    default:
      return 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300';
  }
};

const getPriorityStyle = (priority: string) => {
  switch (priority?.toLowerCase()) {
    case 'high':
      return 'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-300';
    case 'medium':
      return 'bg-orange-100 text-orange-800 dark:bg-orange-900/30 dark:text-orange-300';
    case 'low':
      return 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-300';
    default:
      return 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300';
  }
};

const ProjectList: React.FC = () => {
  const { t } = useTranslation();
  const navigate = useNavigate();
  const [searchParams, setSearchParams] = useSearchParams();
  const setSearchParamsRef = useRef(setSearchParams);

  useEffect(() => {
    setSearchParamsRef.current = setSearchParams;
  }, [setSearchParams]);

  const currentPage = useMemo(() => {
    const p = parseInt(searchParams.get('page') || '1', 10);
    return Number.isNaN(p) || p < 1 ? 1 : p;
  }, [searchParams]);

  const setCurrentPage = useCallback(
    (pageOrUpdater: number | ((p: number) => number)) => {
      const next = typeof pageOrUpdater === 'function' ? pageOrUpdater(currentPage) : pageOrUpdater;
      setSearchParams((prev) => {
        const nextParams = new URLSearchParams(prev);
        nextParams.set('page', String(next));
        return nextParams;
      });
    },
    [currentPage, setSearchParams]
  );

  const pageSize = 20;
  const [isFilterExpanded, setIsFilterExpanded] = useState(false);
  const [statusFilter, setStatusFilter] = useState<string>(() => searchParams.get('status') || '');
  const [priorityFilter, setPriorityFilter] = useState<string>(() => searchParams.get('priority') || '');
  const [searchQuery, setSearchQuery] = useState<string>(() => searchParams.get('q') || '');
  const [dateFilterBy, setDateFilterBy] = useState<'' | 'creation' | 'modified'>(
    () => (searchParams.get('date_filter_by') as '' | 'creation' | 'modified') || ''
  );
  const [dateStart, setDateStart] = useState<string>(() => searchParams.get('date_start') || '');
  const [dateEnd, setDateEnd] = useState<string>(() => searchParams.get('date_end') || '');
  const [sortBy, setSortBy] = useState<string>(() => searchParams.get('sort_by') || 'modified desc');
  const [showExportModal, setShowExportModal] = useState(false);

  // ── Voice Command Assist ──────────────────────────────────────────
  const [showVoiceModal, setShowVoiceModal] = useState(false);
  // ─────────────────────────────────────────────────────────────────

  const didInitUrlSync = useRef(false);
  const skipInitialSearchUrlSync = useRef(true);
  const searchDebounceRef = useRef<number | null>(null);

  const apiFilters = useMemo(() => {
    const filters: Record<string, any> = {};
    if (statusFilter) filters['status'] = statusFilter;
    if (priorityFilter) filters['priority'] = priorityFilter;
    if (searchQuery) filters['project_name'] = ['like', `%${searchQuery}%`];
    Object.assign(filters, buildDateRangeFilters(dateFilterBy, dateStart, dateEnd));
    return filters;
  }, [statusFilter, priorityFilter, searchQuery, dateFilterBy, dateStart, dateEnd]);

  const orderBy = ['creation desc', 'creation asc', 'modified desc', 'modified asc', 'name asc', 'name desc'].includes(sortBy) ? sortBy : 'modified desc';

  const { projects, loading, error, totalCount, refetch } = useProjectList({
    filters: apiFilters,
    limit_start: (currentPage - 1) * pageSize,
    limit_page_length: pageSize,
    order_by: orderBy,
  });

  const selectionResetKey = useMemo(
    () => `${currentPage}|${sortBy}|${JSON.stringify(apiFilters)}`,
    [currentPage, sortBy, apiFilters],
  );
  const {
    selectedRows,
    toggleRow,
    toggleAllOnPage,
    allOnPageSelected,
    someOnPageSelected,
  } = useListPageSelection(projects, selectionResetKey);

  const fetchAllForExport = useCallback(
    () => fetchAllRowsForExport({ doctype: 'Project', filters: apiFilters, orderBy }),
    [apiFilters, orderBy],
  );

  const totalPages = Math.ceil(totalCount / pageSize);
  const formatDate = (dateStr: string) =>
    dateStr ? new Date(dateStr).toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' }) : '-';

  const clearFilters = () => {
    setStatusFilter('');
    setPriorityFilter('');
    setSearchQuery('');
    setDateFilterBy('');
    setDateStart('');
    setDateEnd('');
    setSortBy('modified desc');
    setSearchParams((prev) => {
      const next = new URLSearchParams(prev);
      next.delete('status');
      next.delete('priority');
      next.delete('q');
      next.delete('date_filter_by');
      next.delete('date_start');
      next.delete('date_end');
      next.delete('sort_by');
      next.set('page', '1');
      return next;
    });
  };

  const hasActiveFilters = !!statusFilter || !!priorityFilter || !!searchQuery || !!(dateFilterBy && (dateStart || dateEnd));

  const syncFiltersToUrl = useCallback(() => {
    setSearchParams((prev) => {
      const next = new URLSearchParams(prev);
      if (statusFilter) next.set('status', statusFilter);
      else next.delete('status');
      if (priorityFilter) next.set('priority', priorityFilter);
      else next.delete('priority');
      if (searchQuery) next.set('q', searchQuery);
      else next.delete('q');
      if (dateFilterBy) next.set('date_filter_by', dateFilterBy);
      else next.delete('date_filter_by');
      if (dateStart) next.set('date_start', dateStart);
      else next.delete('date_start');
      if (dateEnd) next.set('date_end', dateEnd);
      else next.delete('date_end');
      if (sortBy !== 'modified desc') next.set('sort_by', sortBy);
      else next.delete('sort_by');
      next.set('page', '1');
      return next;
    });
  }, [statusFilter, priorityFilter, searchQuery, dateFilterBy, dateStart, dateEnd, sortBy, setSearchParams]);

  useEffect(() => {
    if (!didInitUrlSync.current) {
      didInitUrlSync.current = true;
      return;
    }
    setSearchParamsRef.current((prev) => {
      const next = new URLSearchParams(prev);
      if (statusFilter) next.set('status', statusFilter);
      else next.delete('status');
      if (priorityFilter) next.set('priority', priorityFilter);
      else next.delete('priority');
      if (dateFilterBy) next.set('date_filter_by', dateFilterBy);
      else next.delete('date_filter_by');
      if (dateStart) next.set('date_start', dateStart);
      else next.delete('date_start');
      if (dateEnd) next.set('date_end', dateEnd);
      else next.delete('date_end');
      if (sortBy !== 'modified desc') next.set('sort_by', sortBy);
      else next.delete('sort_by');
      next.set('page', '1');
      return next;
    });
  }, [statusFilter, priorityFilter, dateFilterBy, dateStart, dateEnd, sortBy]);

  useEffect(() => {
    if (!didInitUrlSync.current) return;
    if (skipInitialSearchUrlSync.current) {
      skipInitialSearchUrlSync.current = false;
      return;
    }
    if (searchDebounceRef.current) window.clearTimeout(searchDebounceRef.current);
    searchDebounceRef.current = window.setTimeout(() => {
      setSearchParamsRef.current((prev) => {
        const next = new URLSearchParams(prev);
        if (searchQuery) next.set('q', searchQuery);
        else next.delete('q');
        next.set('page', '1');
        return next;
      });
    }, 450);
    return () => {
      if (searchDebounceRef.current) window.clearTimeout(searchDebounceRef.current);
    };
  }, [searchQuery]);

  const handleEdit = (projectName: string) => navigate(`/projects/list/${encodeURIComponent(projectName)}?edit=1`);
  const handleDuplicate = (projectName: string) => navigate(`/projects/list/new?duplicate=${encodeURIComponent(projectName)}`);

  return (
    <div className="p-6 bg-gray-50 dark:bg-gray-900 min-h-screen">
      <div className="flex items-center gap-2 text-sm mb-4">
        <button onClick={() => navigate('/projects')} className="text-gray-500 hover:text-blue-600 dark:text-gray-400 dark:hover:text-blue-400">{t('projects.moduleTitle')}</button>
        <span className="text-gray-400">/</span>
        <span className="text-gray-700 dark:text-gray-300">{t('projects.projectsDoctype')}</span>
      </div>

      {/* ── Page Header ──────────────────────────────────────────────── */}
      <div className="mb-6 flex flex-col gap-4 sm:flex-row sm:justify-between sm:items-center">
        <div>
          <h1 className="text-3xl font-bold text-gray-800 dark:text-white">{t('projects.title')}</h1>
          <p className="text-gray-600 dark:text-gray-400 mt-1">
            {t('projects.listTotal')}
            {totalCount} {totalCount !== 1 ? t('projects.listProjects') : t('projects.listProject')}
            {selectedRows.size > 0 && (
              <span className="ml-2 text-blue-600 dark:text-blue-400">
                • {selectedRows.size} {t('common.selected')}
              </span>
            )}
            {loading && (
              <span className="ml-2 inline-flex items-center gap-1 text-xs text-blue-600 dark:text-blue-400">
                <FaSync className="animate-spin h-3 w-3" />
                {t('common.updating')}
              </span>
            )}
          </p>
        </div>

        <div className="flex flex-wrap gap-3">
          {/* ── Voice Command Assist ───────────────────────────────── */}
          <button
            type="button"
            onClick={() => setShowVoiceModal(true)}
            className="bg-purple-600 hover:bg-purple-700 text-white px-4 py-2 rounded-lg flex items-center gap-2 shadow transition-all"
            title="Bulk-update project status by voice"
          >
            <FaMicrophone />
            <span className="font-medium">Voice Command Assist</span>
          </button>
          {/* ─────────────────────────────────────────────────────── */}

          <button
            type="button"
            onClick={() => setShowExportModal(true)}
            className="bg-green-600 hover:bg-green-700 text-white px-4 py-2 rounded-lg flex items-center gap-2 shadow transition-all disabled:opacity-50"
            disabled={totalCount === 0 && selectedRows.size === 0}
          >
            <FaFileExport />
            <span className="font-medium">{t('listPages.export')}</span>
            {selectedRows.size > 0 && (
              <span className="bg-white/20 px-1.5 py-0.5 rounded text-xs">{selectedRows.size}</span>
            )}
          </button>

          <button
            type="button"
            onClick={() => navigate('/projects/list/new')}
            className="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg flex items-center gap-2 shadow-lg transition-all hover:shadow-xl"
          >
            <FaPlus />
            <span className="font-medium">{t('projects.newProject')}</span>
          </button>
        </div>
      </div>

      {/* ── Export Modal ─────────────────────────────────────────────── */}
      <DynamicExportModal
        isOpen={showExportModal}
        onClose={() => setShowExportModal(false)}
        doctype="Project"
        selectedCount={selectedRows.size}
        pageCount={projects.length}
        totalCount={totalCount}
        pageData={projects}
        selectedRows={selectedRows}
        rowKey="name"
        onFetchAll={fetchAllForExport}
        fileNamePrefix="projects"
      />

      {/* ── Voice Status Modal ───────────────────────────────────────── */}
      <VoiceStatusModal
        isOpen={showVoiceModal}
        onClose={() => setShowVoiceModal(false)}
        selectedRows={selectedRows}
        onUpdateSuccess={() => {
          refetch();
        }}
        doctype="Project"
        fieldname="status"
        statusOptions={PROJECT_STATUS_OPTIONS}
        widgetTitle="Voice Project Status Update"
        showLanguageToggle={true}
        noSelectionLabel="project"
      />

      {/* ── Filter Panel ─────────────────────────────────────────────── */}
      <div className="isolate bg-white dark:bg-gray-800 rounded-lg shadow-lg border border-gray-200 dark:border-gray-700 mb-6">
        <div className="bg-gradient-to-r from-blue-500 to-blue-600 dark:from-blue-600 dark:to-blue-700 px-4 py-3 rounded-t-lg">
          <div className="flex items-center justify-between gap-4">
            <div className="flex items-center gap-3 flex-shrink-0">
              <button onClick={() => setIsFilterExpanded(v => !v)} className="text-white hover:bg-white/20 p-2 rounded-lg transition-all">
                {isFilterExpanded ? <FaChevronUp size={14} /> : <FaChevronDown size={14} />}
              </button>
              <div className="flex items-center gap-2">
                <FaFilter className="text-white" size={16} />
                <span className="text-white font-semibold text-sm">{t('listPages.filters')}</span>
              </div>
              {hasActiveFilters && (
                <span className="bg-white text-blue-600 px-2 py-0.5 rounded-full text-xs font-bold">
                  {[searchQuery, statusFilter, priorityFilter, dateFilterBy && dateStart].filter(Boolean).length}
                </span>
              )}
            </div>

            {hasActiveFilters && (
              <div className="flex-1 overflow-x-auto mx-2">
                <div className="flex items-center gap-2 py-0.5">
                  {searchQuery && (
                    <span className="inline-flex items-center gap-1 px-2 py-0.5 bg-white/90 text-blue-700 rounded-full text-[10px] font-medium whitespace-nowrap">
                      <span className="font-semibold">Name:</span> {searchQuery}
                      <button onClick={() => setSearchQuery('')}><FaTimes className="text-[9px] hover:text-red-500" /></button>
                    </span>
                  )}
                  {statusFilter && (
                    <span className="inline-flex items-center gap-1 px-2 py-0.5 bg-white/90 text-blue-700 rounded-full text-[10px] font-medium whitespace-nowrap">
                      <span className="font-semibold">Status:</span> {statusFilter}
                      <button onClick={() => setStatusFilter('')}><FaTimes className="text-[9px] hover:text-red-500" /></button>
                    </span>
                  )}
                  {priorityFilter && (
                    <span className="inline-flex items-center gap-1 px-2 py-0.5 bg-white/90 text-blue-700 rounded-full text-[10px] font-medium whitespace-nowrap">
                      <span className="font-semibold">Priority:</span> {priorityFilter}
                      <button onClick={() => setPriorityFilter('')}><FaTimes className="text-[9px] hover:text-red-500" /></button>
                    </span>
                  )}
                  {dateFilterBy && dateStart && (
                    <span className="inline-flex items-center gap-1 px-2 py-0.5 bg-white/90 text-blue-700 rounded-full text-[10px] font-medium whitespace-nowrap">
                      <span className="font-semibold">{dateFilterBy === 'creation' ? 'Created' : 'Modified'}:</span> {dateStart}{dateEnd ? ` – ${dateEnd}` : ''}
                      <button onClick={() => { setDateFilterBy(''); setDateStart(''); setDateEnd(''); }}><FaTimes className="text-[9px] hover:text-red-500" /></button>
                    </span>
                  )}
                </div>
              </div>
            )}

            <div className="flex items-center gap-2 flex-shrink-0">
              {hasActiveFilters && (
                <button onClick={clearFilters} className="text-white/80 hover:text-white text-xs underline whitespace-nowrap">Clear all</button>
              )}
              <button onClick={() => refetch()} className="text-white hover:bg-white/20 p-1.5 rounded-lg transition-all" title="Refresh">
                <FaSync size={12} className={loading ? 'animate-spin' : ''} />
              </button>
            </div>
          </div>
        </div>

        {isFilterExpanded && (
          <div className="p-4">
            <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
              <div>
                <label className="block text-[10px] font-medium text-gray-600 dark:text-gray-400 uppercase tracking-wide mb-1">Search</label>
                <div className="relative">
                  <FaSearch className="absolute left-2.5 top-1/2 -translate-y-1/2 text-gray-400 text-xs" />
                  <input type="text" value={searchQuery} onChange={e => setSearchQuery(e.target.value)} onKeyDown={e => e.key === 'Enter' && syncFiltersToUrl()} placeholder={t('projects.searchPlaceholder')}
                    className="w-full pl-8 pr-3 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-400 focus:outline-none" />
                </div>
              </div>
              <div>
                <label className="block text-[10px] font-medium text-gray-600 dark:text-gray-400 uppercase tracking-wide mb-1">Status</label>
                <select value={statusFilter} onChange={e => setStatusFilter(e.target.value)} className="w-full px-3 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-400 focus:outline-none">
                  <option value="">All Status</option>
                  <option value="Open">Open</option>
                  <option value="Completed">Completed</option>
                  <option value="Cancelled">Cancelled</option>
                </select>
              </div>
              <div>
                <label className="block text-[10px] font-medium text-gray-600 dark:text-gray-400 uppercase tracking-wide mb-1">Priority</label>
                <select value={priorityFilter} onChange={e => setPriorityFilter(e.target.value)} className="w-full px-3 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-400 focus:outline-none">
                  <option value="">All Priority</option>
                  <option value="High">High</option>
                  <option value="Medium">Medium</option>
                  <option value="Low">Low</option>
                </select>
              </div>
              <div>
                <label className="block text-[10px] font-medium text-gray-600 dark:text-gray-400 uppercase tracking-wide mb-1">Date Filter By</label>
                <select value={dateFilterBy} onChange={e => setDateFilterBy(e.target.value as '' | 'creation' | 'modified')} className="w-full px-3 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-400 focus:outline-none">
                  <option value="">None</option>
                  <option value="creation">Created</option>
                  <option value="modified">Modified</option>
                </select>
              </div>
              {dateFilterBy && (
                <>
                  <div>
                    <label className="block text-[10px] font-medium text-gray-600 dark:text-gray-400 uppercase tracking-wide mb-1">From</label>
                    <input type="date" value={dateStart} onChange={e => setDateStart(e.target.value)} className="w-full px-3 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-400 focus:outline-none" />
                  </div>
                  <div>
                    <label className="block text-[10px] font-medium text-gray-600 dark:text-gray-400 uppercase tracking-wide mb-1">To</label>
                    <input type="date" value={dateEnd} onChange={e => setDateEnd(e.target.value)} className="w-full px-3 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-400 focus:outline-none" />
                  </div>
                </>
              )}
              <div>
                <label className="block text-[10px] font-medium text-gray-600 dark:text-gray-400 uppercase tracking-wide mb-1">Sort By</label>
                <select value={sortBy} onChange={e => setSortBy(e.target.value)} className="w-full px-3 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-400 focus:outline-none">
                  <option value="modified desc">Modified (newest)</option>
                  <option value="creation desc">Created (newest)</option>
                  <option value="modified asc">Modified (oldest)</option>
                  <option value="creation asc">Created (oldest)</option>
                  <option value="name asc">Name A–Z</option>
                  <option value="name desc">Name Z–A</option>
                </select>
              </div>
            </div>
          </div>
        )}
      </div>

      {error && (
        <div className="mb-4 p-4 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg text-red-700 dark:text-red-300">
          {error}
        </div>
      )}

      {/* ── Table ────────────────────────────────────────────────────── */}
      <div className="bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden relative">
        {loading ? (
          <div className="p-12 text-center text-gray-500 dark:text-gray-400">{t('common.loading')}</div>
        ) : projects.length === 0 ? (
          <div className="p-12 text-center text-gray-500 dark:text-gray-400">{t('projects.noProjects')}</div>
        ) : (
          <div className="overflow-x-auto">
            <table className="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
              <thead className="bg-gray-100 dark:bg-gray-700 border-b border-gray-200 dark:border-gray-600">
                <tr>
                  <th className="w-10 px-4 py-3 text-left">
                    <button
                      type="button"
                      onClick={toggleAllOnPage}
                      className="text-gray-500 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
                      title={allOnPageSelected ? 'Deselect all' : 'Select all'}
                      aria-label="Select all on page"
                    >
                      {allOnPageSelected
                        ? <FaCheckSquare className="text-blue-600 dark:text-blue-400" size={18} />
                        : someOnPageSelected
                          ? (
                              <div className="relative inline-block">
                                <FaSquare size={18} />
                                <div className="absolute inset-0 flex items-center justify-center">
                                  <div className="w-2 h-0.5 bg-current" />
                                </div>
                              </div>
                            )
                          : <FaSquare size={18} />}
                    </button>
                  </th>
                  <th className="px-4 py-3 text-left text-xs font-medium text-gray-700 dark:text-gray-300 uppercase tracking-wider">
                    {t('projects.projectName')}
                  </th>
                  <th className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
                    {t('commonFields.status')}
                  </th>
                  <th className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
                    {t('commonFields.priority')}
                  </th>
                  <th className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
                    {t('projects.customer')}
                  </th>
                  <th className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
                    {t('projects.expectedEnd')}
                  </th>
                  <th className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
                    {t('projects.progress')}
                  </th>
                  <th className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">
                    {t('common.actions')}
                  </th>
                </tr>
              </thead>
              <tbody className="divide-y divide-gray-200 dark:divide-gray-700">
                {projects.map((project: Project) => (
                  <tr
                    key={project.name}
                    className={`hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors cursor-pointer ${selectedRows.has(project.name) ? 'bg-blue-50 dark:bg-blue-900/20' : ''}`}
                    onClick={() => navigate(`/projects/list/${project.name}`)}
                  >
                    <td className="w-10 px-4 py-3" onClick={e => e.stopPropagation()}>
                      <button
                        type="button"
                        onClick={() => toggleRow(project.name)}
                        className="text-gray-500 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
                        aria-label={`Select ${project.name}`}
                      >
                        {selectedRows.has(project.name)
                          ? <FaCheckSquare className="text-blue-600 dark:text-blue-400" size={18} />
                          : <FaSquare size={18} />}
                      </button>
                    </td>
                    <td className="px-6 py-4">
                      <span className="text-[15px] font-medium text-gray-900 dark:text-white hover:underline">
                        {project.project_name || project.name}
                      </span>
                      <span className="block text-xs text-gray-500 dark:text-gray-400">{project.name}</span>
                    </td>
                    <td className="px-6 py-4 whitespace-nowrap">
                      <span className={`px-2 py-0.5 rounded text-xs font-medium ${getStatusStyle(project.status || '')}`}>
                        {project.status || '-'}
                      </span>
                    </td>
                    <td className="px-6 py-4 whitespace-nowrap">
                      <span className={`px-2 py-0.5 rounded text-xs font-medium ${getPriorityStyle(project.priority || '')}`}>
                        {project.priority || '-'}
                      </span>
                    </td>
                    <td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700 dark:text-gray-300">{project.customer || '-'}</td>
                    <td className="px-6 py-4 whitespace-nowrap text-sm text-gray-700 dark:text-gray-300">{formatDate(project.expected_end_date || '')}</td>
                    <td className="px-6 py-4 whitespace-nowrap">
                      <div className="flex items-center gap-2">
                        <div className="flex-1 h-2 bg-gray-200 dark:bg-gray-600 rounded-full overflow-hidden max-w-[80px]">
                          <div
                            className="h-full bg-blue-500 rounded-full"
                            style={{ width: `${project.percent_complete ?? 0}%` }}
                          />
                        </div>
                        <span className="text-xs text-gray-600 dark:text-gray-400">{project.percent_complete ?? 0}%</span>
                      </div>
                    </td>
                    <td className="px-6 py-4 whitespace-nowrap text-sm font-medium" onClick={(e) => e.stopPropagation()}>
                      <div className="flex items-center gap-1">
                        <button
                          type="button"
                          onClick={() => navigate(`/projects/list/${project.name}`)}
                          className="text-blue-600 dark:text-blue-400 hover:text-blue-900 dark:hover:text-blue-300 p-2 hover:bg-blue-50 dark:hover:bg-blue-900/30 rounded transition-colors"
                          title={t('common.view')}
                          aria-label={t('common.view')}
                        >
                          <FaEye />
                        </button>
                        <button
                          type="button"
                          onClick={() => handleEdit(project.name)}
                          className="text-green-600 dark:text-green-400 hover:text-green-900 dark:hover:text-green-300 p-2 hover:bg-green-50 dark:hover:bg-green-900/30 rounded transition-colors"
                          title={t('common.edit', 'Edit')}
                          aria-label={t('common.edit', 'Edit')}
                        >
                          <FaEdit />
                        </button>
                        <button
                          type="button"
                          onClick={() => handleDuplicate(project.name)}
                          className="text-purple-600 dark:text-purple-400 hover:text-purple-900 dark:hover:text-purple-300 p-2 hover:bg-purple-50 dark:hover:bg-purple-900/30 rounded transition-colors"
                          title={t('common.duplicate', 'Duplicate')}
                          aria-label={t('common.duplicate', 'Duplicate')}
                        >
                          <FaCopy />
                        </button>
                      </div>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}

        {totalPages > 1 && (
          <div className="border-t border-gray-200 dark:border-gray-700 px-4 py-3">
            <ListPagination
              currentPage={currentPage}
              totalPages={totalPages}
              totalCount={totalCount}
              pageSize={pageSize}
              onPageChange={setCurrentPage}
            />
          </div>
        )}
      </div>
    </div>
  );
};

export default ProjectList;
