import React, { useState, useEffect, useCallback, useMemo, useRef } from 'react';
import { useNavigate, useSearchParams } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { FaFileInvoiceDollar, FaPlus, FaSearch, FaFilter, FaSync, FaEye, FaChevronDown, FaChevronUp, FaTimes, FaFileExport, FaEdit, FaCopy, FaCheckSquare, FaSquare } from 'react-icons/fa';
import salesInvoiceService, { SalesInvoice } from '../services/salesInvoiceService';
import ListPagination from '../components/ListPagination';
import DynamicExportModal from '../components/DynamicExportModal';
import { fetchAllRowsForExport } from '../utils/frappeListExport';
import { useListPageSelection } from '../hooks/useListPageSelection';

const getStatusStyle = (s: string, docstatus?: number) => {
  if (docstatus === 2) return 'bg-red-100 text-red-700';
  if (docstatus === 1 || s === 'Paid') return 'bg-green-100 text-green-800';
  if (s === 'Overdue') return 'bg-orange-100 text-orange-800';
  return 'bg-yellow-100 text-yellow-800';
};

const pageSize = 20;

const SalesInvoiceList: 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((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 [searchQuery, setSearchQuery]   = useState(searchParams.get('q') || '');
  const [sortBy, setSortBy]             = useState(searchParams.get('sort_by') || 'creation desc');

  const [invoices, setInvoices]     = useState<SalesInvoice[]>([]);
  const [totalCount, setTotalCount] = useState(0);
  const [loading, setLoading]       = useState(true);
  const [error, setError]           = useState<string | null>(null);
  const [showExportModal, setShowExportModal] = useState(false);
  const didInitUrlSync = useRef(false);
  const skipInitialSearchUrlSync = useRef(true);
  const searchDebounceRef = useRef<number | null>(null);
  const fetchSeqRef = useRef(0);

  const apiFilters = useMemo(() => {
    const f: Record<string, any> = {};
    if (statusFilter) f.status = statusFilter;
    if (searchQuery)  f.name   = ['like', `%${searchQuery}%`];
    return f;
  }, [statusFilter, searchQuery]);

  const fetchInvoices = useCallback(async () => {
    const reqId = ++fetchSeqRef.current;
    try {
      setLoading(true); setError(null);
      const [res, count] = await Promise.all([
        salesInvoiceService.getSalesInvoices({
          filters: apiFilters,
          limit_start: (currentPage - 1) * pageSize,
          limit_page_length: pageSize,
          order_by: sortBy,
        }),
        salesInvoiceService.getSalesInvoiceCount(apiFilters),
      ]);
      if (reqId !== fetchSeqRef.current) return;
      setInvoices(res.data);
      setTotalCount(count);
    } catch (err) {
      if (reqId !== fetchSeqRef.current) return;
      setError(err instanceof Error ? err.message : 'Failed to fetch invoices');
    } finally {
      if (reqId === fetchSeqRef.current) setLoading(false);
    }
  }, [apiFilters, currentPage, sortBy]);

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

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

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

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

  const clearFilters = () => {
    setStatusFilter(''); setSearchQuery(''); setSortBy('creation desc');
    setSearchParams(prev => {
      const n = new URLSearchParams(prev);
      ['status','q','sort_by'].forEach(k => n.delete(k));
      n.set('page', '1'); return n;
    });
  };

  // Auto-apply filters (no Apply button)
  useEffect(() => {
    if (!didInitUrlSync.current) {
      didInitUrlSync.current = true;
      return;
    }
    setSearchParamsRef.current(prev => {
      const n = new URLSearchParams(prev);
      statusFilter ? n.set('status', statusFilter) : n.delete('status');
      sortBy !== 'creation desc' ? n.set('sort_by', sortBy) : n.delete('sort_by');
      n.set('page', '1');
      return n;
    });
  }, [statusFilter, 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 n = new URLSearchParams(prev);
        searchQuery ? n.set('q', searchQuery) : n.delete('q');
        n.set('page', '1');
        return n;
      });
    }, 450);
    return () => {
      if (searchDebounceRef.current) window.clearTimeout(searchDebounceRef.current);
    };
  }, [searchQuery]);

  const hasActiveFilters = !!(statusFilter || searchQuery);
  const handleView = (name: string) => navigate(`/invoices/${encodeURIComponent(name)}`);
  const handleEdit = (name: string) => navigate(`/invoices/${encodeURIComponent(name)}?edit=1`);
  const handleDuplicate = (name: string) => navigate(`/invoices/new?duplicate=${encodeURIComponent(name)}`);

  return (
    <div className="p-6">
      <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">
          <button onClick={() => navigate('/projects')} className="text-sm text-gray-500 hover:text-indigo-600">Project Management</button>
          <span className="text-gray-400">/</span>
          <h1 className="text-2xl font-bold text-gray-900 dark:text-white flex items-center gap-2">
            <FaFileInvoiceDollar className="text-indigo-500" /> Sales Invoices
          </h1>
        </div>
        <div className="flex flex-wrap items-center gap-2">
          <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/25 px-1.5 py-0.5 rounded text-xs font-bold">{selectedRows.size}</span>
            )}
          </button>
          <button onClick={() => navigate('/invoices/new')} className="flex items-center gap-2 px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700">
            <FaPlus /> New Invoice
          </button>
        </div>
      </div>

      <DynamicExportModal
        isOpen={showExportModal}
        onClose={() => setShowExportModal(false)}
        doctype="Sales Invoice"
        selectedCount={selectedRows.size}
        pageCount={invoices.length}
        totalCount={totalCount}
        pageData={invoices}
        selectedRows={selectedRows}
        rowKey="name"
        onFetchAll={fetchAllForExport}
        fileNamePrefix="sales_invoices"
      />

      {/* 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-2.5 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-1.5 rounded-lg">
                {isFilterExpanded ? <FaChevronUp size={12} /> : <FaChevronDown size={12} />}
              </button>
              <FaFilter className="text-white" size={13} />
              <span className="text-white font-semibold text-sm">Filters</span>
              {hasActiveFilters && (
                <span className="bg-white text-blue-600 px-2 py-0.5 rounded-full text-xs font-bold">
                  {[statusFilter, searchQuery].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-indigo-700 rounded-full text-[10px] font-medium whitespace-nowrap">
                      <span className="font-semibold">ID:</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-indigo-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>
                  )}
                </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">Clear all</button>}
              <button onClick={fetchInvoices} 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">
            <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 uppercase tracking-wide mb-1">Invoice ID</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' && e.preventDefault()} placeholder="Search by ID…"
                    className="w-full pl-8 pr-3 py-1.5 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-400 focus:outline-none" />
                </div>
              </div>
              <div>
                <label className="block text-[10px] font-medium text-gray-600 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 rounded-lg focus:ring-2 focus:ring-indigo-400 focus:outline-none">
                  <option value="">All Status</option>
                  <option value="Draft">Draft</option>
                  <option value="Submitted">Submitted</option>
                  <option value="Paid">Paid</option>
                  <option value="Unpaid">Unpaid</option>
                  <option value="Overdue">Overdue</option>
                  <option value="Cancelled">Cancelled</option>
                </select>
              </div>
              <div>
                <label className="block text-[10px] font-medium text-gray-600 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 rounded-lg focus:ring-2 focus:ring-indigo-400 focus:outline-none">
                  <option value="creation desc">Created (newest)</option>
                  <option value="creation asc">Created (oldest)</option>
                  <option value="posting_date desc">Date (newest)</option>
                  <option value="grand_total desc">Amount (highest)</option>
                </select>
              </div>
            </div>
          </div>
        )}
      </div>

      {error && <div className="mb-4 p-3 bg-red-50 border border-red-200 rounded-lg text-red-700 text-sm">{error}</div>}

      <div className="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden">
        {loading ? (
          <div className="p-12 text-center text-gray-500">Loading…</div>
        ) : invoices.length === 0 ? (
          <div className="p-12 text-center">
            <FaFileInvoiceDollar className="text-4xl text-gray-300 mx-auto mb-3" />
            <p className="text-gray-500">No sales invoices yet</p>
          </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-indigo-600 dark:hover:text-indigo-400 transition-colors"
                      title={allOnPageSelected ? 'Deselect all' : 'Select all'}
                      aria-label="Select all on page"
                    >
                      {allOnPageSelected
                        ? <FaCheckSquare className="text-indigo-600 dark:text-indigo-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>
                  {['Invoice ID', 'Customer', 'Status', 'Date', 'Grand Total', 'Outstanding', ''].map(h => (
                    <th key={h} className="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">{h}</th>
                  ))}
                </tr>
              </thead>
              <tbody className="divide-y divide-gray-200 dark:divide-gray-700">
                {invoices.map((inv) => (
                  <tr key={inv.name} className={`hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors cursor-pointer ${selectedRows.has(inv.name) ? 'bg-indigo-50 dark:bg-indigo-900/20' : ''}`} onClick={() => handleView(inv.name)}>
                    <td className="w-10 px-4 py-3" onClick={e => e.stopPropagation()}>
                      <button
                        type="button"
                        onClick={() => toggleRow(inv.name)}
                        className="text-gray-500 dark:text-gray-400 hover:text-indigo-600 dark:hover:text-indigo-400 transition-colors"
                        aria-label={`Select ${inv.name}`}
                      >
                        {selectedRows.has(inv.name)
                          ? <FaCheckSquare className="text-indigo-600 dark:text-indigo-400" size={18} />
                          : <FaSquare size={18} />}
                      </button>
                    </td>
                    <td className="px-6 py-4 font-medium text-gray-900 dark:text-white text-sm">{inv.name}</td>
                    <td className="px-6 py-4 text-sm text-gray-700 dark:text-gray-300">{inv.customer_name || inv.customer || '-'}</td>
                    <td className="px-6 py-4">
                      <span className={`px-2 py-0.5 rounded text-xs font-medium ${getStatusStyle(inv.status || '', inv.docstatus)}`}>
                        {inv.status || 'Draft'}
                      </span>
                    </td>
                    <td className="px-6 py-4 text-sm text-gray-500">{inv.posting_date || '-'}</td>
                    <td className="px-6 py-4 text-sm font-medium text-gray-900 dark:text-white">{inv.currency || ''} {(inv.grand_total ?? 0).toFixed(2)}</td>
                    <td className="px-6 py-4 text-sm text-gray-500">{(inv.outstanding_amount ?? 0).toFixed(2)}</td>
                    <td className="px-6 py-3" onClick={e => e.stopPropagation()}>
                      <div className="flex items-center gap-1">
                        <button onClick={() => handleView(inv.name)} className="text-indigo-600 dark:text-indigo-400 hover:text-indigo-900 dark:hover:text-indigo-300 p-2 hover:bg-indigo-50 dark:hover:bg-indigo-900/30 rounded transition-colors" title="View"><FaEye /></button>
                        <button onClick={() => handleEdit(inv.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="Edit"><FaEdit /></button>
                        <button onClick={() => handleDuplicate(inv.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="Duplicate"><FaCopy /></button>
                      </div>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
        {totalPages > 1 && (
          <div className="border-t border-gray-200 px-4 py-3">
            <ListPagination currentPage={currentPage} totalPages={totalPages} totalCount={totalCount} pageSize={pageSize} onPageChange={setCurrentPage} />
          </div>
        )}
      </div>
    </div>
  );
};

export default SalesInvoiceList;
