'use client';

import { useEffect, useState } from 'react';

interface BulkUploadPreviewModalProps {
  file: File;
  busy?: boolean;
  /** Receives the file to upload: the original file when every row is
   * selected (or the preview could not be parsed), otherwise a rebuilt
   * .xlsx containing only the selected rows. */
  onConfirm: (uploadFile: File) => void | Promise<void>;
  onCancel: () => void;
}

const MAX_PREVIEW_ROWS = 200;

const formatSize = (bytes: number): string => {
  if (bytes < 1024) return `${bytes} B`;
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
  return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
};

/**
 * Shown after a bulk-candidate file (.xlsx/.csv) is picked but BEFORE it is
 * sent to the server. Parses the sheet locally (SheetJS) and shows the rows
 * in a table so the user can verify the data. Nothing is uploaded until
 * onConfirm. If local parsing fails, the user can still confirm — the
 * backend does its own authoritative parse.
 */
export function BulkUploadPreviewModal({ file, busy = false, onConfirm, onCancel }: BulkUploadPreviewModalProps) {
  const [parsing, setParsing] = useState(true);
  const [parseError, setParseError] = useState<string | null>(null);
  const [header, setHeader] = useState<string[]>([]);
  const [rows, setRows] = useState<string[][]>([]);
  const [selected, setSelected] = useState<Set<number>>(new Set());

  useEffect(() => {
    let cancelled = false;
    (async () => {
      setParsing(true); setParseError(null); setHeader([]); setRows([]); setSelected(new Set());
      try {
        const XLSX = await import('xlsx');
        const buf = await file.arrayBuffer();
        const wb = XLSX.read(buf, { type: 'array' });
        const ws = wb.Sheets[wb.SheetNames[0]];
        if (!ws) throw new Error('The file has no sheets.');
        const aoa: any[][] = XLSX.utils.sheet_to_json(ws, { header: 1, defval: '', raw: false });
        // Drop rows where every cell is blank.
        const nonEmpty = aoa.filter((r) => r.some((c) => String(c ?? '').trim() !== ''));
        if (cancelled) return;
        const [head = [], ...body] = nonEmpty;
        setHeader(head.map((c) => String(c ?? '')));
        setRows(body.map((r) => head.map((_, i) => String(r[i] ?? ''))));
        setSelected(new Set(body.map((_, i) => i))); // all rows selected by default
      } catch {
        if (!cancelled) setParseError('Could not read this file for preview. You can still upload it — the server will validate it.');
      } finally {
        if (!cancelled) setParsing(false);
      }
    })();
    return () => { cancelled = true; };
  }, [file]);

  const shown = rows.slice(0, MAX_PREVIEW_ROWS);
  const noData = !parsing && !parseError && rows.length === 0;
  const allSelected = rows.length > 0 && selected.size === rows.length;

  const toggleRow = (i: number) =>
    setSelected((s) => { const n = new Set(s); if (n.has(i)) n.delete(i); else n.add(i); return n; });
  const toggleAll = () =>
    setSelected(allSelected ? new Set() : new Set(rows.map((_, i) => i)));

  // Build the file to actually upload: the untouched original when everything
  // is selected (or preview parsing failed), else a rebuilt .xlsx holding only
  // the selected rows in their original order.
  const confirm = async () => {
    if (parseError) { await onConfirm(file); return; }
    if (allSelected) { await onConfirm(file); return; }
    const XLSX = await import('xlsx');
    const picked = rows.filter((_, i) => selected.has(i));
    const ws = XLSX.utils.aoa_to_sheet([header, ...picked]);
    const wb = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(wb, ws, 'Candidates');
    const out = XLSX.write(wb, { type: 'array', bookType: 'xlsx' });
    const base = file.name.replace(/\.(csv|xlsx)$/i, '');
    await onConfirm(new File([out], `${base}-selected.xlsx`, {
      type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
    }));
  };

  return (
    <div className="fixed inset-0 z-[110] flex items-center justify-center p-3 sm:p-4" onClick={busy ? undefined : onCancel}>
      {/* Backdrop */}
      <div className="absolute inset-0 bg-slate-950/60 backdrop-blur-sm" />

      {/* Panel */}
      <div
        className="relative z-10 w-full max-w-5xl max-h-[90vh] bg-white dark:bg-slate-900 rounded-none shadow-2xl flex flex-col"
        onClick={(e) => e.stopPropagation()}
      >
        {/* Header */}
        <div className="flex items-center justify-between gap-3 px-4 sm:px-5 py-3 border-b border-slate-200 dark:border-slate-800 shrink-0">
          <h3 className="text-sm font-semibold text-[#495057] dark:text-slate-100 truncate flex items-center gap-2 min-w-0">
            <i className="fa-solid fa-file-excel text-emerald-600 shrink-0"></i>
            <span className="truncate">{file.name}</span>
            <span className="text-xs text-slate-400 font-normal shrink-0 hidden sm:inline">
              ({formatSize(file.size)}{!parsing && !parseError ? ` · ${rows.length} row${rows.length === 1 ? '' : 's'}` : ''})
            </span>
          </h3>
          <button
            type="button"
            onClick={onCancel}
            disabled={busy}
            className="w-7 h-7 rounded-none text-slate-400 hover:text-slate-600 hover:bg-slate-100 dark:hover:bg-slate-800 dark:hover:text-slate-200 flex items-center justify-center transition cursor-pointer disabled:opacity-50 shrink-0"
          >
            <i className="fa-solid fa-xmark text-sm"></i>
          </button>
        </div>

        {/* Data preview */}
        <div className="flex-1 min-h-0 overflow-auto bg-slate-50 dark:bg-slate-950">
          {parsing ? (
            <div className="h-[30vh] flex flex-col items-center justify-center gap-3">
              <i className="fa-solid fa-spinner animate-spin text-3xl text-indigo-600 dark:text-indigo-400" />
              <p className="text-xs text-slate-500 dark:text-slate-400 font-semibold tracking-wide animate-pulse">Reading file…</p>
            </div>
          ) : parseError ? (
            <div className="h-[25vh] flex flex-col items-center justify-center text-center gap-3 p-6">
              <div className="w-12 h-12 bg-amber-50 dark:bg-amber-950/20 rounded-none flex items-center justify-center text-amber-500 border border-amber-100 dark:border-amber-900/30">
                <i className="fa-solid fa-triangle-exclamation text-xl"></i>
              </div>
              <h4 className="text-sm font-bold text-slate-800 dark:text-white">Preview unavailable</h4>
              <p className="text-xs text-slate-500 dark:text-slate-400 max-w-md leading-relaxed">{parseError}</p>
            </div>
          ) : noData ? (
            <div className="h-[25vh] flex flex-col items-center justify-center text-center gap-3 p-6">
              <div className="w-12 h-12 bg-rose-50 dark:bg-rose-950/20 rounded-none flex items-center justify-center text-rose-500 border border-rose-100 dark:border-rose-900/30">
                <i className="fa-solid fa-circle-exclamation text-xl"></i>
              </div>
              <h4 className="text-sm font-bold text-slate-800 dark:text-white">No data found</h4>
              <p className="text-xs text-slate-500 dark:text-slate-400 max-w-md leading-relaxed">
                The file contains no candidate rows. Please fill the template and choose the file again.
              </p>
            </div>
          ) : (
            <div className="p-3 sm:p-4">
              <div className="overflow-x-auto border border-slate-200 dark:border-slate-800 bg-white dark:bg-slate-900">
                <table className="w-full text-xs min-w-max">
                  <thead className="bg-slate-100 dark:bg-slate-950/60 sticky top-0">
                    <tr className="text-left border-b border-slate-200 dark:border-slate-800">
                      <th className="py-2 px-3 w-8">
                        <input
                          type="checkbox"
                          checked={allSelected}
                          onChange={toggleAll}
                          disabled={busy}
                          title={allSelected ? 'Deselect all' : 'Select all'}
                          className="w-4 h-4 accent-[#405189] cursor-pointer align-middle"
                        />
                      </th>
                      <th className="py-2 px-3 text-[10px] font-extrabold uppercase tracking-wider text-slate-400 whitespace-nowrap">#</th>
                      {header.map((h, i) => (
                        <th key={i} className="py-2 px-3 text-[10px] font-extrabold uppercase tracking-wider text-slate-500 dark:text-slate-400 whitespace-nowrap">{h || `Column ${i + 1}`}</th>
                      ))}
                    </tr>
                  </thead>
                  <tbody className="divide-y divide-slate-100 dark:divide-slate-800">
                    {shown.map((r, ri) => (
                      <tr
                        key={ri}
                        onClick={() => !busy && toggleRow(ri)}
                        className={`cursor-pointer transition ${selected.has(ri) ? 'hover:bg-slate-50 dark:hover:bg-slate-800/40' : 'opacity-45 bg-slate-50/50 dark:bg-slate-950/40'}`}
                      >
                        <td className="py-1.5 px-3" onClick={(e) => e.stopPropagation()}>
                          <input
                            type="checkbox"
                            checked={selected.has(ri)}
                            onChange={() => toggleRow(ri)}
                            disabled={busy}
                            className="w-4 h-4 accent-[#405189] cursor-pointer align-middle"
                          />
                        </td>
                        <td className="py-1.5 px-3 text-slate-400 font-semibold">{ri + 1}</td>
                        {r.map((c, ci) => (
                          <td key={ci} className="py-1.5 px-3 text-slate-700 dark:text-slate-300 whitespace-nowrap max-w-[240px] truncate" title={c}>{c || '—'}</td>
                        ))}
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
              {rows.length > MAX_PREVIEW_ROWS && (
                <p className="text-[11px] text-slate-400 mt-2">
                  Showing the first {MAX_PREVIEW_ROWS} of {rows.length} rows — rows beyond this list follow the &quot;Select all&quot; checkbox.
                </p>
              )}
            </div>
          )}
        </div>

        {/* Confirmation footer */}
        <div className="border-t border-slate-200 dark:border-slate-800 px-4 sm:px-5 py-4 shrink-0">
          <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-1 mb-3 text-center sm:text-left">
            <p className="text-sm font-semibold text-slate-800 dark:text-slate-100">
              Is this the correct data you want to upload?
            </p>
            {!parsing && !parseError && rows.length > 0 && (
              <span className={`text-xs font-bold ${selected.size ? 'text-[#405189] dark:text-indigo-300' : 'text-rose-500'}`}>
                {selected.size} of {rows.length} record{rows.length === 1 ? '' : 's'} selected
              </span>
            )}
          </div>
          <div className="flex flex-col-reverse sm:flex-row sm:justify-end gap-2">
            <button
              type="button"
              onClick={onCancel}
              disabled={busy}
              className="px-4 py-2.5 border border-slate-200 dark:border-slate-700 text-sm font-semibold text-slate-700 dark:text-slate-200 hover:bg-slate-50 dark:hover:bg-slate-800 transition cursor-pointer disabled:opacity-50"
            >
              <i className="fa-solid fa-rotate-left mr-1.5" />
              Cancel / Choose Another File
            </button>
            <button
              type="button"
              onClick={confirm}
              disabled={busy || parsing || noData || (!parseError && selected.size === 0)}
              className="px-6 py-2.5 bg-[#405189] text-white font-bold text-sm hover:bg-[#334267] transition cursor-pointer disabled:opacity-50"
            >
              {busy ? (
                <><i className="fa-solid fa-spinner animate-spin mr-1.5" /> Uploading…</>
              ) : (
                <><i className="fa-solid fa-check mr-1.5" /> Confirm & Upload{!parseError && rows.length > 0 && !allSelected ? ` (${selected.size})` : ''}</>
              )}
            </button>
          </div>
        </div>
      </div>
    </div>
  );
}
