/**
 * LoaderModal — Granite Team_Device Loader Sheet Generator
 *
 * Generates a properly formatted xlsx for upload to SNIP XperLoad.
 * Supports queue-initiated mode (pre-populated devices) and standalone mode (paste IPs).
 */

import React, { useState, useEffect, useCallback, useMemo } from 'react';
import { FileSpreadsheet, Download, X, RefreshCw, Plus, Trash2, AlertCircle, ChevronDown, ChevronRight } from 'lucide-react';
import {
  LOADER_COLUMNS,
  COLUMN_GROUPS,
  OPERATION_TYPES,
  getRequiredColumns,
  getColumnsByGroup,
} from '../utils/graniteLoaderConfig';
import { generateLoaderXlsx, generateFilename } from '../utils/graniteLoaderExport';
import { COLUMN_PICKLISTS } from '../utils/graniteLoaderPicklists';
import SearchableSelect from './SearchableSelect';

const API_BASE = process.env.REACT_APP_API_BASE || 'http://localhost:3001/api';

// ---------------------------------------------------------------------------
// Styles
// ---------------------------------------------------------------------------
const OVERLAY = {
  position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.7)', zIndex: 9999,
  display: 'flex', alignItems: 'center', justifyContent: 'center',
};
const MODAL = {
  background: '#1E293B', borderRadius: '0.75rem', border: '1px solid #334155',
  width: '90vw', maxWidth: '1100px', maxHeight: '90vh', display: 'flex', flexDirection: 'column',
  overflow: 'hidden',
};
const HEADER = {
  display: 'flex', alignItems: 'center', justifyContent: 'space-between',
  padding: '1rem 1.25rem', borderBottom: '1px solid #334155',
};
const BODY = { flex: 1, overflow: 'auto', padding: '1.25rem' };
const FOOTER = {
  display: 'flex', alignItems: 'center', justifyContent: 'space-between',
  padding: '1rem 1.25rem', borderTop: '1px solid #334155',
};
const INPUT = {
  background: '#0F172A', border: '1px solid #334155', borderRadius: '0.375rem',
  color: '#E2E8F0', padding: '0.4rem 0.6rem', fontSize: '0.75rem', width: '100%',
};
const BTN = {
  padding: '0.5rem 1rem', borderRadius: '0.375rem', border: 'none',
  fontSize: '0.75rem', fontWeight: '600', cursor: 'pointer',
};
const BTN_PRIMARY = { ...BTN, background: '#7C3AED', color: '#fff' };
const BTN_SECONDARY = { ...BTN, background: '#334155', color: '#E2E8F0' };
const BTN_SUCCESS = { ...BTN, background: '#10B981', color: '#fff' };

