import React, { useState, useEffect, useCallback, useMemo } from 'react';
import { useNavigate, useSearchParams } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { toast, ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import {
  FaFolderOpen,
  FaPlus,
  FaSync,
  FaEye,
  FaEdit,
  FaCopy,
  FaFileExport,
  FaCheckSquare,
  FaSquare,
  FaFilter,
  FaChevronDown,
  FaChevronUp,
  FaSearch,
} from 'react-icons/fa';
import ListPagination from '../components/ListPagination';
import DynamicExportModal from '../components/DynamicExportModal';
import projectService, { type Project } from '../services/projectService';
import { buildDateRangeFilters } from '../utils/listFilterUtils';
import { fetchAllRowsForExport } from '../utils/frappeListExport';

const pageSize = 20;

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

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

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

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

  const [projects, setProjects] = useState<Project[]>([]);
  const [totalCount, setTotalCount] = useState(0);
  const [loading, setLoading] = useState(true);
  const [selectedRows, setSelectedRows] = useState<Set<string>>(new Set());
  const [showExportModal, setShowExportModal] = useState(false);
  const [duplicating, setDuplicating] = useState<string | null>(null);

  const apiFilters = useMemo(() => {
    const f: Record<string, any> = {};
    if (statusFilter) f.status = statusFilter;
    if (priorityFilter) f.priority = priorityFilter;
    if (searchQuery) f.project_name = ['like', `%${searchQuery}%`];
    Object.assign(f, buildDateRangeFilters(dateFilterBy, dateStart, dateEnd));
    return f;
  }, [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 fetchAllForExport = useCallback(
    () => fetchAllRowsForExport({ doctype: 'Project', filters: apiFilters, order_by: orderBy }),
    [apiFilters, orderBy]
  );

  const load = useCallback(async () => {
    setLoading(true);
    try {
      const [res, cnt] = await Promise.all([
        projectService.getProjects({
          filters: apiFilters,
          limit_start: (currentPage - 1) * pageSize,
          limit_page_length: pageSize,
          order_by: orderBy,
        }),
        projectService.getProjectCount(apiFilters),
      ]);
      setProjects(res.data);
      setTotalCount(cnt);
    } catch (e: any) {
      toast.error(e.message || 'Failed to load projects');
    } finally {
      setLoading(false);
    }
  }, [apiFilters, currentPage, orderBy]);

  useEffect(() => {
    load();
  }, [load]);

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

  const toggleRow = (name: string) => {
    setSelectedRows(prev => {
      const n = new Set(prev);
      if (n.has(name)) n.delete(name);
      else n.add(name);
      return n;
    });
  };

  const allOnPageSelected = projects.length > 0 && projects.every(p => selectedRows.has(p.name));
  const someSelected = selectedRows.size > 0;

  const toggleSelectAllPage = () => {
    if (allOnPageSelected) {
      setSelectedRows(prev => {
        const n = new Set(prev);
        projects.forEach(p => n.delete(p.name));
        return n;
      });
    } else {
      setSelectedRows(prev => {
        const n = new Set(prev);
        projects.forEach(p => n.add(p.name));
        return n;
      });
    }
  };

  const handleDuplicate = async (e: React.MouseEvent, name: string) => {
    e.stopPropagation();
    try {
      setDuplicating(name);
      const newName = await projectService.copyProject(name);
      toast.success(`Duplicated: ${newName}`);
      await load();
      navigate(`/projects/list/${encodeURIComponent(newName)}`);
    } catch (err: any) {
      toast.error(err.message || 'Duplicate failed');
    } finally {
      setDuplicating(null);
    }
  };

  const applyFilters = () => {
    setSearchParams(prev => {
      const n = new URLSearchParams(prev);
      statusFilter ? n.set('status', statusFilter) : n.delete('status');
      priorityFilter ? n.set('priority', priorityFilter) : n.delete('priority');
      searchQuery ? n.set('q', searchQuery) : n.delete('q');
      dateFilterBy ? n.set('date_filter_by', dateFilterBy) : n.delete('date_filter_by');
      dateStart ? n.set('date_start', dateStart) : n.delete('date_start');
      dateEnd ? n.set('date_end', dateEnd) : n.delete('date_end');
      sortBy !== 'modified desc' ? n.set('sort_by', sortBy) : n.delete('sort_by');
      n.set('page', '1');
      return n;
    });
  };

  const clearFilters = () => {
    setStatusFilter('');
    setPriorityFilter('');
    setSearchQuery('');
    setDateFilterBy('');
    setDateStart('');
    setDateEnd('');
    setSortBy('modified desc');
    setSearchParams({ page: '1' });
  };

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

  return (
    <div className="p-6">
      <ToastContainer position="top-right" autoClose={3000} />

      <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-6">
        <div className="flex items-center gap-3">
          <div className="w-12 h-12 rounded-2xl bg-blue-600 flex items-center justify-center shadow-md">
            <FaFolderOpen className="text-white text-xl" />
          </div>
          <div>
            <h1 className="text-2xl font-bold text-gray-900 dark:text-white">{t('projects.listTitle', 'Projects')}</h1>
            <p className="text-sm text-gray-500 dark:text-gray-400">
              {totalCount} {t('projects.total', 'total')}
              {someSelected && (
                <span className="ml-2 text-blue-600 dark:text-blue-400">
                  • {selectedRows.size} {t('listPages.selected', 'selected')}
                </span>
              )}
            </p>
          </div>
        </div>
        <div className="flex flex-wrap items-center gap-2">
          <button
            type="button"
            onClick={() => setShowExportModal(true)}
            disabled={totalCount === 0}
            className="inline-flex items-center gap-2 px-4 py-2 rounded-lg bg-green-600 hover:bg-green-700 disabled:opacity-50 disabled:cursor-not-allowed text-white text-sm font-semibold shadow"
          >
            <FaFileExport size={14} /> {t('listPages.export', 'Export')}
          </button>
          <button
            type="button"
            onClick={() => navigate('/projects/list/new')}
            className="inline-flex items-center gap-2 px-4 py-2 rounded-lg bg-blue-600 hover:bg-blue-700 text-white text-sm font-semibold shadow"
          >
            <FaPlus size={14} /> {t('projects.newProject', 'New project')}
          </button>
        </div>
      </div>

      <div className="bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 shadow-sm mb-6 overflow-hidden">
        <div className="bg-gradient-to-r from-blue-500 to-blue-600 px-4 py-2.5">
          <div className="flex items-center justify-between gap-4">
            <div className="flex items-center gap-3">
              <button
                type="button"
                onClick={() => setIsFilterExpanded(v => !v)}
                className="text-white hover:bg-white/20 p-1.5 rounded-lg"
              >
                {isFilterExpanded ? <FaChevronUp size={12} /> : <FaChevronDown size={12} />}
              </button>
              <FaFilter className="text-white" size={14} />
              <span className="text-white font-semibold text-sm">{t('listPages.filters', 'Filters')}</span>
              {hasActiveFilters && (
                <span className="bg-white text-blue-600 px-2 py-0.5 rounded-full text-xs font-bold">
                  {[searchQuery, statusFilter, priorityFilter].filter(Boolean).length}
                </span>
              )}
            </div>
            <div className="flex items-center gap-2">
              {hasActiveFilters && (
                <button type="button" onClick={clearFilters} className="text-xs text-white/90 underline">
                  {t('listPages.clearFilters', 'Clear all')}
                </button>
              )}
              <button type="button" onClick={() => load()} className="text-white hover:bg-white/20 p-1.5 rounded-lg" title="Refresh">
                <FaSync size={12} className={loading ? 'animate-spin' : ''} />
              </button>
            </div>
          </div>
        </div>
        {isFilterExpanded && (
          <div className="p-4 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 border-t border-gray-100 dark:border-gray-700">
            <div>
              <label className="block text-[10px] font-semibold text-gray-500 uppercase 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
                  value={searchQuery}
                  onChange={e => setSearchQuery(e.target.value)}
                  onKeyDown={e => e.key === 'Enter' && applyFilters()}
                  className="w-full pl-8 pr-3 py-2 text-sm border rounded-lg dark:bg-gray-700 dark:border-gray-600"
                  placeholder="Project name…"
                />
              </div>
            </div>
            <div>
              <label className="block text-[10px] font-semibold text-gray-500 uppercase mb-1">Status</label>
              <select
                value={statusFilter}
                onChange={e => setStatusFilter(e.target.value)}
                className="w-full px-3 py-2 text-sm border rounded-lg dark:bg-gray-700 dark:border-gray-600"
              >
                <option value="">All</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-semibold text-gray-500 uppercase mb-1">Priority</label>
              <select
                value={priorityFilter}
                onChange={e => setPriorityFilter(e.target.value)}
                className="w-full px-3 py-2 text-sm border rounded-lg dark:bg-gray-700 dark:border-gray-600"
              >
                <option value="">All</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-semibold text-gray-500 uppercase mb-1">Sort</label>
              <select
                value={sortBy}
                onChange={e => setSortBy(e.target.value)}
                className="w-full px-3 py-2 text-sm border rounded-lg dark:bg-gray-700 dark:border-gray-600"
              >
                <option value="modified desc">Modified (newest)</option>
                <option value="modified asc">Modified (oldest)</option>
                <option value="creation desc">Created (newest)</option>
                <option value="name asc">ID (A–Z)</option>
              </select>
            </div>
            <div className="sm:col-span-2 lg:col-span-4 flex justify-end gap-2 pt-2">
              <button type="button" onClick={applyFilters} className="px-4 py-2 bg-blue-600 text-white text-sm rounded-lg hover:bg-blue-700">
                {t('listPages.applyFilters', 'Apply')}
              </button>
            </div>
          </div>
        )}
      </div>

      <div className="bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 overflow-hidden shadow-sm">
        <div className="overflow-x-auto">
          <table className="min-w-full text-sm">
            <thead>
              <tr className="bg-blue-600 text-left">
                <th className="px-3 py-3 w-12">
                  <button type="button" onClick={toggleSelectAllPage} className="text-white/90 hover:text-white p-1">
                    {allOnPageSelected ? <FaCheckSquare size={16} /> : <FaSquare size={16} />}
                  </button>
                </th>
                {['Project', 'Status', 'Priority', 'Customer', 'Progress', 'Dates', 'Actions'].map(h => (
                  <th key={h} className="px-4 py-3 text-[10px] font-semibold text-white/90 uppercase tracking-wider">
                    {h}
                  </th>
                ))}
              </tr>
            </thead>
            <tbody className="divide-y divide-gray-100 dark:divide-gray-700">
              {loading ? (
                <tr>
                  <td colSpan={8} className="text-center py-12 text-gray-400">
                    Loading…
                  </td>
                </tr>
              ) : projects.length === 0 ? (
                <tr>
                  <td colSpan={8} className="text-center py-12 text-gray-400">
                    No projects found
                  </td>
                </tr>
              ) : (
                projects.map(p => (
                  <tr
                    key={p.name}
                    className="hover:bg-blue-50/50 dark:hover:bg-gray-700/30 cursor-pointer"
                    onClick={() => navigate(`/projects/list/${encodeURIComponent(p.name)}`)}
                  >
                    <td className="px-3 py-3" onClick={e => e.stopPropagation()}>
                      <button type="button" onClick={() => toggleRow(p.name)} className="text-gray-500 hover:text-blue-600 p-1">
                        {selectedRows.has(p.name) ? <FaCheckSquare className="text-blue-600" /> : <FaSquare />}
                      </button>
                    </td>
                    <td className="px-4 py-3">
                      <span className="font-medium text-blue-600 dark:text-blue-400">{p.project_name || p.name}</span>
                      <div className="text-xs text-gray-400">{p.name}</div>
                    </td>
                    <td className="px-4 py-3">
                      <span className="px-2 py-0.5 rounded-full text-xs font-medium bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-200">
                        {p.status || '-'}
                      </span>
                    </td>
                    <td className="px-4 py-3">
                      <span className="px-2 py-0.5 rounded-full text-xs font-medium bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-200">
                        {p.priority || '-'}
                      </span>
                    </td>
                    <td className="px-4 py-3 text-gray-700 dark:text-gray-300">{p.customer_name || p.customer || '—'}</td>
                    <td className="px-4 py-3 text-gray-600">{p.percent_complete ?? 0}%</td>
                    <td className="px-4 py-3 text-xs text-gray-500">
                      {p.expected_start_date || '—'} → {p.expected_end_date || '—'}
                    </td>
                    <td className="px-4 py-3" onClick={e => e.stopPropagation()}>
                      <div className="flex items-center gap-2">
                        <button
                          type="button"
                          title="View"
                          onClick={() => navigate(`/projects/list/${encodeURIComponent(p.name)}`)}
                          className="p-1.5 rounded-lg hover:bg-blue-50 dark:hover:bg-blue-900/30 text-blue-600"
                        >
                          <FaEye size={15} />
                        </button>
                        <button
                          type="button"
                          title="Edit"
                          onClick={() => navigate(`/projects/list/${encodeURIComponent(p.name)}?edit=1`)}
                          className="p-1.5 rounded-lg hover:bg-green-50 dark:hover:bg-green-900/30 text-green-600"
                        >
                          <FaEdit size={14} />
                        </button>
                        <button
                          type="button"
                          title="Duplicate"
                          disabled={duplicating === p.name}
                          onClick={e => handleDuplicate(e, p.name)}
                          className="p-1.5 rounded-lg hover:bg-purple-50 dark:hover:bg-purple-900/30 text-purple-600 disabled:opacity-50"
                        >
                          <FaCopy size={14} />
                        </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>

      <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"
        defaultColumns={['name', 'project_name', 'status', 'priority', 'customer', 'customer_name', 'percent_complete', 'company', 'modified']}
        hiddenColumns={['docstatus', 'idx', 'naming_series']}
      />
    </div>
  );
};

export default ProjectList;
