"use client";

import { useState, useRef } from "react";
import { trpc } from "~/lib/trpc/client.js";
import { assertSpreadsheetFile, parseSpreadsheet, isSpreadsheetFile } from "~/lib/excel.js";

type ImportStage = "idle" | "preview" | "importing" | "done";

interface ImportResult {
  total: number;
  created: number;
  updated: number;
  errors: { row: number; message: string }[];
  dryRun: boolean;
  message?: string;
}

interface Props {
  onClose: () => void;
}

export function ImportModal({ onClose }: Props) {
  const [stage, setStage] = useState<ImportStage>("idle");
  const [rows, setRows] = useState<Record<string, string>[]>([]);
  const [fileName, setFileName] = useState<string>("");
  const [fileError, setFileError] = useState<string>("");
  const [result, setResult] = useState<ImportResult | null>(null);
  const [dryRun, setDryRun] = useState(true);
  const fileInputRef = useRef<HTMLInputElement>(null);

  const importMutation = trpc.importExport.importCSV.useMutation({
    onSuccess: (data) => {
      setResult(data);
      setStage("done");
    },
    onError: (err) => {
      setFileError(err.message);
      setStage("preview");
    },
  });

  async function handleFileChange(e: React.ChangeEvent<HTMLInputElement>) {
    const file = e.target.files?.[0];
    if (!file) return;

    setFileError("");
    setRows([]);
    setResult(null);

    if (!isSpreadsheetFile(file)) {
      setFileError("Unsupported file type. Please upload a .xlsx or .csv file.");
      return;
    }

    setFileName(file.name);

    try {
      assertSpreadsheetFile(file, { contextLabel: "resource import" });
      const parsed = await parseSpreadsheet(file);
      setRows(parsed);
      setStage("preview");
    } catch (err) {
      setFileError(err instanceof Error ? err.message : "Failed to parse file.");
    }
  }

  function handleImport() {
    if (rows.length === 0) return;
    setStage("importing");
    importMutation.mutate({
      entityType: "resources",
      rows,
      dryRun,
    });
  }

  function handleReset() {
    setStage("idle");
    setRows([]);
    setFileName("");
    setFileError("");
    setResult(null);
    if (fileInputRef.current) {
      fileInputRef.current.value = "";
    }
  }

  const previewHeaders = rows.length > 0 ? Object.keys(rows[0]!) : [];
  const previewRows = rows.slice(0, 5);

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40 p-4">
      <div className="bg-white rounded-2xl shadow-2xl w-full max-w-3xl max-h-[90vh] flex flex-col">
        {/* Header */}
        <div className="flex items-center justify-between px-6 py-4 border-b border-gray-200">
          <h2 className="text-lg font-semibold text-gray-900">Import Resources</h2>
          <button
            type="button"
            onClick={onClose}
            className="text-gray-400 hover:text-gray-600 transition-colors"
            aria-label="Close"
          >
            <svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
              <path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
            </svg>
          </button>
        </div>

        {/* Body */}
        <div className="flex-1 overflow-y-auto px-6 py-4 space-y-4">
          {/* File picker */}
          {stage === "idle" && (
            <div className="space-y-4">
              <p className="text-sm text-gray-600">
                Upload a `.xlsx` or CSV file to import resources. The first row must contain column headers
                matching the resource fields (e.g.{" "}
                <code className="px-1 py-0.5 bg-gray-100 rounded text-xs font-mono">
                  eid, displayName, email, chapter, lcrCents
                </code>
                ).
              </p>
              <label className="block">
                <span className="sr-only">Choose spreadsheet file</span>
                <div
                  className="flex flex-col items-center justify-center w-full h-40 border-2 border-dashed border-gray-300 rounded-xl cursor-pointer hover:border-brand-400 hover:bg-brand-50 transition-colors"
                  onClick={() => fileInputRef.current?.click()}
                >
                  <svg className="w-10 h-10 text-gray-400 mb-2" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
                    <path strokeLinecap="round" strokeLinejoin="round" d="M9 13h6m-3-3v6m5 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
                  </svg>
                  <p className="text-sm text-gray-500">Click to select `.xlsx` or CSV</p>
                  <p className="text-xs text-gray-400 mt-1">.xlsx, .csv supported</p>
                </div>
                <input
                  ref={fileInputRef}
                  type="file"
                  accept=".xlsx,.csv"
                  className="hidden"
                  onChange={handleFileChange}
                />
              </label>
              {fileError && (
                <p className="text-sm text-red-600">{fileError}</p>
              )}
            </div>
          )}

          {/* Preview */}
          {(stage === "preview" || stage === "importing") && rows.length > 0 && (
            <div className="space-y-4">
              <div className="flex items-center justify-between">
                <div>
                  <p className="text-sm font-medium text-gray-900">{fileName}</p>
                  <p className="text-xs text-gray-500">{rows.length} row{rows.length !== 1 ? "s" : ""} parsed</p>
                </div>
                <button
                  type="button"
                  onClick={handleReset}
                  className="text-xs text-gray-500 hover:text-gray-700 underline"
                >
                  Choose different file
                </button>
              </div>

              {previewHeaders.length > 0 && (
                <div>
                  <p className="text-xs font-medium text-gray-500 uppercase tracking-wider mb-2">
                    Preview (first {previewRows.length} of {rows.length} rows)
                  </p>
                  <div className="overflow-x-auto rounded-lg border border-gray-200">
                    <table className="text-xs w-full">
                      <thead className="bg-gray-50 border-b border-gray-200">
                        <tr>
                          {previewHeaders.map((h) => (
                            <th
                              key={h}
                              className="px-3 py-2 text-left font-medium text-gray-500 uppercase tracking-wider whitespace-nowrap"
                            >
                              {h}
                            </th>
                          ))}
                        </tr>
                      </thead>
                      <tbody className="divide-y divide-gray-100">
                        {previewRows.map((row, i) => (
                          <tr key={i} className="hover:bg-gray-50">
                            {previewHeaders.map((h) => (
                              <td key={h} className="px-3 py-2 text-gray-700 whitespace-nowrap max-w-[200px] truncate">
                                {row[h] ?? ""}
                              </td>
                            ))}
                          </tr>
                        ))}
                      </tbody>
                    </table>
                  </div>
                  {rows.length > 5 && (
                    <p className="text-xs text-gray-400 mt-1">…and {rows.length - 5} more rows</p>
                  )}
                </div>
              )}

              {fileError && (
                <p className="text-sm text-red-600">{fileError}</p>
              )}

              {/* Import options */}
              <div className="flex items-center gap-2">
                <input
                  type="checkbox"
                  id="dryRun"
                  checked={dryRun}
                  onChange={(e) => setDryRun(e.target.checked)}
                  className="rounded border-gray-300"
                />
                <label htmlFor="dryRun" className="text-sm text-gray-700">
                  Dry run (validate only, do not write to database)
                </label>
              </div>
            </div>
          )}

          {/* Done */}
          {stage === "done" && result && (
            <div className="space-y-4">
              <div className={`rounded-lg p-4 ${result.errors.length > 0 ? "bg-yellow-50 border border-yellow-200" : "bg-green-50 border border-green-200"}`}>
                <p className="text-sm font-medium text-gray-900 mb-1">
                  {result.dryRun ? "Dry run complete" : "Import complete"}
                </p>
                <ul className="text-sm text-gray-700 space-y-0.5">
                  <li>Total rows: <strong>{result.total}</strong></li>
                  {!result.dryRun && (
                    <>
                      <li>Created: <strong>{result.created}</strong></li>
                      <li>Updated: <strong>{result.updated}</strong></li>
                    </>
                  )}
                  {result.message && <li>{result.message}</li>}
                  {result.errors.length > 0 && (
                    <li className="text-red-600">Errors: <strong>{result.errors.length}</strong></li>
                  )}
                </ul>
              </div>

              {result.errors.length > 0 && (
                <div className="space-y-1">
                  <p className="text-xs font-medium text-gray-500 uppercase tracking-wider">Errors</p>
                  <ul className="text-xs text-red-600 space-y-0.5 max-h-32 overflow-y-auto">
                    {result.errors.map((e, i) => (
                      <li key={i}>Row {e.row}: {e.message}</li>
                    ))}
                  </ul>
                </div>
              )}

              {result.dryRun && result.errors.length === 0 && (
                <div className="flex items-center gap-2">
                  <input
                    type="checkbox"
                    id="dryRunConfirm"
                    checked={false}
                    onChange={() => {
                      setDryRun(false);
                      setStage("preview");
                      setResult(null);
                    }}
                    className="rounded border-gray-300"
                  />
                  <label htmlFor="dryRunConfirm" className="text-sm text-gray-700 cursor-pointer">
                    Validation passed — click here to run the actual import
                  </label>
                </div>
              )}
            </div>
          )}
        </div>

        {/* Footer */}
        <div className="flex items-center justify-end gap-3 px-6 py-4 border-t border-gray-200">
          <button
            type="button"
            onClick={onClose}
            className="px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors"
          >
            Close
          </button>
          {(stage === "preview") && (
            <button
              type="button"
              onClick={handleImport}
              disabled={rows.length === 0 || importMutation.isPending}
              className="px-4 py-2 text-sm font-medium text-white bg-brand-600 rounded-lg hover:bg-brand-700 disabled:opacity-50 transition-colors"
            >
              {dryRun ? "Validate" : "Import"} {rows.length} row{rows.length !== 1 ? "s" : ""}
            </button>
          )}
          {stage === "importing" && (
            <span className="px-4 py-2 text-sm text-gray-500 animate-pulse">Importing…</span>
          )}
          {stage === "done" && (
            <button
              type="button"
              onClick={handleReset}
              className="px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors"
            >
              Import another file
            </button>
          )}
        </div>
      </div>
    </div>
  );
}