export default function LoaderModal({ isOpen, onClose, initialDevices }) {
  // --- State ---
  const [operationType, setOperationType] = useState('Change');
  const [selectedColumns, setSelectedColumns] = useState(new Set());
  const [devices, setDevices] = useState([]);
  const [bulkDefaults, setBulkDefaults] = useState({});
  const [overrides, setOverrides] = useState({});
  const [editingCell, setEditingCell] = useState(null);
  const [editValue, setEditValue] = useState('');
  const [enriching, setEnriching] = useState(false);
  const [enrichErrors, setEnrichErrors] = useState([]);
  const [cardConfigured, setCardConfigured] = useState(false);
  const [pasteInput, setPasteInput] = useState('');
  const [expandedGroups, setExpandedGroups] = useState(new Set(['Identification', 'Responsible Org']));
  const [validationWarnings, setValidationWarnings] = useState([]);

  // --- Initialize ---
  useEffect(() => {
    if (!isOpen) return;
    // Check CARD status
    fetch(`${API_BASE}/card/status`, { credentials: 'include' })
      .then(r => r.json())
      .then(d => setCardConfigured(d.configured === true))
      .catch(() => setCardConfigured(false));
  }, [isOpen]);

  // Populate devices from initialDevices or reset
  useEffect(() => {
    if (!isOpen) return;
    if (initialDevices && initialDevices.length > 0) {
      setDevices(initialDevices.map(d => ({
        IPV4_ADDRESS: d.ip_address || '',
        EQUIP_NAME: d.hostname || '',
        _host_id: d.host_id || null,
      })));
    } else {
      setDevices([]);
    }
    setOverrides({});
    setBulkDefaults({});
    setEnrichErrors([]);
    setValidationWarnings([]);
    setEnriching(false);
  }, [isOpen, initialDevices]);

  // Auto-select required columns + useful defaults when operation type changes
  useEffect(() => {
    const required = getRequiredColumns(operationType);
    setSelectedColumns(prev => {
      const next = new Set(prev);
      required.forEach(id => next.add(id));
      // Always include these useful columns by default
      next.add('IPV4_ADDRESS');
      next.add('EQUIP_NAME');
      next.add('RESPONSIBLE_TEAM');
      return next;
    });
  }, [operationType]);

  // --- Column selection ---
  const toggleColumn = useCallback((colId) => {
    const required = getRequiredColumns(operationType);
    if (required.includes(colId)) return; // Can't deselect required
    setSelectedColumns(prev => {
      const next = new Set(prev);
      if (next.has(colId)) next.delete(colId);
      else next.add(colId);
      return next;
    });
  }, [operationType]);

  const toggleGroup = useCallback((group) => {
    setExpandedGroups(prev => {
      const next = new Set(prev);
      if (next.has(group)) next.delete(group);
      else next.add(group);
      return next;
    });
  }, []);

  // --- Ordered selected columns (canonical order) ---
  const orderedColumns = useMemo(() => {
    return LOADER_COLUMNS.filter(col => selectedColumns.has(col.id));
  }, [selectedColumns]);

  // --- Resolve cell value (override > bulk default > device value > empty) ---
  const getCellValue = useCallback((rowIdx, colId) => {
    if (overrides[rowIdx] && overrides[rowIdx][colId] !== undefined) {
      return overrides[rowIdx][colId];
    }
    if (bulkDefaults[colId] !== undefined && bulkDefaults[colId] !== '') {
      return bulkDefaults[colId];
    }
    return devices[rowIdx]?.[colId] || '';
  }, [overrides, bulkDefaults, devices]);

  // --- Cell editing ---
  const startEdit = (rowIdx, colId) => {
    setEditingCell({ rowIdx, colId });
    setEditValue(getCellValue(rowIdx, colId));
  };

  const commitEdit = () => {
    if (!editingCell) return;
    const { rowIdx, colId } = editingCell;
    const currentBulk = bulkDefaults[colId] || '';
    const currentDevice = devices[rowIdx]?.[colId] || '';
    // Only store override if different from bulk default and device value
    if (editValue !== currentBulk || currentDevice) {
      setOverrides(prev => ({
        ...prev,
        [rowIdx]: { ...(prev[rowIdx] || {}), [colId]: editValue },
      }));
    }
    setEditingCell(null);
  };

  const clearOverride = (rowIdx, colId) => {
    setOverrides(prev => {
      const next = { ...prev };
      if (next[rowIdx]) {
        const row = { ...next[rowIdx] };
        delete row[colId];
        if (Object.keys(row).length === 0) delete next[rowIdx];
        else next[rowIdx] = row;
      }
      return next;
    });
  };

  // --- Bulk default ---
  const setBulkDefault = (colId, value) => {
    setBulkDefaults(prev => ({ ...prev, [colId]: value }));
  };

  // --- Paste IPs (standalone mode) ---
  const loadPastedIps = () => {
    const lines = pasteInput.split(/[\n,]+/).map(s => s.trim()).filter(Boolean);
    const newDevices = lines.slice(0, 200).map(ip => ({ IPV4_ADDRESS: ip, EQUIP_NAME: '' }));
    setDevices(newDevices);
    setOverrides({});
    setPasteInput('');
  };

  const addRow = () => {
    setDevices(prev => [...prev, { IPV4_ADDRESS: '', EQUIP_NAME: '' }]);
  };

  const removeRow = (idx) => {
    setDevices(prev => prev.filter((_, i) => i !== idx));
    setOverrides(prev => {
      const next = {};
      Object.entries(prev).forEach(([k, v]) => {
        const ki = parseInt(k, 10);
        if (ki < idx) next[ki] = v;
        else if (ki > idx) next[ki - 1] = v;
      });
      return next;
    });
  };

  // --- CARD Enrichment ---
  const enrichFromCard = async () => {
    const ips = devices.map(d => d.IPV4_ADDRESS).filter(Boolean);
    const hostIds = devices.filter(d => !d.IPV4_ADDRESS && d._host_id).map(d => d._host_id);

    if (ips.length === 0 && hostIds.length === 0) return;

    setEnriching(true);
    setEnrichErrors([]);

    try {
      const body = {};
      if (ips.length > 0) body.ips = ips;
      if (hostIds.length > 0) body.host_ids = hostIds;

      const resp = await fetch(`${API_BASE}/card/enrich-batch`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        credentials: 'include',
        body: JSON.stringify(body),
      });

      if (!resp.ok) {
        const err = await resp.json().catch(() => ({}));
        setEnrichErrors([{ ip: 'all', error: err.error || `HTTP ${resp.status}` }]);
        setEnriching(false);
        return;
      }

      const data = await resp.json();
      const errors = [];

      // Map results back to devices
      setDevices(prev => prev.map((device, idx) => {
        // Try matching by IP first
        let result = data.results ? data.results.find(r => r.ip === device.IPV4_ADDRESS) : null;

        // If no IP match, try matching by host_id
        if (!result && device._host_id && data.host_id_results) {
          result = data.host_id_results.find(r => String(r.host_id) === String(device._host_id));
        }

        if (!result || !result.found) {
          if (result) errors.push({ ip: device.IPV4_ADDRESS || `hostId:${device._host_id}`, error: result.error || 'Not found' });
          return device;
        }

        // Only populate fields that aren't already overridden by the user
        const updated = { ...device };
        const rowOverrides = overrides[idx] || {};

        // Populate IP from host_id result if device didn't have one
        if (result.ip && !device.IPV4_ADDRESS) {
          updated.IPV4_ADDRESS = result.ip;
        }
        if (result.equip_inst_id && !rowOverrides.EQUIP_INST_ID && !device.EQUIP_INST_ID) {
          updated.EQUIP_INST_ID = result.equip_inst_id;
        }
        if (result.hostname && !rowOverrides.EQUIP_NAME && !device.EQUIP_NAME) {
          updated.EQUIP_NAME = result.hostname;
        }
        if (result.site_name && !rowOverrides.SITE_NAME && !device.SITE_NAME) {
          updated.SITE_NAME = result.site_name;
        }
        if (result.mgmt_ip_asn && !rowOverrides.MGMT_IP_ASN && !device.MGMT_IP_ASN) {
          updated.MGMT_IP_ASN = result.mgmt_ip_asn;
        }
        if (result.responsible_team && !rowOverrides.RESPONSIBLE_TEAM && !device.RESPONSIBLE_TEAM) {
          updated.RESPONSIBLE_TEAM = result.responsible_team;
        }
        if (result.equip_status && !rowOverrides.EQUIP_STATUS && !device.EQUIP_STATUS) {
          updated.EQUIP_STATUS = result.equip_status;
        }

        return updated;
      }));

      setEnrichErrors(errors);
    } catch (err) {
      setEnrichErrors([{ ip: 'all', error: err.message }]);
    }

    setEnriching(false);
  };

  // --- Validation ---
  const validate = () => {
    const required = getRequiredColumns(operationType);
    const warnings = [];

    devices.forEach((_, rowIdx) => {
      required.forEach(colId => {
        if (colId === 'DELETE') return; // Auto-filled
        const val = getCellValue(rowIdx, colId);
        if (!val) {
          warnings.push({ rowIdx, colId });
        }
      });
    });

    setValidationWarnings(warnings);
    return warnings;
  };

  // --- Download ---
  const handleDownload = () => {
    const warnings = validate();

    // Build final rows
    const finalRows = devices.map((_, rowIdx) => {
      const row = {};
      orderedColumns.forEach(col => {
        row[col.id] = getCellValue(rowIdx, col.id);
      });
      return row;
    });

    // Determine team name for filename (from bulk default or first row)
    const teamName = bulkDefaults.RESPONSIBLE_TEAM || finalRows[0]?.RESPONSIBLE_TEAM || '';

    const blob = generateLoaderXlsx({
      operationType,
      columnIds: orderedColumns.map(c => c.id),
      rows: finalRows,
    });

    const filename = generateFilename(operationType, teamName);
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = filename;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);

    // Keep warnings visible but don't block download
    if (warnings.length > 0) {
      // Warnings already displayed in UI
    }
  };

  // --- Render ---
  if (!isOpen) return null;

  const requiredCols = getRequiredColumns(operationType);
  const isStandalone = !initialDevices || initialDevices.length === 0;
  const missingCount = validationWarnings.length;
  const isCellWarning = (rowIdx, colId) => validationWarnings.some(w => w.rowIdx === rowIdx && w.colId === colId);
  const isOverridden = (rowIdx, colId) => overrides[rowIdx] && overrides[rowIdx][colId] !== undefined;

  return (
    <div style={OVERLAY} onClick={onClose}>
      <div style={MODAL} onClick={e => e.stopPropagation()}>
        {/* Header */}
        <div style={HEADER}>
          <div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
            <FileSpreadsheet style={{ width: '18px', height: '18px', color: '#7C3AED' }} />
            <span style={{ fontSize: '0.9rem', fontWeight: '700', color: '#E2E8F0' }}>Generate Granite Loader Sheet</span>
            <span style={{ fontSize: '0.7rem', color: '#64748B' }}>({devices.length} devices)</span>
          </div>
          <button onClick={onClose} style={{ background: 'none', border: 'none', color: '#64748B', cursor: 'pointer' }}>
            <X style={{ width: '18px', height: '18px' }} />
          </button>
        </div>

        {/* Body */}
        <div style={BODY}>
          {/* Top controls row */}
          <div style={{ display: 'flex', gap: '1rem', alignItems: 'flex-end', marginBottom: '1rem', flexWrap: 'wrap' }}>
            <div>
              <label style={{ fontSize: '0.65rem', color: '#94A3B8', display: 'block', marginBottom: '0.2rem' }}>Operation</label>
              <select style={{ ...INPUT, width: '140px', cursor: 'pointer' }} value={operationType} onChange={e => setOperationType(e.target.value)}>
                {OPERATION_TYPES.map(op => <option key={op} value={op}>{op}</option>)}
              </select>
            </div>

            {cardConfigured && (
              <button style={{ ...BTN_SECONDARY, display: 'flex', alignItems: 'center', gap: '0.3rem' }} onClick={enrichFromCard} disabled={enriching || devices.length === 0}>
                <RefreshCw style={{ width: '12px', height: '12px', animation: enriching ? 'spin 1s linear infinite' : 'none' }} />
                {enriching ? 'Enriching...' : 'Enrich from CARD'}
              </button>
            )}
          </div>

          {/* Standalone: paste IPs */}
          {isStandalone && devices.length === 0 && (
            <div style={{ marginBottom: '1rem', padding: '1rem', background: '#0F172A', borderRadius: '0.5rem', border: '1px solid #334155' }}>
              <label style={{ fontSize: '0.7rem', color: '#94A3B8', display: 'block', marginBottom: '0.3rem' }}>Paste IP addresses (one per line or comma-separated)</label>
              <textarea
                style={{ ...INPUT, height: '80px', resize: 'vertical', fontFamily: 'monospace' }}
                value={pasteInput}
                onChange={e => setPasteInput(e.target.value)}
                placeholder="10.240.78.110&#10;10.240.78.111&#10;172.16.5.20"
              />
              <div style={{ marginTop: '0.5rem', display: 'flex', gap: '0.5rem' }}>
                <button style={BTN_PRIMARY} onClick={loadPastedIps} disabled={!pasteInput.trim()}>Load IPs</button>
              </div>
            </div>
          )}

          {/* Enrich errors */}
          {enrichErrors.length > 0 && (
            <div style={{ marginBottom: '0.75rem', padding: '0.5rem 0.75rem', background: 'rgba(239, 68, 68, 0.1)', border: '1px solid rgba(239, 68, 68, 0.3)', borderRadius: '0.375rem' }}>
              <div style={{ fontSize: '0.7rem', color: '#EF4444', display: 'flex', alignItems: 'center', gap: '0.3rem', justifyContent: 'space-between' }}>
                <span style={{ display: 'flex', alignItems: 'center', gap: '0.3rem' }}>
                  <AlertCircle style={{ width: '12px', height: '12px' }} />
                  {enrichErrors.length === 1 && enrichErrors[0].ip === 'all'
                    ? enrichErrors[0].error
                    : enrichErrors.some(e => e.error && e.error.includes('timed out'))
                      ? `${enrichErrors.length} device(s) timed out — CARD may be slow`
                      : `${enrichErrors.length} device(s) not found in CARD`}
                </span>
                <button
                  onClick={enrichFromCard}
                  disabled={enriching}
                  style={{
                    background: 'rgba(239, 68, 68, 0.15)', border: '1px solid rgba(239, 68, 68, 0.4)',
                    borderRadius: '0.25rem', padding: '0.2rem 0.5rem',
                    color: '#F87171', cursor: 'pointer',
                    fontSize: '0.65rem', fontFamily: 'monospace', fontWeight: '600',
                  }}
                >
                  Retry
                </button>
              </div>
            </div>
          )}

          {/* Column selection */}
          <div style={{ marginBottom: '1rem', padding: '0.75rem', background: '#0F172A', borderRadius: '0.5rem', border: '1px solid #334155' }}>
            <div style={{ fontSize: '0.7rem', color: '#94A3B8', marginBottom: '0.5rem', fontWeight: '600' }}>Columns</div>
            {COLUMN_GROUPS.map(group => {
              const cols = getColumnsByGroup(group);
              const selectedInGroup = cols.filter(c => selectedColumns.has(c.id)).length;
              const expanded = expandedGroups.has(group);
              return (
                <div key={group} style={{ marginBottom: '0.25rem' }}>
                  <div
                    style={{ display: 'flex', alignItems: 'center', gap: '0.3rem', cursor: 'pointer', padding: '0.2rem 0', userSelect: 'none' }}
                    onClick={() => toggleGroup(group)}
                  >
                    {expanded ? <ChevronDown style={{ width: '12px', height: '12px', color: '#64748B' }} /> : <ChevronRight style={{ width: '12px', height: '12px', color: '#64748B' }} />}
                    <span style={{ fontSize: '0.7rem', color: '#E2E8F0' }}>{group}</span>
                    <span style={{ fontSize: '0.6rem', color: '#64748B' }}>({selectedInGroup} selected)</span>
                  </div>
                  {expanded && (
                    <div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.3rem', paddingLeft: '1.2rem', marginTop: '0.2rem' }}>
                      {cols.map(col => {
                        const isRequired = requiredCols.includes(col.id);
                        const isChecked = selectedColumns.has(col.id);
                        return (
                          <label key={col.id} style={{ display: 'flex', alignItems: 'center', gap: '0.2rem', fontSize: '0.65rem', color: isRequired ? '#A78BFA' : '#94A3B8', cursor: isRequired ? 'default' : 'pointer' }}>
                            <input
                              type="checkbox"
                              checked={isChecked}
                              onChange={() => toggleColumn(col.id)}
                              disabled={isRequired}
                              style={{ accentColor: '#7C3AED' }}
                            />
                            {col.label.length > 30 ? col.id : col.label}
                            {isRequired && <span style={{ fontSize: '0.55rem', color: '#7C3AED' }}>*</span>}
                          </label>
                        );
                      })}
                    </div>
                  )}
                </div>
              );
            })}
          </div>

          {/* Bulk defaults */}
          {orderedColumns.length > 0 && devices.length > 0 && (
            <div style={{ marginBottom: '1rem', padding: '0.75rem', background: '#0F172A', borderRadius: '0.5rem', border: '1px solid #334155' }}>
              <div style={{ fontSize: '0.7rem', color: '#94A3B8', marginBottom: '0.5rem', fontWeight: '600' }}>Bulk Defaults (applies to all rows)</div>
              <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(220px, 1fr))', gap: '0.5rem' }}>
                {orderedColumns.filter(c => c.id !== 'DELETE').map(col => (
                  <div key={col.id}>
                    <label style={{ fontSize: '0.6rem', color: '#64748B', display: 'block', marginBottom: '0.15rem' }}>
                      {col.id}
                    </label>
                    {COLUMN_PICKLISTS[col.id] ? (
                      <SearchableSelect
                        value={bulkDefaults[col.id] || ''}
                        options={COLUMN_PICKLISTS[col.id]}
                        onChange={(val) => setBulkDefault(col.id, val)}
                        placeholder={`Default for all rows`}
                        autoFocus={false}
                      />
                    ) : (
                      <input
                        style={INPUT}
                        value={bulkDefaults[col.id] || ''}
                        onChange={e => setBulkDefault(col.id, e.target.value)}
                        placeholder={`Default for all rows`}
                      />
                    )}
                  </div>
                ))}
              </div>
            </div>
          )}

          {/* Preview table */}
          {devices.length > 0 && orderedColumns.length > 0 && (
            <div style={{ border: '1px solid #334155', borderRadius: '0.5rem', overflow: 'auto', maxHeight: '300px' }}>
              <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: '0.7rem' }}>
                <thead>
                  <tr style={{ position: 'sticky', top: 0, background: '#0F172A', zIndex: 1 }}>
                    <th style={{ padding: '0.4rem', borderBottom: '1px solid #334155', color: '#64748B', textAlign: 'center', width: '30px' }}>#</th>
                    {orderedColumns.map(col => (
                      <th key={col.id} style={{ padding: '0.4rem 0.5rem', borderBottom: '1px solid #334155', color: '#94A3B8', textAlign: 'left', whiteSpace: 'nowrap' }}>
                        {col.id}
                      </th>
                    ))}
                    <th style={{ padding: '0.4rem', borderBottom: '1px solid #334155', width: '30px' }}></th>
                  </tr>
                </thead>
                <tbody>
                  {devices.map((_, rowIdx) => (
                    <tr key={rowIdx} style={{ borderBottom: '1px solid rgba(51, 65, 85, 0.5)' }}>
                      <td style={{ padding: '0.3rem', textAlign: 'center', color: '#475569', fontSize: '0.6rem' }}>{rowIdx + 1}</td>
                      {orderedColumns.map(col => {
                        const value = getCellValue(rowIdx, col.id);
                        const isEditing = editingCell?.rowIdx === rowIdx && editingCell?.colId === col.id;
                        const hasOverride = isOverridden(rowIdx, col.id);
                        const hasWarning = isCellWarning(rowIdx, col.id);

                        return (
                          <td
                            key={col.id}
                            style={{
                              padding: '0.2rem 0.4rem',
                              position: 'relative',
                              background: hasWarning ? 'rgba(239, 68, 68, 0.08)' : 'transparent',
                              cursor: 'pointer',
                              minWidth: '100px',
                            }}
                            onClick={() => !isEditing && startEdit(rowIdx, col.id)}
                          >
                            {isEditing ? (
                              COLUMN_PICKLISTS[col.id] ? (
                                <SearchableSelect
                                  value={editValue}
                                  options={COLUMN_PICKLISTS[col.id]}
                                  onChange={(val) => {
                                    setOverrides(prev => ({
                                      ...prev,
                                      [rowIdx]: { ...(prev[rowIdx] || {}), [col.id]: val },
                                    }));
                                    setEditingCell(null);
                                  }}
                                  onClose={() => setEditingCell(null)}
                                  autoFocus
                                />
                              ) : (
                                <input
                                  style={{ ...INPUT, padding: '0.2rem 0.4rem', fontSize: '0.7rem' }}
                                  value={editValue}
                                  onChange={e => setEditValue(e.target.value)}
                                  onBlur={commitEdit}
                                  onKeyDown={e => { if (e.key === 'Enter') commitEdit(); if (e.key === 'Escape') setEditingCell(null); }}
                                  autoFocus
                                />
                              )
                            ) : (
                              <div style={{ display: 'flex', alignItems: 'center', gap: '0.2rem' }}>
                                {hasOverride && <span style={{ color: '#F59E0B', fontSize: '0.5rem' }}>●</span>}
                                <span style={{ color: value ? '#E2E8F0' : '#475569' }}>{value || '—'}</span>
                                {hasOverride && (
                                  <button
                                    onClick={e => { e.stopPropagation(); clearOverride(rowIdx, col.id); }}
                                    style={{ background: 'none', border: 'none', color: '#64748B', cursor: 'pointer', fontSize: '0.55rem', padding: '0 0.2rem' }}
                                    title="Revert to bulk default"
                                  >↻</button>
                                )}
                              </div>
                            )}
                          </td>
                        );
                      })}
                      <td style={{ padding: '0.2rem', textAlign: 'center' }}>
                        <button onClick={() => removeRow(rowIdx)} style={{ background: 'none', border: 'none', color: '#64748B', cursor: 'pointer' }}>
                          <Trash2 style={{ width: '11px', height: '11px' }} />
                        </button>
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          )}

          {/* Add row button */}
          {devices.length > 0 && (
            <button style={{ ...BTN_SECONDARY, marginTop: '0.5rem', display: 'flex', alignItems: 'center', gap: '0.3rem', fontSize: '0.65rem' }} onClick={addRow}>
              <Plus style={{ width: '11px', height: '11px' }} /> Add Row
            </button>
          )}
        </div>

        {/* Footer */}
        <div style={FOOTER}>
          <div style={{ fontSize: '0.7rem', color: '#64748B' }}>
            {missingCount > 0 && (
              <span style={{ color: '#F59E0B' }}>⚠ {missingCount} missing required field{missingCount > 1 ? 's' : ''}</span>
            )}
          </div>
          <div style={{ display: 'flex', gap: '0.5rem' }}>
            <button style={BTN_SECONDARY} onClick={onClose}>Cancel</button>
            <button
              style={{ ...BTN_SUCCESS, display: 'flex', alignItems: 'center', gap: '0.3rem' }}
              onClick={handleDownload}
              disabled={devices.length === 0 || orderedColumns.length === 0}
            >
              <Download style={{ width: '13px', height: '13px' }} />
              Download Loader Sheet
            </button>
          </div>
        </div>
      </div>
    </div>
  );
}
