import React, { useState, useEffect, useCallback } from 'react';
import { useParams, useNavigate, useSearchParams } from 'react-router-dom';
import {
  FaArrowLeft, FaSave, FaEdit, FaTimes, FaPlus, FaTrash,
  FaCheckCircle, FaTimesCircle, FaSpinner, FaFileInvoiceDollar,
  FaChevronDown, FaChevronRight, FaPaperPlane, FaPencilAlt, FaMoneyBillWave,
} from 'react-icons/fa';
import { toast, ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import salesInvoiceService, { SalesInvoice, SalesInvoiceItem } from '../services/salesInvoiceService';
import type { SalesTaxCharge } from '../services/salesOrderService';
import LinkField from '../components/LinkField';
import ActivityLog from '../components/ActivityLog';
import {
  DEFAULT_COMPANY, DEFAULT_CURRENCY, DEFAULT_SALES_TAXES_TEMPLATE,
  taxRatePercent, displayTxnCurrency,
} from '../constants/orgDefaults';

// ─── Helpers ─────────────────────────────────────────────────────────────────
const FL: React.FC<{ children: React.ReactNode; required?: boolean }> = ({ children, required }) => (
  <label className="block text-[11px] font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wide mb-1">
    {children}{required && <span className="text-red-500 ml-0.5">*</span>}
  </label>
);
const RV: React.FC<{ children?: React.ReactNode }> = ({ children }) => (
  <div className="px-3 py-2 text-sm text-gray-800 dark:text-gray-200 bg-gray-50 dark:bg-gray-800/60 rounded min-h-[34px] flex items-center">
    {children || <span className="text-gray-400">-</span>}
  </div>
);
const inputCls = 'w-full px-3 py-2 text-sm border border-gray-300 dark:border-gray-600 rounded bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:outline-none focus:ring-1 focus:ring-indigo-400';
const numCls   = inputCls + ' text-right';
const inlineTxt = 'w-full px-2 py-1 text-xs border border-gray-300 dark:border-gray-600 rounded bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:outline-none focus:ring-1 focus:ring-indigo-400';
const inlineNum = inlineTxt + ' text-right';

// ── Collapsible inside row editor ──
const RGroup: React.FC<{ title: string; children: React.ReactNode; defaultOpen?: boolean }> = ({ title, children, defaultOpen = false }) => {
  const [open, setOpen] = useState(defaultOpen);
  return (
    <div className="border-t border-gray-200 dark:border-gray-600 mt-3 pt-1">
      <button type="button" onClick={() => setOpen(o => !o)}
        className="flex items-center gap-2 py-1 text-xs font-semibold text-blue-600 dark:text-blue-400 hover:underline">
        {open ? <FaChevronDown size={9} /> : <FaChevronRight size={9} />}
        {title}
      </button>
      {open && <div className="mt-2">{children}</div>}
    </div>
  );
};

// ── Page-level collapsible ──
const Section: React.FC<{ title: string; children: React.ReactNode; defaultOpen?: boolean }> = ({ title, children, defaultOpen = true }) => {
  const [open, setOpen] = useState(defaultOpen);
  return (
    <div className="border-t border-gray-100 dark:border-gray-700">
      <button type="button" onClick={() => setOpen(o => !o)} className="w-full flex items-center justify-between px-6 py-3 hover:bg-gray-50 dark:hover:bg-gray-700/30">
        <span className="text-sm font-semibold text-gray-700 dark:text-gray-300">{title}</span>
        {open ? <FaChevronDown className="text-gray-400 text-xs" /> : <FaChevronRight className="text-gray-400 text-xs" />}
      </button>
      {open && <div className="px-6 pb-5">{children}</div>}
    </div>
  );
};

const emptyItem = (): Partial<SalesInvoiceItem> => ({
  item_code: '', item_name: '', description: '', qty: 1, uom: '',
  stock_uom: '', conversion_factor: 1, rate: 0, amount: 0,
  price_list_rate: 0, discount_percentage: 0, net_rate: 0, net_amount: 0,
  income_account: '', expense_account: '', item_tax_template: '',
  is_free_item: 0, grant_commission: 1,
});

/** ERPNext uses `sales_order` / `delivery_note` on Sales Invoice Item; DN rows use `against_sales_order`. */
const cleanSiLink = (v: any) => {
  if (v == null || v === '') return undefined;
  const s = String(v);
  if (s.toLowerCase() === 'none') return undefined;
  return s;
};

const normalizeSiItemFromApi = (it: any) => {
  const salesOrder = cleanSiLink(it.sales_order ?? it.against_sales_order);
  const deliveryNote = cleanSiLink(it.delivery_note ?? it.against_delivery_note);
  return {
    ...it,
    sales_order: salesOrder,
    delivery_note: deliveryNote,
    so_detail: cleanSiLink(it.so_detail),
    dn_detail: cleanSiLink(it.dn_detail),
    against_sales_order: salesOrder,
    against_delivery_note: deliveryNote,
  };
};

const mapSiItemToFrappePayload = (it: any, idx: number) => {
  const salesOrder = cleanSiLink(it.sales_order ?? it.against_sales_order);
  const deliveryNote = cleanSiLink(it.delivery_note ?? it.against_delivery_note);
  return {
    ...(it.name ? { name: it.name } : {}),
    item_code: it.item_code,
    item_name: it.item_name || it.item_code,
    description: it.description || undefined,
    qty: it.qty ?? 1,
    uom: it.uom || undefined,
    stock_uom: it.stock_uom || undefined,
    conversion_factor: it.conversion_factor ?? 1,
    price_list_rate: it.price_list_rate ?? 0,
    discount_percentage: it.discount_percentage ?? 0,
    rate: it.rate ?? 0,
    amount: it.amount ?? 0,
    item_tax_template: it.item_tax_template || undefined,
    is_free_item: it.is_free_item ?? 0,
    income_account: it.income_account || undefined,
    expense_account: it.expense_account || undefined,
    cost_center: (it as any).cost_center || undefined,
    project: (it as any).project || undefined,
    sales_order: salesOrder,
    delivery_note: deliveryNote,
    so_detail: cleanSiLink(it.so_detail),
    dn_detail: cleanSiLink(it.dn_detail),
    pos_invoice: cleanSiLink((it as any).pos_invoice),
    pos_invoice_item: (it as any).pos_invoice_item || undefined,
    delivered_qty: (it as any).delivered_qty != null ? (it as any).delivered_qty : undefined,
    idx: idx + 1,
  };
};

// ─── Item Row Editor ─────────────────────────────────────────────────────────
const ItemRowEditor: React.FC<{
  item: Partial<SalesInvoiceItem>;
  rowNo: number;
  onChange: (k: keyof SalesInvoiceItem, v: any) => void;
  onClose: () => void;
  onDelete: () => void;
  onInsertBelow: () => void;
}> = ({ item, rowNo, onChange, onClose, onDelete, onInsertBelow }) => {

  const [fetchingItem, setFetchingItem] = useState(false);

  // Auto-fetch item details when item_code changes
  const fetchItemDetails = useCallback(async (code: string) => {
    if (!code) return;
    try {
      setFetchingItem(true);
      const r = await fetch(`/api/resource/Item/${encodeURIComponent(code)}`, { credentials: 'include' });
      const body = await r.json();
      const d = body.data;
      if (!d) return;
      if (d.item_name)         onChange('item_name', d.item_name);
      if (d.description)       onChange('description', d.description);
      if (d.stock_uom)         onChange('stock_uom', d.stock_uom);
      if (d.sales_uom || d.stock_uom) onChange('uom', d.sales_uom || d.stock_uom);
    } catch { /* ignore */ } finally {
      setFetchingItem(false);
    }
  }, [onChange]);

  // Auto-calc is handled by parent updateItem; just call onChange
  const set = (k: keyof SalesInvoiceItem, v: any) => onChange(k, v);

  return (
    <tr>
      <td colSpan={7} className="p-0">
        <div className="border border-blue-300 dark:border-blue-600 rounded-lg mx-2 my-1 bg-white dark:bg-gray-800 shadow-md">
          {/* Editor header */}
          <div className="flex items-center justify-between px-4 py-2 bg-blue-50 dark:bg-blue-900/30 rounded-t-lg border-b border-blue-200 dark:border-blue-700">
            <span className="text-sm font-semibold text-blue-700 dark:text-blue-300">
              Editing Row #{rowNo} {fetchingItem && <FaSpinner className="inline animate-spin ml-1 text-xs" />}
            </span>
            <div className="flex items-center gap-2">
              <button onClick={onInsertBelow} className="px-2 py-1 text-xs border border-gray-300 dark:border-gray-600 rounded hover:bg-gray-50 dark:hover:bg-gray-700 text-gray-600 dark:text-gray-300">
                Insert Below
              </button>
              <button onClick={onDelete} className="px-2 py-1 text-xs border border-red-300 dark:border-red-700 rounded text-red-500 hover:bg-red-50 dark:hover:bg-red-900/20">
                Delete
              </button>
              <button onClick={onClose} className="p-1 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300">
                <FaTimes size={13} />
              </button>
            </div>
          </div>

          {/* Fields grid */}
          <div className="p-4 space-y-4">
            {/* Row 1: Item + Item Name */}
            <div className="grid grid-cols-2 gap-4">
              <div>
                <FL required>Item</FL>
                <LinkField
                  label="Item" hideLabel doctype="Item"
                  value={item.item_code || ''}
                  onChange={v => { onChange('item_code', v); fetchItemDetails(v); }}
                  placeholder="Select item…"
                />
              </div>
              <div>
                <FL required>Item Name</FL>
                <input type="text" value={item.item_name || ''} onChange={e => onChange('item_name', e.target.value)} className={inputCls} placeholder="Item name…" />
              </div>
            </div>

            {/* Description */}
            <RGroup title="Description" defaultOpen={!!(item.description)}>
              <FL>Description</FL>
              <textarea rows={2} value={item.description || ''} onChange={e => onChange('description', e.target.value)} className={inputCls} placeholder="Description…" />
            </RGroup>

            {/* Qty / UOM row */}
            <div className="grid grid-cols-4 gap-4">
              <div>
                <FL required>Quantity</FL>
                <input type="number" min={0} step="1" value={item.qty ?? 1} onChange={e => set('qty', parseFloat(e.target.value) || 0)} className={numCls} />
              </div>
              <div>
                <FL required>UOM</FL>
                <input type="text" value={item.uom || ''} onChange={e => onChange('uom', e.target.value)} className={inputCls} placeholder="UOM…" />
              </div>
              <div>
                <FL>Stock UOM</FL>
                <input type="text" value={item.stock_uom || ''} onChange={e => onChange('stock_uom', e.target.value)} className={inputCls} placeholder="Stock UOM…" />
              </div>
              <div>
                <FL required>UOM Conversion Factor</FL>
                <input type="number" min={0} step="0.001" value={item.conversion_factor ?? 1} onChange={e => onChange('conversion_factor', parseFloat(e.target.value) || 1)} className={numCls} />
              </div>
            </div>

            {/* Price / Rate / Amount */}
            <div className="grid grid-cols-4 gap-4">
              <div>
                <FL>Price List Rate</FL>
                <input type="number" min={0} step="0.01" value={item.price_list_rate ?? 0} onChange={e => onChange('price_list_rate', parseFloat(e.target.value) || 0)} className={numCls} />
              </div>
              <div>
                <FL>Discount %</FL>
                <input type="number" min={0} max={100} step="0.01" value={item.discount_percentage ?? 0} onChange={e => onChange('discount_percentage', parseFloat(e.target.value) || 0)} className={numCls} />
              </div>
              <div>
                <FL required>Rate</FL>
                <input type="number" min={0} step="0.01" value={item.rate ?? 0} onChange={e => set('rate', parseFloat(e.target.value) || 0)} className={numCls} />
              </div>
              <div>
                <FL required>Amount</FL>
                <div className="px-3 py-2 text-sm font-semibold text-gray-800 dark:text-gray-100 bg-gray-50 dark:bg-gray-700 rounded text-right">
                  {(item.amount || 0).toFixed(2)}
                </div>
              </div>
            </div>

            <div className="grid grid-cols-4 gap-4">
              <div>
                <FL>Net Rate</FL>
                <div className="px-3 py-2 text-sm text-gray-600 dark:text-gray-300 bg-gray-50 dark:bg-gray-700 rounded text-right">
                  {(item.net_rate || item.rate || 0).toFixed(2)}
                </div>
              </div>
              <div>
                <FL>Net Amount</FL>
                <div className="px-3 py-2 text-sm text-gray-600 dark:text-gray-300 bg-gray-50 dark:bg-gray-700 rounded text-right">
                  {(item.net_amount || item.amount || 0).toFixed(2)}
                </div>
              </div>
              <div>
                <FL>Item Tax Template</FL>
                <input type="text" value={item.item_tax_template || ''} onChange={e => onChange('item_tax_template', e.target.value)} className={inputCls} placeholder="Tax template…" />
              </div>
              <div className="flex flex-col justify-end gap-2 pb-1">
                <label className="flex items-center gap-2 cursor-pointer select-none">
                  <input type="checkbox" checked={!!(item.is_free_item)} onChange={e => onChange('is_free_item', e.target.checked ? 1 : 0)} className="rounded border-gray-300" />
                  <span className="text-xs text-gray-600 dark:text-gray-400">Is Free Item</span>
                </label>
                <label className="flex items-center gap-2 cursor-pointer select-none">
                  <input type="checkbox" checked={item.grant_commission !== 0} onChange={e => onChange('grant_commission', e.target.checked ? 1 : 0)} className="rounded border-gray-300" />
                  <span className="text-xs text-gray-600 dark:text-gray-400">Grant Commission</span>
                </label>
              </div>
            </div>

            {/* Accounting Details */}
            <RGroup title="Accounting Details" defaultOpen>
              <div className="grid grid-cols-2 gap-4">
                <div>
                  <FL required>Income Account</FL>
                  <LinkField label="Income Account" hideLabel doctype="Account" value={item.income_account || ''}
                    onChange={v => onChange('income_account', v)} placeholder="Income account…" />
                </div>
                <div>
                  <FL>Expense Account</FL>
                  <LinkField label="Expense Account" hideLabel doctype="Account" value={item.expense_account || ''}
                    onChange={v => onChange('expense_account', v)} placeholder="Expense account…" />
                </div>
              </div>
            </RGroup>

            {/* Accounting Dimensions */}
            <RGroup title="Accounting Dimensions">
              <div className="grid grid-cols-2 gap-4">
                <div>
                  <FL>Cost Center</FL>
                  <LinkField label="Cost Center" hideLabel doctype="Cost Center" value={item.cost_center || ''}
                    onChange={v => onChange('cost_center', v)} placeholder="Cost center…" />
                </div>
                <div>
                  <FL>Project</FL>
                  <LinkField label="Project" hideLabel doctype="Project" value={item.project || ''}
                    onChange={v => onChange('project', v)} placeholder="Project…" />
                </div>
              </div>
            </RGroup>

            {/* References — ERPNext fieldnames: sales_order, delivery_note, dn_detail, so_detail */}
            <RGroup title="References" defaultOpen={!!(
              cleanSiLink((item as any).sales_order ?? (item as any).against_sales_order)
              || cleanSiLink((item as any).delivery_note ?? (item as any).against_delivery_note)
              || cleanSiLink((item as any).pos_invoice)
            )}>
              <div className="grid grid-cols-2 gap-4">
                <div>
                  <FL>Sales Order</FL>
                  <LinkField label="Sales Order" hideLabel doctype="Sales Order"
                    value={cleanSiLink((item as any).sales_order ?? (item as any).against_sales_order) || ''}
                    onChange={v => { onChange('sales_order' as any, v); onChange('against_sales_order' as any, v); }}
                    placeholder="Sales Order…" />
                </div>
                <div>
                  <FL>Delivery Note</FL>
                  <LinkField label="Delivery Note" hideLabel doctype="Delivery Note"
                    value={cleanSiLink((item as any).delivery_note ?? (item as any).against_delivery_note) || ''}
                    onChange={v => { onChange('delivery_note' as any, v); onChange('against_delivery_note' as any, v); }}
                    placeholder="Delivery Note…" />
                </div>
                <div>
                  <FL>POS Invoice</FL>
                  <LinkField label="POS Invoice" hideLabel doctype="POS Invoice"
                    value={(item as any).pos_invoice || ''}
                    onChange={v => onChange('pos_invoice' as any, v)}
                    placeholder="POS Invoice…" />
                </div>
                <div>
                  <FL>Delivered Qty</FL>
                  <div className="px-3 py-2 text-sm text-gray-700 dark:text-gray-200 bg-gray-50 dark:bg-gray-700 rounded">
                    {(item as any).delivered_qty != null ? +(item as any).delivered_qty : '—'}
                  </div>
                </div>
              </div>
            </RGroup>
          </div>
        </div>
      </td>
    </tr>
  );
};

const SITaxRowEditor: React.FC<{
  tax: Partial<SalesTaxCharge>; rowNo: number;
  onChange: (k: keyof SalesTaxCharge, v: any) => void;
  onClose: () => void; onDelete: () => void; onInsertBelow: () => void;
}> = ({ tax, rowNo, onChange, onClose, onDelete, onInsertBelow }) => (
  <tr>
    <td colSpan={7} className="p-0">
      <div className="border border-blue-300 dark:border-blue-600 rounded-lg mx-2 my-1 bg-white dark:bg-gray-800 shadow-md">
        <div className="flex items-center justify-between px-4 py-2 bg-blue-50 dark:bg-blue-900/30 rounded-t-lg border-b border-blue-200">
          <span className="text-sm font-semibold text-blue-700 dark:text-blue-300">Tax Row #{rowNo}</span>
          <div className="flex items-center gap-2">
            <button type="button" onClick={onInsertBelow} className="px-2 py-1 text-xs border border-gray-300 rounded hover:bg-gray-50 dark:hover:bg-gray-700 text-gray-600 dark:text-gray-300">Insert Below</button>
            <button type="button" onClick={onDelete} className="px-2 py-1 text-xs border border-red-300 rounded text-red-500 hover:bg-red-50 dark:hover:bg-red-900/20">Delete</button>
            <button type="button" onClick={onClose} className="p-1 text-gray-400 hover:text-gray-600"><FaTimes size={13} /></button>
          </div>
        </div>
        <div className="p-4 space-y-4">
          <div className="grid grid-cols-2 gap-4">
            <div><FL required>Type</FL>
              <select value={tax.charge_type || ''} onChange={e => onChange('charge_type', e.target.value)} className={inputCls}>
                <option value="">Select type…</option>
                <option value="Actual">Actual</option>
                <option value="On Net Total">On Net Total</option>
                <option value="On Previous Row Amount">On Previous Row Amount</option>
                <option value="On Previous Row Total">On Previous Row Total</option>
                <option value="On Item Quantity">On Item Quantity</option>
                <option value="Inter Company Transaction">Inter Company Transaction</option>
              </select>
            </div>
            <div><FL>Description</FL>
              <textarea rows={3} value={tax.description || ''} onChange={e => onChange('description', e.target.value)} className={inputCls} placeholder="Description…" />
            </div>
          </div>
          <div><FL required>Account Head</FL>
            <LinkField label="Account Head" hideLabel doctype="Account" value={tax.account_head || ''} onChange={v => onChange('account_head', v)} placeholder="Account…" />
          </div>
          <div className="flex items-center gap-2">
            <input type="checkbox" checked={!!(tax.included_in_print_rate)} onChange={e => onChange('included_in_print_rate', e.target.checked ? 1 : 0)} className="rounded border-gray-300" />
            <span className="text-xs text-gray-600 dark:text-gray-400">Tax included in basic rate</span>
          </div>
          <RGroup title="Accounting dimensions" defaultOpen>
            <div><FL>Cost Center</FL>
              <LinkField label="Cost Center" hideLabel doctype="Cost Center" value={tax.cost_center || ''} onChange={v => onChange('cost_center', v)} placeholder="Cost center…" />
            </div>
          </RGroup>
          <div className="grid grid-cols-2 gap-4">
            {tax.charge_type === 'Actual' && (
              <div><FL>Tax amount</FL>
                <input type="number" min={0} step="0.01" value={tax.tax_amount ?? 0} onChange={e => onChange('tax_amount', parseFloat(e.target.value) || 0)} className={numCls} />
              </div>
            )}
            <div><FL>Tax rate</FL>
              <input type="number" min={0} step="0.01" value={taxRatePercent(tax)} onChange={e => onChange('tax_rate', parseFloat(e.target.value) || 0)} className={numCls} />
            </div>
            <div><FL>Account currency</FL>
              <input value={tax.account_currency || DEFAULT_CURRENCY} onChange={e => onChange('account_currency', e.target.value)} className={inputCls} />
            </div>
          </div>
        </div>
      </div>
    </td>
  </tr>
);

const emptyTax = (): Partial<SalesTaxCharge> => ({
  charge_type: '', account_head: '', tax_rate: 0, account_currency: DEFAULT_CURRENCY, included_in_print_rate: 0,
});

const normalizeTaxFromApi = (tx: any): Partial<SalesTaxCharge> => ({
  ...tx,
  tax_rate: tx.tax_rate ?? tx.rate ?? 0,
  tax_amount: tx.tax_amount,
});

const mapSiTaxToFrappePayload = (tx: any, idx: number) => {
  const row: Record<string, any> = {
    ...(tx.name ? { name: tx.name } : {}),
    charge_type: tx.charge_type,
    account_head: tx.account_head || undefined,
    description: tx.description || undefined,
    included_in_print_rate: tx.included_in_print_rate ?? 0,
    cost_center: tx.cost_center || undefined,
    rate: taxRatePercent(tx),
    account_currency: tx.account_currency || DEFAULT_CURRENCY,
    idx: idx + 1,
  };
  if (tx.charge_type === 'Actual') row.tax_amount = tx.tax_amount ?? 0;
  return row;
};

// ─── Component ────────────────────────────────────────────────────────────────
const SalesInvoiceDetail: React.FC = () => {
  const { invoiceName } = useParams<{ invoiceName: string }>();
  const [searchParams] = useSearchParams();
  const navigate = useNavigate();
  const isNew = invoiceName === 'new';

  const contextCustomer  = searchParams.get('customer')  || '';
  const contextDN        = searchParams.get('dn')        || '';
  const contextSO        = searchParams.get('so')        || '';
  const contextCompanyParam = searchParams.get('company') || DEFAULT_COMPANY;
  const contextProjectParam = searchParams.get('project') || '';

  const [invoice, setInvoice]     = useState<SalesInvoice | null>(null);
  const [loading, setLoading]     = useState(!isNew);
  const [error, setError]         = useState<string | null>(null);
  const [isEditing, setIsEditing] = useState(isNew);
  const [saving, setSaving]       = useState(false);
  const [submitting, setSubmitting] = useState(false);
  const [expandedRow, setExpandedRow] = useState<number | null>(null);
  const [expandedTax, setExpandedTax] = useState<number | null>(null);

  const today = new Date().toISOString().split('T')[0];
  const [form, setForm] = useState<Partial<SalesInvoice>>({
    customer: contextCustomer,
    posting_date: today,
    currency: DEFAULT_CURRENCY,
    company: contextCompanyParam,
    project: contextProjectParam || undefined,
    taxes_and_charges: DEFAULT_SALES_TAXES_TEMPLATE,
    items: [],
    taxes: [],
  } as any);

  const syncForm = useCallback((inv: SalesInvoice) => {
    setForm({
      customer:     inv.customer     || '',
      posting_date: inv.posting_date || today,
      currency:     inv.currency === 'INR' ? DEFAULT_CURRENCY : (inv.currency || DEFAULT_CURRENCY),
      company:      inv.company      || DEFAULT_COMPANY,
      project:      (inv as any).project || '',
      items:        (inv.items || []).map((it: any) => normalizeSiItemFromApi(it)),
      tax_category:       (inv as any).tax_category || '',
      taxes_and_charges:  (inv as any).taxes_and_charges || '',
      shipping_rule:      (inv as any).shipping_rule || '',
      incoterm:           (inv as any).incoterm || '',
      taxes:              ((inv as any).taxes || []).map(normalizeTaxFromApi),
      selling_price_list: (inv as any).selling_price_list || '',
      price_list_currency: (inv as any).price_list_currency || '',
      conversion_rate: (inv as any).conversion_rate || 1,
      plc_conversion_rate: (inv as any).plc_conversion_rate || 1,
    } as any);
    setExpandedRow(null);
    setExpandedTax(null);
  }, [today]);

  // Auto-fetch company default currency for new documents
  useEffect(() => {
    const company = (form as any).company;
    if (!isNew || !company) return;
    fetch(`/api/resource/Company/${encodeURIComponent(company)}`, { credentials: 'include' })
      .then(r => r.json()).then(b => {
        if (b.data?.default_currency) {
          const cur = displayTxnCurrency(b.data.default_currency);
          setForm(f => ({ ...f, currency: cur,
            selling_price_list: (f as any).selling_price_list || 'Standard Selling',
            price_list_currency: (f as any).price_list_currency || cur,
          } as any));
        }
      }).catch(() => {});
  }, [(form as any).company, isNew]);

  // Pre-fill items from Delivery Note when created from DN
  useEffect(() => {
    if (!isNew || !contextDN) return;
    fetch(`/api/resource/Delivery Note/${encodeURIComponent(contextDN)}`, { credentials: 'include' })
      .then(r => r.json()).then(body => {
        const dn = body.data;
        if (!dn) return;
        const dnProject = dn.project || '';
        setForm(f => ({
          ...f,
          customer: dn.customer || f.customer,
          company:  dn.company  || f.company,
          project:  dnProject || (f as any).project,
          tax_category:      (dn as any).tax_category || (f as any).tax_category,
          taxes_and_charges: (dn as any).taxes_and_charges || (f as any).taxes_and_charges,
          shipping_rule:     (dn as any).shipping_rule || (f as any).shipping_rule,
          incoterm:          (dn as any).incoterm || (f as any).incoterm,
          taxes:             (((dn as any).taxes?.length ? (dn as any).taxes : (f.taxes || [])) as any[]).map(normalizeTaxFromApi),
          items: (dn.items || []).map((it: any) => normalizeSiItemFromApi({
            item_code: it.item_code, item_name: it.item_name,
            description: it.description || it.item_name || it.item_code,
            qty: it.qty, uom: it.uom, stock_uom: it.stock_uom,
            rate: it.rate, amount: it.amount,
            project: it.project || dnProject || undefined,
            delivery_note: contextDN,
            sales_order: cleanSiLink(it.against_sales_order),
            so_detail: cleanSiLink(it.so_detail),
            dn_detail: it.name || undefined,
          })),
        }));
      }).catch(() => { /* ignore */ });
  }, [isNew, contextDN]);

  // Pre-fill from Sales Order (same spirit as DN: header + item rows with correct SI references)
  useEffect(() => {
    if (!isNew || !contextSO || contextDN) return;
    fetch(`/api/resource/Sales Order/${encodeURIComponent(contextSO)}`, { credentials: 'include' })
      .then(r => r.json()).then(body => {
        const so = body.data;
        if (!so) return;
        const headerProject = String(so.project || '').trim() || contextProjectParam;
        setForm(f => ({
          ...f,
          customer: so.customer || f.customer,
          company:  so.company  || f.company,
          project:  headerProject || (f as any).project,
          tax_category:      (so as any).tax_category || (f as any).tax_category,
          taxes_and_charges: (so as any).taxes_and_charges || (f as any).taxes_and_charges,
          shipping_rule:     (so as any).shipping_rule || (f as any).shipping_rule,
          incoterm:          (so as any).incoterm || (f as any).incoterm,
          taxes:             (((so as any).taxes?.length ? (so as any).taxes : (f.taxes || [])) as any[]).map(normalizeTaxFromApi),
          currency: so.currency || f.currency,
          selling_price_list: so.selling_price_list || (f as any).selling_price_list || 'Standard Selling',
          price_list_currency: so.currency || (f as any).price_list_currency || f.currency,
          conversion_rate: so.conversion_rate ?? (f as any).conversion_rate ?? 1,
          plc_conversion_rate: so.plc_conversion_rate ?? (f as any).plc_conversion_rate ?? 1,
          items: (so.items || []).map((it: any) => normalizeSiItemFromApi({
            item_code: it.item_code,
            item_name: it.item_name,
            description: it.description || it.item_name || it.item_code,
            qty: it.qty,
            uom: it.uom,
            stock_uom: it.stock_uom,
            conversion_factor: it.conversion_factor ?? 1,
            rate: it.rate,
            amount: it.amount ?? ((it.qty || 0) * (it.rate || 0)),
            income_account: it.income_account,
            expense_account: it.expense_account,
            item_tax_template: it.item_tax_template,
            cost_center: it.cost_center,
            project: it.project || headerProject || undefined,
            sales_order: contextSO,
            so_detail: it.name || undefined,
          })),
        } as any));
      }).catch(() => { /* ignore */ });
  }, [isNew, contextSO, contextDN]);

  useEffect(() => {
    if (isNew) return;
    setLoading(true);
    salesInvoiceService.getSalesInvoice(invoiceName!)
      .then(inv => { setInvoice(inv); syncForm(inv); })
      .catch(e => setError(e.message))
      .finally(() => setLoading(false));
  }, [invoiceName, isNew, syncForm]);

  const set = (k: keyof SalesInvoice | string, v: any) => setForm(f => ({ ...f, [k]: v }));

  // ── Item helpers ──
  const updateItem = (idx: number, k: keyof SalesInvoiceItem, v: any) =>
    setForm(f => {
      const items = [...(f.items || [])];
      const updated = { ...items[idx], [k]: v };
      // Auto-recalculate amount when qty or rate changes
      if (k === 'qty' || k === 'rate') {
        const qty  = parseFloat(String(k === 'qty'  ? v : updated.qty))  || 0;
        const rate = parseFloat(String(k === 'rate' ? v : updated.rate)) || 0;
        updated.amount     = parseFloat((qty * rate).toFixed(4));
        updated.net_amount = updated.amount;
        updated.net_rate   = rate;
      }
      items[idx] = updated;
      return { ...f, items };
    });

  const addItem = (afterIdx?: number) => {
    setForm(f => {
      const items = [...(f.items || [])];
      const newItem = emptyItem();
      let newIdx: number;
      if (afterIdx !== undefined) {
        items.splice(afterIdx + 1, 0, newItem);
        newIdx = afterIdx + 1;
      } else {
        items.push(newItem);
        newIdx = items.length - 1;
      }
      // Use setTimeout so expandedRow update happens after state settles
      setTimeout(() => setExpandedRow(newIdx), 0);
      return { ...f, items };
    });
  };

  const removeItem = (idx: number) => {
    setForm(f => { const items = [...(f.items || [])]; items.splice(idx, 1); return { ...f, items }; });
    setExpandedRow(null);
  };

  // Fetch item details from Frappe Item doctype and fill into row
  const handleItemCodeChange = async (idx: number, code: string) => {
    updateItem(idx, 'item_code', code);
    if (!code) return;
    try {
      const r = await fetch(`/api/resource/Item/${encodeURIComponent(code)}`, { credentials: 'include' });
      const body = await r.json();
      const d = body.data;
      if (!d) return;
      setForm(f => {
        const items = [...(f.items || [])];
        items[idx] = {
          ...items[idx],
          item_code:  code,
          item_name:  d.item_name  || code,
          description: d.description || items[idx].description || '',
          stock_uom:  d.stock_uom  || items[idx].stock_uom || '',
          uom:        d.sales_uom  || d.stock_uom || items[idx].uom || '',
        };
        return { ...f, items };
      });
    } catch { /* ignore */ }
  };

  // ── Tax helpers ──
  const updateTax = (idx: number, k: keyof SalesTaxCharge, v: any) =>
    setForm(f => { const taxes = [...(f.taxes || [])]; taxes[idx] = { ...taxes[idx], [k]: v }; return { ...f, taxes }; });

  const addTax = (afterIdx?: number) => {
    setForm(f => {
      const taxes = [...(f.taxes || [])];
      const newTax = emptyTax();
      let newIdx: number;
      if (afterIdx !== undefined) { taxes.splice(afterIdx + 1, 0, newTax); newIdx = afterIdx + 1; }
      else { taxes.push(newTax); newIdx = taxes.length - 1; }
      setTimeout(() => setExpandedTax(newIdx), 0);
      return { ...f, taxes };
    });
  };
  const removeTax = (idx: number) => {
    setForm(f => { const taxes = [...(f.taxes || [])]; taxes.splice(idx, 1); return { ...f, taxes }; });
    setExpandedTax(null);
  };

  const loadTaxTemplate = async (templateName: string) => {
    if (!templateName) return;
    try {
      const r = await fetch(`/api/resource/Sales Taxes and Charges Template/${encodeURIComponent(templateName)}`, { credentials: 'include' });
      const body = await r.json();
      const tmpl = body.data;
        if (tmpl?.taxes?.length) {
        setForm(f => ({ ...f, taxes: tmpl.taxes.map((tx: any) => normalizeTaxFromApi({
          charge_type: tx.charge_type, account_head: tx.account_head,
          description: tx.description, rate: tx.rate, tax_amount: tx.tax_amount,
          cost_center: tx.cost_center, account_currency: tx.account_currency,
          included_in_print_rate: tx.included_in_print_rate ?? 0,
        })) }));
      }
    } catch { /* ignore */ }
  };

  useEffect(() => {
    if (!isNew || contextDN || contextSO) return;
    void loadTaxTemplate(DEFAULT_SALES_TAXES_TEMPLATE);
  }, [isNew, contextDN, contextSO]);

  // Computed
  const netTotal = (form.items || []).reduce((s, it) => s + (it.amount || 0), 0);
  const computeTaxRows = (taxes: any[], baseNet: number) => {
    let runningTotal = baseNet;
    return taxes.map(tx => {
      const pct = taxRatePercent(tx);
      let txAmt = 0;
      if (tx.charge_type === 'On Net Total') txAmt = baseNet * (pct / 100);
      else if (tx.charge_type === 'Actual') txAmt = tx.tax_amount || 0;
      else if (tx.charge_type === 'On Previous Row Amount' || tx.charge_type === 'On Previous Row Total') txAmt = runningTotal * (pct / 100);
      else txAmt = baseNet * (pct / 100);
      runningTotal += txAmt;
      return { ...tx, _computed_amt: txAmt, _computed_total: runningTotal };
    });
  };
  const computedTaxes = computeTaxRows(form.taxes || [], netTotal);
  const taxTotal   = computedTaxes.reduce((s, tx) => s + tx._computed_amt, 0);
  const grandTotal = netTotal + taxTotal;

  // Save
  const handleSave = async () => {
    if (!form.customer)     { toast.error('Customer is required', { icon: <FaTimesCircle /> }); return; }
    if (!form.posting_date) { toast.error('Posting date is required', { icon: <FaTimesCircle /> }); return; }
    try {
      setSaving(true);
      const payload: Partial<SalesInvoice> = {
        customer:     form.customer,
        posting_date: form.posting_date,
        currency:     form.currency || undefined,
        selling_price_list: (form as any).selling_price_list || 'Standard Selling',
        price_list_currency: (form as any).price_list_currency || form.currency || undefined,
        conversion_rate: (form as any).conversion_rate || 1,
        plc_conversion_rate: (form as any).plc_conversion_rate || 1,
        company:      (form as any).company || undefined,
        project:      (form as any).project || undefined,
        tax_category:       (form as any).tax_category || undefined,
        taxes_and_charges:  (form as any).taxes_and_charges || undefined,
        shipping_rule:      (form as any).shipping_rule || undefined,
        incoterm:           (form as any).incoterm || undefined,
        items: (form.items || []).filter(it => it.item_code).map((it, i) =>
          mapSiItemToFrappePayload({ ...it, project: (it as any).project || (form as any).project }, i)),
        taxes: (form.taxes || []).filter(tx => tx.charge_type).map((tx, i) => mapSiTaxToFrappePayload(tx, i)),
      };
      if (isNew) {
        const created = await salesInvoiceService.createSalesInvoice(payload);
        toast.success('Sales Invoice created', { icon: <FaCheckCircle /> });
        setIsEditing(false);
        navigate(`/invoices/${created.name}`);
      } else {
        const updated = await salesInvoiceService.updateSalesInvoice(invoiceName!, payload);
        setInvoice(updated); syncForm(updated);
        toast.success('Sales Invoice saved', { icon: <FaCheckCircle /> });
        setIsEditing(false);
      }
    } catch (err) {
      toast.error(err instanceof Error ? err.message : 'Error saving invoice', { icon: <FaTimesCircle /> });
    } finally { setSaving(false); }
  };

  const buildCleanPayload = () => {
    const payload: Partial<SalesInvoice> = {
      customer:     form.customer,
      posting_date: form.posting_date,
      currency:     form.currency || undefined,
      selling_price_list: (form as any).selling_price_list || 'Standard Selling',
      price_list_currency: (form as any).price_list_currency || form.currency || undefined,
      conversion_rate: (form as any).conversion_rate || 1,
      plc_conversion_rate: (form as any).plc_conversion_rate || 1,
      company:      (form as any).company || undefined,
      project:      (form as any).project || undefined,
      tax_category:       (form as any).tax_category || undefined,
      taxes_and_charges:  (form as any).taxes_and_charges || undefined,
      shipping_rule:      (form as any).shipping_rule || undefined,
      incoterm:           (form as any).incoterm || undefined,
      items: (form.items || []).filter(it => it.item_code).map((it, i) =>
        mapSiItemToFrappePayload({ ...it, project: (it as any).project || (form as any).project }, i)),
      taxes: (form.taxes || []).filter(tx => tx.charge_type).map((tx, i) => mapSiTaxToFrappePayload(tx, i)),
    };
    return payload;
  };

  const handleSubmit = async () => {
    if (!invoiceName || isNew) return;
    try {
      setSubmitting(true);
      // Directly clear any stale "None" link values via frappe.client.set_value (bypasses document validation)
      await salesInvoiceService.clearItemLinkNones(invoiceName);
      const updated = await salesInvoiceService.submitSalesInvoice(invoiceName);
      setInvoice(updated); syncForm(updated);
      toast.success('Sales Invoice submitted', { icon: <FaCheckCircle /> });
    } catch (err) {
      toast.error(err instanceof Error ? err.message : 'Error submitting', { icon: <FaTimesCircle /> });
    } finally { setSubmitting(false); }
  };

  const editable = isNew || isEditing;
  const isSubmitted = !isNew && invoice?.docstatus === 1;

  if (loading) return <div className="flex items-center justify-center min-h-[400px]"><FaSpinner className="animate-spin text-indigo-500 text-3xl" /></div>;

  return (
    <div className="min-h-screen bg-gray-50 dark:bg-gray-900 px-6 py-6">
      <ToastContainer position="top-right" autoClose={3500} />

      {/* Breadcrumb */}
      <div className="flex items-center gap-2 text-sm mb-6 text-gray-500">
        <button onClick={() => navigate('/projects')} className="hover:text-indigo-600">Project Management</button>
        <span>/</span>
        <button onClick={() => navigate('/invoices')} className="hover:text-indigo-600">Sales Invoices</button>
        <span>/</span>
        <span className="text-gray-700 dark:text-gray-300">{isNew ? 'New Sales Invoice' : invoiceName}</span>
      </div>

      <div className="bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 shadow-sm overflow-hidden">

        {/* ── Header ── */}
        <div className="px-6 py-4 border-b border-gray-100 dark:border-gray-700 flex items-center justify-between gap-4 flex-wrap">
          <div className="flex items-center gap-3">
            <button onClick={() => navigate('/invoices')} className="text-gray-400 hover:text-gray-700"><FaArrowLeft /></button>
            <div>
              <div className="flex items-center gap-2 flex-wrap">
                <FaFileInvoiceDollar className="text-indigo-500" />
                <h1 className="text-xl font-bold text-gray-900 dark:text-white">
                  {isNew ? 'New Sales Invoice' : invoiceName}
                </h1>
                {!isNew && (
                  <span className={`px-2 py-0.5 rounded text-xs font-semibold ${(() => { const s = invoice?.status || ''; if (invoice?.docstatus === 2 || s === 'Cancelled') return 'bg-red-100 text-red-700'; if (!invoice || invoice.docstatus === 0) return 'bg-yellow-100 text-yellow-800'; if (s === 'Paid') return 'bg-green-100 text-green-800'; if (s === 'Partly Paid') return 'bg-indigo-100 text-indigo-800'; if (s === 'Unpaid') return 'bg-orange-100 text-orange-800'; if (s === 'Overdue') return 'bg-red-100 text-red-700'; if (s === 'Return' || s === 'Credit Note Issued') return 'bg-orange-100 text-orange-800'; return 'bg-green-100 text-green-800'; })()}`}>
                    {invoice?.docstatus === 2 ? 'Cancelled' : invoice?.docstatus === 0 ? 'Draft' : (invoice?.status || 'Submitted')}
                  </span>
                )}
              </div>
              {form.customer && <p className="text-xs text-gray-400 mt-0.5">{form.customer}</p>}
            </div>
          </div>

          <div className="flex items-center gap-2 flex-wrap">
            {!isNew && !isEditing && invoice?.docstatus === 0 && (
              <button onClick={handleSubmit} disabled={submitting} className="flex items-center gap-2 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50 text-sm font-medium">
                {submitting ? <FaSpinner className="animate-spin" /> : <FaPaperPlane size={12} />} Submit
              </button>
            )}
            {!isNew && !isEditing && isSubmitted && (invoice?.outstanding_amount ?? 0) > 0 && (
              <button
                onClick={() => {
                  const params = new URLSearchParams({
                    si: invoiceName!,
                    customer: invoice?.customer || '',
                    company: (invoice as any)?.company || '',
                    project: (invoice as any)?.project || '',
                    amount: String(invoice?.outstanding_amount || invoice?.grand_total || 0),
                    currency: invoice?.currency || '',
                  });
                  navigate(`/payment-entries/new?${params}`);
                }}
                className="flex items-center gap-2 px-4 py-2 bg-teal-600 hover:bg-teal-700 text-white text-sm font-semibold rounded-lg shadow transition-colors"
              >
                <FaMoneyBillWave size={13} /> Create Payment
              </button>
            )}
            {!isNew && !isEditing && !isSubmitted && (
              <button onClick={() => setIsEditing(true)} className="flex items-center gap-2 px-4 py-2 border border-indigo-500 text-indigo-600 rounded-lg hover:bg-indigo-50 text-sm">
                <FaEdit /> Edit
              </button>
            )}
            {editable && (
              <>
                <button onClick={handleSave} disabled={saving} className="flex items-center gap-2 px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 disabled:opacity-50 text-sm font-medium">
                  {saving ? <FaSpinner className="animate-spin" /> : <FaSave />}
                  {saving ? 'Saving…' : 'Save'}
                </button>
                {!isNew && (
                  <button onClick={() => { if (invoice) syncForm(invoice); setIsEditing(false); }} className="px-3 py-2 border border-gray-300 rounded-lg text-gray-600 text-sm">
                    <FaTimes />
                  </button>
                )}
              </>
            )}
          </div>
        </div>

        {error && <div className="mx-6 mt-4 p-3 bg-red-50 rounded-lg text-red-700 text-sm">{error}</div>}

        {/* ── Main fields ── */}
        <div className="px-6 pt-5 pb-4">
          <div className="grid grid-cols-1 sm:grid-cols-2 gap-x-8 gap-y-4">
            <div>
              <FL required>Customer</FL>
              {editable
                ? <LinkField label="Customer" hideLabel doctype="Customer" value={form.customer || ''} onChange={v => set('customer', v)} placeholder="Select customer…" />
                : <RV>{form.customer}</RV>}
            </div>
            <div>
              <FL required>Posting Date</FL>
              {editable
                ? <input type="date" value={form.posting_date || ''} onChange={e => set('posting_date', e.target.value)} className={inputCls} />
                : <RV>{form.posting_date}</RV>}
            </div>
            <div>
              <FL>Currency</FL>
              {editable
                ? <select value={form.currency || DEFAULT_CURRENCY} onChange={e => set('currency', e.target.value)} className={inputCls}>
                    <option value="SAR">SAR</option><option value="USD">USD</option>
                    <option value="EUR">EUR</option>
                  </select>
                : <RV>{form.currency}</RV>}
            </div>
            <div>
              <FL>Company</FL>
              {editable
                ? <LinkField label="Company" hideLabel doctype="Company" value={(form as any).company || ''} onChange={v => set('company' as any, v)} placeholder="Select company…" />
                : <RV>{(form as any).company}</RV>}
            </div>
          </div>
        </div>

        {/* ── Items Table ── */}
        <Section title="Items">
          <div className="overflow-x-auto -mx-2">
            <table className="min-w-full text-sm">
              <thead>
                <tr className="border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900/40">
                  <th className="text-left text-[10px] font-semibold text-gray-500 uppercase py-2 px-3 w-8">No.</th>
                  <th className="text-left text-[10px] font-semibold text-gray-500 uppercase py-2 px-3 min-w-[200px]">Item</th>
                  <th className="text-left text-[10px] font-semibold text-gray-500 uppercase py-2 px-3">Item Name</th>
                  <th className="text-right text-[10px] font-semibold text-gray-500 uppercase py-2 px-3 w-24">Qty</th>
                  <th className="text-right text-[10px] font-semibold text-gray-500 uppercase py-2 px-3 w-28">Rate</th>
                  <th className="text-right text-[10px] font-semibold text-gray-500 uppercase py-2 px-3 w-28">Amount</th>
                  <th className="w-20 py-2 px-3" />
                </tr>
              </thead>
              <tbody>
                {(form.items || []).map((it, idx) => (
                  <React.Fragment key={idx}>
                    {/* Directly editable summary row */}
                    <tr className={`border-b border-gray-100 dark:border-gray-700 align-middle ${expandedRow === idx ? 'bg-blue-50/60 dark:bg-blue-900/10' : ''}`}>
                      <td className="py-1.5 px-3 text-gray-400 text-xs">{idx + 1}</td>

                      {/* Item — LinkField directly in row when editable */}
                      <td className="py-1.5 px-2 min-w-[200px]">
                        {editable
                          ? <LinkField
                              label="Item" hideLabel doctype="Item"
                              value={it.item_code || ''}
                              onChange={v => handleItemCodeChange(idx, v)}
                              placeholder="Select item…"
                            />
                          : <span className="font-medium text-gray-800 dark:text-gray-200">{it.item_code || <span className="text-gray-400 italic text-xs">No item</span>}</span>}
                      </td>

                      {/* Item Name — read-only, auto-filled */}
                      <td className="py-1.5 px-3 text-gray-600 dark:text-gray-400 max-w-[180px] truncate text-sm">
                        {it.item_name || <span className="text-gray-400">-</span>}
                      </td>

                      {/* Qty — inline input */}
                      <td className="py-1.5 px-2 w-24">
                        {editable
                          ? <input type="number" min={0} step="0.001"
                              value={it.qty ?? 1}
                              onChange={e => updateItem(idx, 'qty', parseFloat(e.target.value) || 0)}
                              className="w-full px-2 py-1 text-sm text-right border border-gray-300 dark:border-gray-600 rounded bg-white dark:bg-gray-700 focus:outline-none focus:ring-1 focus:ring-indigo-400"
                            />
                          : <span className="block text-right text-gray-700 dark:text-gray-300 text-sm pr-1">{it.qty ?? 0}</span>}
                      </td>

                      {/* Rate — inline input */}
                      <td className="py-1.5 px-2 w-28">
                        {editable
                          ? <input type="number" min={0} step="0.01"
                              value={it.rate ?? 0}
                              onChange={e => updateItem(idx, 'rate', parseFloat(e.target.value) || 0)}
                              className="w-full px-2 py-1 text-sm text-right border border-gray-300 dark:border-gray-600 rounded bg-white dark:bg-gray-700 focus:outline-none focus:ring-1 focus:ring-indigo-400"
                            />
                          : <span className="block text-right text-gray-700 dark:text-gray-300 text-sm pr-1">{(it.rate ?? 0).toFixed(2)}</span>}
                      </td>

                      {/* Amount — always read-only, auto-calculated */}
                      <td className="py-1.5 px-3 text-right font-semibold text-gray-900 dark:text-white text-sm">
                        {(it.amount ?? 0).toFixed(2)}
                      </td>

                      <td className="py-1.5 px-2">
                        <div className="flex items-center justify-end gap-1">
                          {editable && (
                            <button
                              onClick={() => setExpandedRow(expandedRow === idx ? null : idx)}
                              className={`p-1.5 rounded text-xs ${expandedRow === idx ? 'bg-blue-600 text-white' : 'text-indigo-600 hover:bg-indigo-50 dark:hover:bg-indigo-900/20'}`}
                              title="More fields"
                            >
                              <FaPencilAlt size={11} />
                            </button>
                          )}
                          {editable && (
                            <button onClick={() => removeItem(idx)} className="p-1.5 text-red-400 hover:text-red-600 hover:bg-red-50 dark:hover:bg-red-900/20 rounded text-xs" title="Delete row">
                              <FaTrash size={11} />
                            </button>
                          )}
                        </div>
                      </td>
                    </tr>

                    {/* Inline editor row — for additional fields (description, UOM, accounts, etc.) */}
                    {editable && expandedRow === idx && (
                      <ItemRowEditor
                        item={it}
                        rowNo={idx + 1}
                        onChange={(k, v) => {
                          if (k === 'item_code') handleItemCodeChange(idx, v as string);
                          else updateItem(idx, k, v);
                        }}
                        onClose={() => setExpandedRow(null)}
                        onDelete={() => removeItem(idx)}
                        onInsertBelow={() => addItem(idx)}
                      />
                    )}
                  </React.Fragment>
                ))}

                {/* Add row */}
                {editable && (
                  <tr>
                    <td colSpan={7} className="py-2 px-3">
                      <button onClick={() => addItem()} className="flex items-center gap-1.5 text-indigo-600 hover:text-indigo-700 text-sm font-medium">
                        <FaPlus size={10} /> Add Row
                      </button>
                    </td>
                  </tr>
                )}
              </tbody>
            </table>
          </div>

          {/* Items total */}
          <div className="mt-3 flex justify-between items-center text-sm border-t border-gray-100 dark:border-gray-700 pt-3">
            <span className="text-gray-500">Total Quantity: <strong className="text-gray-800 dark:text-gray-200">{(form.items || []).reduce((s, it) => s + (it.qty || 0), 0)}</strong></span>
            <span className="text-gray-500">Total: <strong className="text-gray-900 dark:text-white text-base">{displayTxnCurrency(form.currency)} {netTotal.toFixed(2)}</strong></span>
          </div>
        </Section>

        {/* ── Taxes and Charges ── */}
        <Section title="Taxes and Charges" defaultOpen>
          <div className="grid grid-cols-1 sm:grid-cols-3 gap-x-8 gap-y-3">
            <div>
              <FL>Tax Category</FL>
              {editable
                ? <LinkField label="Tax Category" hideLabel doctype="Tax Category" value={(form as any).tax_category || ''} onChange={v => set('tax_category', v)} placeholder="Select tax category…" />
                : <RV>{(form as any).tax_category}</RV>}
            </div>
            <div>
              <FL>Shipping Rule</FL>
              {editable
                ? <LinkField label="Shipping Rule" hideLabel doctype="Shipping Rule" value={(form as any).shipping_rule || ''} onChange={v => set('shipping_rule', v)} placeholder="Select shipping rule…" />
                : <RV>{(form as any).shipping_rule}</RV>}
            </div>
            <div>
              <FL>Incoterm</FL>
              {editable
                ? <LinkField label="Incoterm" hideLabel doctype="Incoterm" value={(form as any).incoterm || ''} onChange={v => set('incoterm', v)} placeholder="Select incoterm…" />
                : <RV>{(form as any).incoterm}</RV>}
            </div>
          </div>
          <div className="mt-3">
            <FL>Sales Taxes and Charges Template</FL>
            {editable
              ? <LinkField label="Sales Taxes and Charges Template" hideLabel doctype="Sales Taxes and Charges Template" value={(form as any).taxes_and_charges || ''} onChange={v => { set('taxes_and_charges', v); loadTaxTemplate(v); }} placeholder="Select template…" />
              : <RV>{(form as any).taxes_and_charges}</RV>}
          </div>

          <div className="overflow-x-auto -mx-2 mt-4">
            <p className="text-[11px] font-semibold text-gray-500 uppercase tracking-wide px-2 mb-2">Sales Taxes and Charges</p>
            <table className="min-w-full text-sm">
              <thead>
                <tr className="border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900/40">
                  <th className="text-left text-[10px] font-semibold text-gray-500 uppercase py-2 px-3 w-8">No.</th>
                  <th className="text-left text-[10px] font-semibold text-gray-500 uppercase py-2 px-3 w-44">Type <span className="text-red-400">*</span></th>
                  <th className="text-left text-[10px] font-semibold text-gray-500 uppercase py-2 px-3">Account Head <span className="text-red-400">*</span></th>
                  <th className="text-right text-[10px] font-semibold text-gray-500 uppercase py-2 px-3 w-24">Tax Rate</th>
                  <th className="text-right text-[10px] font-semibold text-gray-500 uppercase py-2 px-3 w-28">Amount</th>
                  <th className="text-right text-[10px] font-semibold text-gray-500 uppercase py-2 px-3 w-28">Total</th>
                  {editable && <th className="w-16 py-2 px-2" />}
                </tr>
              </thead>
              <tbody>
                {computedTaxes.length === 0 && (
                  <tr>
                    <td colSpan={editable ? 7 : 6} className="py-10 text-center text-gray-400 text-sm">No tax rows — use Add Row or pick a template.</td>
                  </tr>
                )}
                {computedTaxes.map((tx, idx) => (
                  <React.Fragment key={idx}>
                    <tr className={`border-b border-gray-100 dark:border-gray-700 align-middle ${expandedTax === idx ? 'bg-blue-50/60 dark:bg-blue-900/10' : ''}`}>
                      <td className="py-1.5 px-3 text-gray-400 text-xs">{idx + 1}</td>
                      <td className="py-1.5 px-2 w-44">
                        {editable
                          ? <select value={tx.charge_type || ''} onChange={e => updateTax(idx, 'charge_type', e.target.value)} className={inlineTxt}>
                              <option value="">Select type…</option>
                              <option value="Actual">Actual</option>
                              <option value="On Net Total">On Net Total</option>
                              <option value="On Previous Row Amount">On Previous Row Amount</option>
                              <option value="On Previous Row Total">On Previous Row Total</option>
                              <option value="On Item Quantity">On Item Quantity</option>
                              <option value="Inter Company Transaction">Inter Company Transaction</option>
                            </select>
                          : <span className="text-gray-700 dark:text-gray-300">{tx.charge_type || '-'}</span>}
                      </td>
                      <td className="py-1.5 px-2">
                        {editable
                          ? <LinkField label="Account Head" hideLabel doctype="Account" value={tx.account_head || ''} onChange={v => updateTax(idx, 'account_head', v)} placeholder="Account Head" />
                          : <span className="text-gray-700 dark:text-gray-300">{tx.account_head || '-'}</span>}
                      </td>
                      <td className="py-1.5 px-2 w-24">
                        {editable
                          ? <input type="number" min={0} step="0.01" value={taxRatePercent(tx)} onChange={e => updateTax(idx, 'tax_rate', parseFloat(e.target.value) || 0)} className={inlineNum} />
                          : <span className="block text-right text-gray-700 dark:text-gray-300 pr-1">{taxRatePercent(tx)}</span>}
                      </td>
                      <td className="py-1.5 px-3 text-right text-gray-700 dark:text-gray-300 text-sm">{(tx._computed_amt ?? 0).toFixed(2)}</td>
                      <td className="py-1.5 px-3 text-right font-semibold text-gray-900 dark:text-white text-sm">{(tx._computed_total ?? 0).toFixed(2)}</td>
                      {editable && (
                        <td className="py-1.5 px-2">
                          <div className="flex items-center gap-1">
                            <button type="button" onClick={() => setExpandedTax(expandedTax === idx ? null : idx)}
                              className={`p-1.5 rounded text-xs ${expandedTax === idx ? 'bg-blue-600 text-white' : 'text-indigo-600 hover:bg-indigo-50 dark:hover:bg-indigo-900/20'}`} title="More fields">
                              <FaPencilAlt size={11} />
                            </button>
                            <button type="button" onClick={() => removeTax(idx)} className="p-1.5 text-red-400 hover:text-red-600 hover:bg-red-50 dark:hover:bg-red-900/20 rounded"><FaTrash size={11} /></button>
                          </div>
                        </td>
                      )}
                    </tr>
                    {editable && expandedTax === idx && (
                      <SITaxRowEditor tax={tx} rowNo={idx + 1} onChange={(k, v) => updateTax(idx, k, v)}
                        onClose={() => setExpandedTax(null)} onDelete={() => removeTax(idx)} onInsertBelow={() => addTax(idx)} />
                    )}
                  </React.Fragment>
                ))}
                {editable && (
                  <tr><td colSpan={7} className="py-2 px-3">
                    <button type="button" onClick={() => addTax()} className="flex items-center gap-1.5 text-indigo-600 hover:text-indigo-700 text-sm font-medium"><FaPlus size={10} /> Add Row</button>
                  </td></tr>
                )}
              </tbody>
            </table>
          </div>
          <div className="mt-3 flex justify-end text-sm text-gray-500 pt-2 border-t border-gray-100 dark:border-gray-700">
            Total Taxes and Charges ({displayTxnCurrency(form.currency)}):{' '}
            <strong className="ml-2 text-gray-900 dark:text-white">
              {displayTxnCurrency(form.currency)} {(invoice?.total_taxes_and_charges ?? taxTotal).toFixed(2)}
            </strong>
          </div>
        </Section>

        {/* ── Totals ── */}
        <Section title="Totals">
          <div className="space-y-3 max-w-xs ml-auto">
            {[
              { label: 'Net Total', value: (invoice?.net_total ?? netTotal).toFixed(2) },
              { label: 'Total Taxes', value: (invoice?.total_taxes_and_charges ?? taxTotal).toFixed(2) },
              { label: 'Grand Total', value: (invoice?.grand_total ?? grandTotal).toFixed(2) },
              { label: 'Outstanding', value: (invoice != null ? (invoice.outstanding_amount ?? grandTotal) : grandTotal).toFixed(2) },
            ].map(({ label, value }) => (
              <div key={label} className="flex justify-between items-center text-sm border-b border-gray-100 dark:border-gray-700 pb-2 last:border-0">
                <span className="text-gray-500">{label}</span>
                <span className="font-semibold text-gray-900 dark:text-white">{displayTxnCurrency(form.currency)} {value}</span>
              </div>
            ))}
          </div>
        </Section>

        {/* ── Meta ── */}
        {!isNew && invoice && (
          <Section title="Meta" defaultOpen={false}>
            <div className="grid grid-cols-3 gap-4 text-sm">
              <div><FL>Created By</FL><RV>{invoice.owner}</RV></div>
              <div><FL>Created</FL><RV>{invoice.creation ? new Date(invoice.creation).toLocaleString() : '-'}</RV></div>
              <div><FL>Modified</FL><RV>{invoice.modified ? new Date(invoice.modified).toLocaleString() : '-'}</RV></div>
            </div>
          </Section>
        )}

        {!isNew && (
          <ActivityLog
            doctype="Sales Invoice"
            docname={invoice?.name || invoiceName || ''}
            creationDate={invoice?.creation}
            createdBy={invoice?.owner}
            compact={false}
            initialVisible={5}
            collapsible
            startCollapsed
          />
        )}
      </div>
    </div>
  );
};

export default SalesInvoiceDetail;
