import { useState, useRef, useEffect } from "react";
import ExcelJS from "exceljs";
import { chemicalsApi } from "../lib/api";
import { validateCAS, validateNumber, validatePhoneOrEmail } from "../lib/validators";
import type { ChemicalInventory } from "../shared/types";
import { Card } from "./ui/card";
import { Button } from "./ui/button";
import { Input } from "./ui/input";
import { Label } from "./ui/label";
import { Badge } from "./ui/badge";
import {
  Camera, Sparkles, Mail, Search, Plus, AlertTriangle,
  ChevronDown, ChevronUp, Loader2, Trash2, FlaskConical,
  Table2, FileDown, FileSpreadsheet, Upload, ArrowRight,
} from "lucide-react";
import {
  Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger,
} from "./ui/dialog";
import {
  Select, SelectContent, SelectItem, SelectTrigger, SelectValue,
} from "./ui/select";

// ── constants ──────────────────────────────────────────────────────────────

const storageDeviceOptions = [
  "Aerosol Can","Ampule","Bulked Item","Fiber Box","Gas Cylinder",
  "Glass Bottle","Metal Can","Metal Drum","Metal Open Drum","Pallet",
  "Plastic Bag","Plastic Bottle","Plastic Drum","Plastic Open Drum",
];

const physicalStates = ["Solid", "Liquid", "Gas"];

const unitOptions = ["mL", "L", "g", "kg", "mg", "oz", "lb", "gal", "mol"];

const TABLE_COLUMNS: { label: string; key: keyof ChemicalInventory }[] = [
  { label: "PI First Name",              key: "piFirstName" },
  { label: "Physical State",             key: "physicalState" },
  { label: "Chemical Name",              key: "chemicalName" },
  { label: "Bldg Code",                  key: "bldgCode" },
  { label: "LAB",                        key: "lab" },
  { label: "Storage Location",           key: "storageLocation" },
  { label: "Storage Device",             key: "storageDevice" },
  { label: "# of Containers",           key: "numberOfContainers" },
  { label: "Amount per Container",       key: "amountPerContainer" },
  { label: "Unit of Measure",            key: "unitOfMeasure" },
  { label: "CAS #",                      key: "casNumber" },
  { label: "Chemical Formula",           key: "chemicalFormula" },
  { label: "Molecular Weight",           key: "molecularWeight" },
  { label: "Vendor",                     key: "vendor" },
  { label: "Catalog #",                  key: "catalogNumber" },
  { label: "Found in Catalog",           key: "foundInCatalog" },
  { label: "PO#",                        key: "poNumber" },
  { label: "Receipt Date",               key: "receiptDate" },
  { label: "Open Date",                  key: "openDate" },
  { label: "MAX on Hand",                key: "maxOnHand" },
  { label: "Expiration Date",            key: "expirationDate" },
  { label: "Contact",                    key: "contact" },
  { label: "Comments",                   key: "comments" },
  { label: "Date Entered",               key: "dateEntered" },
  { label: "Permit #",                   key: "permitNumber" },
  { label: "Barcode",                    key: "barcode" },
  { label: "LAST_CHANGED",              key: "lastChanged" },
  { label: "Concentration",             key: "concentration" },
  { label: "Chemical Number",           key: "chemicalNumber" },
  { label: "Lot Number",                key: "lotNumber" },
  { label: "Multiple CAS (comma delimited)", key: "multipleCAS" },
];

type ImportColumnMapping = keyof ChemicalInventory | "__skip__";

// ── helpers ────────────────────────────────────────────────────────────────

function daysUntil(dateStr: string) {
  const today = new Date(); today.setHours(0, 0, 0, 0);
  return Math.ceil((new Date(dateStr).getTime() - today.getTime()) / 86400000);
}

function fillBarColor(pct: number) {
  if (pct < 20) return "bg-red-500";
  if (pct < 40) return "bg-amber-500";
  return "bg-[#5a9584]";
}

type UserProfile = { pi_first_name: string; bldg_code: string; lab: string; contact?: string };

function emptyForm(profile?: UserProfile | null): Partial<ChemicalInventory> {
  return {
    piFirstName: profile?.pi_first_name ?? "",
    bldgCode: profile?.bldg_code ?? "",
    lab: profile?.lab ?? "",
    contact: profile?.contact ?? "",
    physicalState: "",
    chemicalName: "",
    storageLocation: "",
    storageDevice: "Glass Bottle",
    numberOfContainers: "1",
    amountPerContainer: "",
    unitOfMeasure: "",
    casNumber: "",
    chemicalFormula: "",
    molecularWeight: "",
    vendor: "",
    catalogNumber: "",
    lotNumber: "",
    expirationDate: "",
    concentration: "",
    percentageFull: undefined,
    comments: "",
  };
}

// ── field helper ───────────────────────────────────────────────────────────

function Field({ label, value, required }: { label: string; value?: string | number; required?: boolean }) {
  if (!value && value !== 0) return null;
  return (
    <div>
      <p className={`text-xs mb-0.5 ${required ? "text-red-500" : "text-muted-foreground"}`}>{label}</p>
      <p className="text-sm text-foreground">{value}</p>
    </div>
  );
}

// ── main component ─────────────────────────────────────────────────────────

export function Inventory() {
  const [inventory, setInventory] = useState<ChemicalInventory[]>([]);
  const [profile, setProfile] = useState<UserProfile | null>(null);
  const [isLoading, setIsLoading] = useState(true);
  const [searchQuery, setSearchQuery] = useState("");
  const [expandedId, setExpandedId] = useState<string | null>(null);

  // add/edit dialog
  const [dialogOpen, setDialogOpen] = useState(false);
  const [editingItem, setEditingItem] = useState<ChemicalInventory | null>(null);
  const [form, setForm] = useState<Partial<ChemicalInventory>>(emptyForm());
  const [isSaving, setIsSaving] = useState(false);
  const [formError, setFormError] = useState("");
  const [showOptional, setShowOptional] = useState(false);

  // table view dialog
  const [tableViewOpen, setTableViewOpen] = useState(false);

  // import dialog
  const [importOpen, setImportOpen] = useState(false);
  const [importStep, setImportStep] = useState<"upload" | "map" | "result">("upload");
  const [importHeaders, setImportHeaders] = useState<string[]>([]);
  const [importRows, setImportRows] = useState<string[][]>([]);
  const [columnMapping, setColumnMapping] = useState<Record<string, ImportColumnMapping>>({});
  const [importResult, setImportResult] = useState<{ imported: number; errors: string[] } | null>(null);
  const [isImporting, setIsImporting] = useState(false);
  const [importError, setImportError] = useState("");
  const importFileRef = useRef<HTMLInputElement>(null);

  // scan dialog
  const [scanOpen, setScanOpen] = useState(false);
  const [capturedImage, setCapturedImage] = useState<string | null>(null);
  const [isProcessing, setIsProcessing] = useState(false);
  const [extractedData, setExtractedData] = useState<Partial<ChemicalInventory> | null>(null);
  const fileInputRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    Promise.all([
      chemicalsApi.list(),
      fetch("/api/profile", { credentials: "include" }).then(r => r.ok ? r.json() : null),
    ]).then(([chems, prof]) => {
      setInventory(chems);
      setProfile(prof);
    }).finally(() => setIsLoading(false));
  }, []);

  // ── form helpers ────────────────────────────────────────────────────────

  function openAdd() {
    setEditingItem(null);
    setForm(emptyForm(profile));
    setFormError("");
    setShowOptional(false);
    setDialogOpen(true);
  }

  function openEdit(item: ChemicalInventory) {
    setEditingItem(item);
    setForm({ ...item });
    setFormError("");
    setShowOptional(true);
    setDialogOpen(true);
  }

  function setField(key: keyof ChemicalInventory, value: string | number | undefined) {
    setForm(f => ({ ...f, [key]: value }));
  }

  async function handleSave() {
    const required: (keyof ChemicalInventory)[] = [
      "piFirstName","physicalState","chemicalName","bldgCode","lab",
      "storageLocation","storageDevice","numberOfContainers","amountPerContainer",
      "unitOfMeasure","casNumber",
    ];
    const missing = required.filter(k => !form[k]);
    if (missing.length) {
      setFormError("Please fill in all required fields.");
      return;
    }
    if (!validateCAS(String(form.casNumber || ""))) {
      setFormError("CAS # must be in the format ##-##-# (e.g. 67-56-1).");
      return;
    }
    if (!validateNumber(form.numberOfContainers, { min: 1, integer: true })) {
      setFormError("# of containers must be a whole number of 1 or more.");
      return;
    }
    if (!validateNumber(form.amountPerContainer, { min: 0 })) {
      setFormError("Amount per container must be a number.");
      return;
    }
    if (form.molecularWeight && !validateNumber(form.molecularWeight, { min: 0 })) {
      setFormError("Molecular weight must be a number.");
      return;
    }
    if (form.percentageFull != null && !validateNumber(form.percentageFull, { min: 0, max: 100 })) {
      setFormError("% full must be between 0 and 100.");
      return;
    }
    if (form.contact && !validatePhoneOrEmail(String(form.contact))) {
      setFormError("Contact must be a valid phone number or email address.");
      return;
    }
    setFormError("");
    setIsSaving(true);
    try {
      if (editingItem) {
        const updated = await chemicalsApi.update(editingItem.id, form);
        setInventory(inv => inv.map(c => c.id === editingItem.id ? updated : c));
      } else {
        const saved = await chemicalsApi.create(form as ChemicalInventory);
        setInventory(inv => [saved, ...inv]);
      }
      setDialogOpen(false);
    } catch {
      setFormError("Failed to save. Please try again.");
    } finally {
      setIsSaving(false);
    }
  }

  async function handleDelete(id: string) {
    if (!confirm("Remove this chemical from inventory?")) return;
    await chemicalsApi.remove(id);
    setInventory(inv => inv.filter(c => c.id !== id));
    if (expandedId === id) setExpandedId(null);
  }

  // ── scan helpers ────────────────────────────────────────────────────────

  function handlePhotoCapture(e: React.ChangeEvent<HTMLInputElement>) {
    const file = e.target.files?.[0];
    if (!file) return;
    const reader = new FileReader();
    reader.onloadend = () => {
      setCapturedImage(reader.result as string);
      setIsProcessing(true);
      setTimeout(() => {
        setExtractedData({
          chemicalName: "Methanol", casNumber: "67-56-1", physicalState: "Liquid",
          vendor: "Sigma-Aldrich", lotNumber: "SLCD7890", catalogNumber: "34860",
          amountPerContainer: "1", unitOfMeasure: "L", numberOfContainers: "1",
          storageDevice: "Glass Bottle", chemicalFormula: "CH3OH", molecularWeight: "32.04",
          expirationDate: "2026-03-15", concentration: "99.8%", percentageFull: 95,
          needsManualEntry: ["piFirstName", "bldgCode", "lab", "storageLocation"],
          scannedImage: reader.result as string,
          piFirstName: profile?.pi_first_name ?? "",
          bldgCode: profile?.bldg_code ?? "",
          lab: profile?.lab ?? "",
        });
        setIsProcessing(false);
      }, 2000);
    };
    reader.readAsDataURL(file);
  }

  async function handleAddFromScan() {
    if (!extractedData) return;
    try {
      const saved = await chemicalsApi.create({
        ...extractedData,
        piFirstName: extractedData.piFirstName || "",
        physicalState: extractedData.physicalState || "",
        chemicalName: extractedData.chemicalName || "",
        bldgCode: extractedData.bldgCode || "",
        lab: extractedData.lab || "",
        storageLocation: extractedData.storageLocation || "",
        storageDevice: extractedData.storageDevice || "Glass Bottle",
        numberOfContainers: extractedData.numberOfContainers || "1",
        amountPerContainer: extractedData.amountPerContainer || "",
        unitOfMeasure: extractedData.unitOfMeasure || "",
        casNumber: extractedData.casNumber || "",
      });
      setInventory(inv => [saved, ...inv]);
      setCapturedImage(null); setExtractedData(null); setScanOpen(false);
    } catch (err) { console.error(err); }
  }

  // ── export helpers ──────────────────────────────────────────────────────

  function handleDownloadCSV() {
    const headers = TABLE_COLUMNS.map(c => c.label);
    const rows = filtered.map(item =>
      TABLE_COLUMNS.map(c => String(item[c.key] ?? ""))
    );
    const csv = [headers, ...rows]
      .map(row => row.map(cell => `"${cell.replace(/"/g, '""')}"`).join(","))
      .join("\n");
    const blob = new Blob([csv], { type: "text/csv;charset=utf-8;" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = "chemical_inventory.csv";
    a.click();
    URL.revokeObjectURL(url);
  }

  async function handleDownloadExcel() {
    const wb = new ExcelJS.Workbook();
    const ws = wb.addWorksheet("Chemical Inventory");
    ws.addRow(TABLE_COLUMNS.map(c => c.label));
    filtered.forEach(item => ws.addRow(TABLE_COLUMNS.map(c => item[c.key] ?? "")));
    const buffer = await wb.xlsx.writeBuffer();
    const blob = new Blob([buffer], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = "chemical_inventory.xlsx";
    a.click();
    URL.revokeObjectURL(url);
  }

  // ── import helpers ──────────────────────────────────────────────────────

  function normalizeHeader(s: string): string {
    return s.toLowerCase().replace(/[^a-z0-9]/g, "");
  }

  function fuzzyMatchColumn(header: string): ImportColumnMapping {
    const norm = normalizeHeader(header);
    if (!norm) return "__skip__";
    for (const col of TABLE_COLUMNS) {
      if (normalizeHeader(col.label) === norm) return col.key;
    }
    for (const col of TABLE_COLUMNS) {
      const colNorm = normalizeHeader(col.label);
      if (colNorm.startsWith(norm) || norm.startsWith(colNorm)) return col.key;
    }
    let bestKey: ImportColumnMapping = "__skip__";
    let bestScore = 0.55;
    for (const col of TABLE_COLUMNS) {
      const colNorm = normalizeHeader(col.label);
      let matches = 0, ci = 0;
      for (const ch of norm) {
        while (ci < colNorm.length && colNorm[ci] !== ch) ci++;
        if (ci < colNorm.length) { matches++; ci++; }
      }
      const score = matches / Math.max(norm.length, colNorm.length);
      if (score > bestScore) { bestScore = score; bestKey = col.key; }
    }
    return bestKey;
  }

  function openImport() {
    setImportStep("upload");
    setImportHeaders([]);
    setImportRows([]);
    setColumnMapping({});
    setImportResult(null);
    setImportError("");
    setImportOpen(true);
  }

  async function handleImportFileSelect(e: React.ChangeEvent<HTMLInputElement>) {
    const file = e.target.files?.[0];
    console.log("[import] file selected:", file?.name, file?.type, file?.size);
    if (!file) return;
    e.target.value = "";
    setImportError("");

    try {
      let allRows: string[][];

      if (file.name.toLowerCase().endsWith(".csv")) {
        console.log("[import] parsing as CSV");
        const text = await file.text();
        console.log("[import] CSV text length:", text.length);
        allRows = text.split(/\r?\n/).map(line => {
          const row: string[] = [];
          let cur = "", inQuote = false;
          for (let i = 0; i < line.length; i++) {
            const ch = line[i];
            if (ch === '"') {
              if (inQuote && line[i + 1] === '"') { cur += '"'; i++; }
              else inQuote = !inQuote;
            } else if (ch === "," && !inQuote) {
              row.push(cur); cur = "";
            } else {
              cur += ch;
            }
          }
          row.push(cur);
          return row;
        });
      } else {
        console.log("[import] parsing as XLSX");
        const buffer = await file.arrayBuffer();
        console.log("[import] arrayBuffer size:", buffer.byteLength);
        const wb = new ExcelJS.Workbook();
        await wb.xlsx.load(buffer);
        console.log("[import] workbook loaded, worksheets:", wb.worksheets.length);
        const ws = wb.worksheets[0];
        if (!ws) throw new Error("No worksheets found in this file.");
        allRows = [];
        ws.eachRow(row => {
          allRows.push((row.values as ExcelJS.CellValue[]).slice(1).map(v => String(v ?? "")));
        });
        console.log("[import] parsed rows:", allRows.length);
      }

      if (allRows.length < 2) {
        setImportError("The file appears to be empty or has no data rows.");
        return;
      }
      const headers = allRows[0];
      const dataRows = allRows.slice(1).filter(r => r.some(c => c.trim() !== ""));
      console.log("[import] headers:", headers, "data rows:", dataRows.length);
      setImportHeaders(headers);
      setImportRows(dataRows);
      const mapping: Record<string, ImportColumnMapping> = {};
      for (const h of headers) mapping[h] = fuzzyMatchColumn(h);
      setColumnMapping(mapping);
      console.log("[import] advancing to map step");
      setImportStep("map");
    } catch (err) {
      console.error("[import] error:", err);
      setImportError(`Could not read file: ${(err as Error).message}`);
    }
  }

  async function handleImportConfirm() {
    setIsImporting(true);
    try {
      const rows = importRows.map(row => {
        const chemical: Partial<ChemicalInventory> = {};
        importHeaders.forEach((header, i) => {
          const key = columnMapping[header];
          if (key && key !== "__skip__") (chemical as Record<string, string>)[key] = row[i] ?? "";
        });
        return chemical;
      });
      const result = await chemicalsApi.import(rows);
      setImportResult(result);
      setImportStep("result");
      if (result.imported > 0) {
        const updated = await chemicalsApi.list();
        setInventory(updated);
      }
    } catch (err) {
      setImportResult({ imported: 0, errors: [(err as Error).message] });
      setImportStep("result");
    } finally {
      setIsImporting(false);
    }
  }

  // ── derived ─────────────────────────────────────────────────────────────

  const filtered = inventory.filter(c =>
    c.chemicalName.toLowerCase().includes(searchQuery.toLowerCase()) ||
    c.casNumber.includes(searchQuery) ||
    c.lab.toLowerCase().includes(searchQuery.toLowerCase()) ||
    (c.storageLocation || "").toLowerCase().includes(searchQuery.toLowerCase())
  );

  const lowStockCount = inventory.filter(c => c.percentageFull != null && c.percentageFull < 20).length;

  // ── render ───────────────────────────────────────────────────────────────

  return (
    <div className="p-6 max-w-5xl mx-auto">

      {/* Header */}
      <div className="flex items-center justify-between mb-4">
        <div>
          <h1 className="text-foreground mb-1">Chemical Inventory</h1>
          <p className="text-muted-foreground text-sm">Track, manage, and monitor your lab chemicals</p>
        </div>
        <div className="flex gap-2">
          {/* Import Excel */}
          <Button variant="outline" className="gap-2" onClick={openImport}>
            <Upload className="w-4 h-4" /> Import Table
          </Button>

          {/* Add manually */}
          <Button onClick={openAdd} className="gap-2 bg-primary hover:bg-primary/90">
            <Plus className="w-4 h-4" /> Add Chemical
          </Button>

          {/* Scan */}
          <Dialog open={scanOpen} onOpenChange={setScanOpen}>
            <DialogTrigger asChild>
              <Button variant="outline" className="gap-2">
                <Camera className="w-4 h-4" /> Scan Label
              </Button>
            </DialogTrigger>
            <DialogContent className="max-w-2xl max-h-[90vh] overflow-y-auto">
              <DialogHeader>
                <DialogTitle className="flex items-center gap-2">
                  <Camera className="w-5 h-5" /> Scan Chemical Label
                </DialogTitle>
              </DialogHeader>
              <div className="space-y-4 py-2">
                {!capturedImage ? (
                  <div
                    className="border-2 border-dashed border-border rounded-lg p-12 text-center hover:border-primary transition-colors cursor-pointer bg-muted/30"
                    onClick={() => fileInputRef.current?.click()}
                  >
                    <Camera className="w-14 h-14 text-muted-foreground mx-auto mb-3" />
                    <p className="text-foreground mb-1">Click to capture or upload a label photo</p>
                    <p className="text-muted-foreground text-sm">AI will extract all available information</p>
                    <input ref={fileInputRef} type="file" accept="image/*" capture="environment"
                      className="hidden" onChange={handlePhotoCapture} />
                  </div>
                ) : (
                  <div className="space-y-4">
                    <img src={capturedImage} alt="Scanned label" className="w-full rounded-lg border border-border" />
                    {isProcessing ? (
                      <div className="bg-accent border border-border rounded-lg p-6 text-center">
                        <Sparkles className="w-8 h-8 text-primary mx-auto mb-2 animate-pulse" />
                        <p className="text-foreground">Scanning label…</p>
                        <p className="text-muted-foreground text-sm">Reading all visible information with AI</p>
                      </div>
                    ) : extractedData ? (
                      <div className="space-y-4">
                        <div className="bg-accent border border-border rounded-lg p-3 flex items-start gap-2">
                          <Sparkles className="w-4 h-4 text-primary mt-0.5" />
                          <p className="text-sm text-foreground">Information extracted. Yellow fields need manual entry.</p>
                        </div>
                        <div className="grid grid-cols-2 gap-3">
                          {(["piFirstName","bldgCode","lab","storageLocation"] as const).map(k => (
                            <div key={k} className={`space-y-1 ${extractedData.needsManualEntry?.includes(k) ? "bg-yellow-50 p-2 rounded" : ""}`}>
                              <Label className="text-red-600 text-xs">{k === "piFirstName" ? "PI First Name" : k === "bldgCode" ? "Building Code" : k === "lab" ? "Lab" : "Storage Location"} *</Label>
                              <Input value={(extractedData as Record<string,string>)[k] || ""} onChange={e => setExtractedData({ ...extractedData, [k]: e.target.value })} />
                            </div>
                          ))}
                          <div className="space-y-1">
                            <Label className="text-red-600 text-xs">Chemical Name *</Label>
                            <Input value={extractedData.chemicalName || ""} onChange={e => setExtractedData({...extractedData, chemicalName: e.target.value})} />
                          </div>
                          <div className="space-y-1">
                            <Label className="text-red-600 text-xs">CAS # *</Label>
                            <Input value={extractedData.casNumber || ""} onChange={e => setExtractedData({...extractedData, casNumber: e.target.value})} />
                          </div>
                          <div className="space-y-1">
                            <Label className="text-red-600 text-xs">Physical State *</Label>
                            <Select value={extractedData.physicalState} onValueChange={v => setExtractedData({...extractedData, physicalState: v})}>
                              <SelectTrigger><SelectValue /></SelectTrigger>
                              <SelectContent>{physicalStates.map(s => <SelectItem key={s} value={s}>{s}</SelectItem>)}</SelectContent>
                            </Select>
                          </div>
                          <div className="space-y-1">
                            <Label className="text-red-600 text-xs">Storage Device *</Label>
                            <Select value={extractedData.storageDevice} onValueChange={v => setExtractedData({...extractedData, storageDevice: v})}>
                              <SelectTrigger><SelectValue /></SelectTrigger>
                              <SelectContent>{storageDeviceOptions.map(s => <SelectItem key={s} value={s}>{s}</SelectItem>)}</SelectContent>
                            </Select>
                          </div>
                          <div className="space-y-1">
                            <Label className="text-xs">Amount / Container</Label>
                            <Input value={extractedData.amountPerContainer || ""} onChange={e => setExtractedData({...extractedData, amountPerContainer: e.target.value})} />
                          </div>
                          <div className="space-y-1">
                            <Label className="text-xs">Unit</Label>
                            <Input value={extractedData.unitOfMeasure || ""} onChange={e => setExtractedData({...extractedData, unitOfMeasure: e.target.value})} />
                          </div>
                          <div className="space-y-1">
                            <Label className="text-xs">Expiration Date</Label>
                            <Input type="date" value={extractedData.expirationDate || ""} onChange={e => setExtractedData({...extractedData, expirationDate: e.target.value})} />
                          </div>
                          <div className="space-y-1">
                            <Label className="text-xs text-blue-600">% Full</Label>
                            <Input type="number" min={0} max={100} value={extractedData.percentageFull ?? ""} onChange={e => setExtractedData({...extractedData, percentageFull: parseFloat(e.target.value)})} />
                          </div>
                        </div>
                        <div className="flex gap-2">
                          <Button className="flex-1 bg-primary hover:bg-primary/90" onClick={handleAddFromScan}>Add to Inventory</Button>
                          <Button variant="outline" onClick={() => { setCapturedImage(null); setExtractedData(null); }}>Retake</Button>
                        </div>
                      </div>
                    ) : null}
                  </div>
                )}
              </div>
            </DialogContent>
          </Dialog>
        </div>
      </div>

      {/* Import Excel dialog */}
      <Dialog open={importOpen} onOpenChange={setImportOpen}>
        <DialogContent className="max-w-2xl max-h-[90vh] overflow-y-auto">
          <DialogHeader>
            <DialogTitle className="flex items-center gap-2">
              <Upload className="w-5 h-5" /> Import File
            </DialogTitle>
          </DialogHeader>

          {importStep === "upload" && (
            <div className="space-y-3 mt-2">
              <div
                className="border-2 border-dashed border-border rounded-lg p-12 text-center hover:border-primary transition-colors cursor-pointer bg-muted/30"
                onClick={() => importFileRef.current?.click()}
                onDragOver={e => { e.preventDefault(); e.currentTarget.classList.add("border-primary"); }}
                onDragLeave={e => e.currentTarget.classList.remove("border-primary")}
                onDrop={e => {
                  e.preventDefault();
                  e.currentTarget.classList.remove("border-primary");
                  const file = e.dataTransfer.files[0];
                  if (file) handleImportFileSelect({ target: { files: e.dataTransfer.files, value: "" } } as unknown as React.ChangeEvent<HTMLInputElement>);
                }}
              >
                <FileSpreadsheet className="w-14 h-14 text-muted-foreground mx-auto mb-3" />
                <p className="text-foreground mb-1">Click or drag a file here</p>
                <p className="text-muted-foreground text-sm">Supports .xlsx and .csv — columns will be automatically matched to your inventory fields</p>
                <input ref={importFileRef} type="file" accept=".xlsx,.xls,.csv" className="hidden" onChange={handleImportFileSelect} />
              </div>
              {importError && (
                <p className="text-sm text-red-600 flex items-center gap-1">
                  <AlertTriangle className="w-4 h-4 shrink-0" /> {importError}
                </p>
              )}
            </div>
          )}

          {importStep === "map" && (
            <div className="space-y-4 mt-2">
              <p className="text-sm text-muted-foreground">
                Review the column mapping below. Adjust any mismatches before importing{" "}
                <span className="font-medium text-foreground">{importRows.length} row{importRows.length !== 1 ? "s" : ""}</span>.
              </p>
              <div className="border border-border rounded-lg overflow-hidden">
                <table className="w-full text-sm">
                  <thead className="bg-muted/50">
                    <tr>
                      <th className="text-left px-3 py-2 text-muted-foreground font-medium">File Column</th>
                      <th className="text-left px-3 py-2 text-muted-foreground font-medium w-8"></th>
                      <th className="text-left px-3 py-2 text-muted-foreground font-medium">Maps To</th>
                      <th className="text-left px-3 py-2 text-muted-foreground font-medium">Sample</th>
                    </tr>
                  </thead>
                  <tbody>
                    {importHeaders.map((header, idx) => (
                      <tr key={header} className="border-t border-border">
                        <td className="px-3 py-2 text-foreground font-mono text-xs">{header}</td>
                        <td className="px-1 py-2 text-muted-foreground">
                          <ArrowRight className="w-3 h-3" />
                        </td>
                        <td className="px-3 py-2">
                          <Select
                            value={columnMapping[header] ?? ""}
                            onValueChange={v => setColumnMapping(m => ({ ...m, [header]: v as ImportColumnMapping }))}
                          >
                            <SelectTrigger className="h-7 text-xs w-48">
                              <SelectValue placeholder="— skip —" />
                            </SelectTrigger>
                            <SelectContent>
                              <SelectItem value="__skip__">— skip —</SelectItem>
                              {TABLE_COLUMNS.map(col => (
                                <SelectItem key={col.key} value={col.key}>{col.label}</SelectItem>
                              ))}
                            </SelectContent>
                          </Select>
                        </td>
                        <td className="px-3 py-2 text-muted-foreground text-xs truncate max-w-[120px]">
                          {importRows[0]?.[idx] ?? ""}
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
              <div className="flex gap-2 pt-1">
                <Button
                  className="flex-1 bg-primary hover:bg-primary/90 gap-2"
                  onClick={handleImportConfirm}
                  disabled={isImporting}
                >
                  {isImporting ? <Loader2 className="w-4 h-4 animate-spin" /> : <Upload className="w-4 h-4" />}
                  {isImporting ? "Importing…" : `Import ${importRows.length} row${importRows.length !== 1 ? "s" : ""}`}
                </Button>
                <Button variant="outline" onClick={() => setImportStep("upload")}>Back</Button>
              </div>
            </div>
          )}

          {importStep === "result" && importResult && (
            <div className="space-y-4 mt-2">
              <div className={`rounded-lg p-4 border ${importResult.imported > 0 ? "bg-accent border-border" : "bg-red-50 border-red-200"}`}>
                <p className="font-medium text-foreground">
                  {importResult.imported > 0
                    ? `Successfully imported ${importResult.imported} chemical${importResult.imported !== 1 ? "s" : ""}.`
                    : "No rows were imported."}
                </p>
              </div>
              {importResult.errors.length > 0 && (
                <div className="space-y-1">
                  <p className="text-sm font-medium text-red-600 flex items-center gap-1">
                    <AlertTriangle className="w-4 h-4" /> {importResult.errors.length} row{importResult.errors.length !== 1 ? "s" : ""} failed
                  </p>
                  <div className="border border-red-200 rounded-lg bg-red-50 p-3 max-h-40 overflow-y-auto space-y-1">
                    {importResult.errors.map((e, i) => (
                      <p key={i} className="text-xs text-red-700 font-mono">{e}</p>
                    ))}
                  </div>
                </div>
              )}
              <div className="flex gap-2">
                <Button className="flex-1 bg-primary hover:bg-primary/90" onClick={() => setImportOpen(false)}>Done</Button>
                <Button variant="outline" onClick={openImport}>Import Another File</Button>
              </div>
            </div>
          )}
        </DialogContent>
      </Dialog>

      {/* Email receipt banner */}
      <Card className="p-4 mb-5 bg-gradient-to-r from-accent to-secondary border-border">
        <div className="flex items-start gap-3">
          <Mail className="w-4 h-4 text-primary mt-0.5 shrink-0" />
          <p className="text-sm text-foreground">
            Auto-import receipts: email them to{" "}
            <code className="bg-muted px-1.5 py-0.5 rounded text-primary text-xs">inventory@labwise-auto.com</code>
            {" "}and we'll extract and add chemicals automatically.
          </p>
        </div>
      </Card>

      {/* Search + stats */}
      <div className="flex items-center gap-3 mb-5">
        <div className="relative flex-1">
          <Search className="absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground w-4 h-4" />
          <Input
            placeholder="Search by name, CAS, lab, or location…"
            className="pl-9"
            value={searchQuery}
            onChange={e => setSearchQuery(e.target.value)}
          />
        </div>
        <div className="flex items-center gap-2 shrink-0 text-sm text-muted-foreground">
          <FlaskConical className="w-4 h-4 text-[#5a9584]" />
          <span>{inventory.length} chemicals</span>
          {lowStockCount > 0 && (
            <>
              <span className="text-border">·</span>
              <AlertTriangle className="w-4 h-4 text-amber-500" />
              <span className="text-amber-600">{lowStockCount} low stock</span>
            </>
          )}
          <span className="text-border">·</span>
          <Button variant="ghost" size="sm" className="gap-1.5 h-7 px-2 text-muted-foreground bg-background hover:bg-background/80 hover:text-foreground rounded-md" onClick={() => setTableViewOpen(true)}>
            <Table2 className="w-3.5 h-3.5" /> View / Export Table
          </Button>
        </div>
      </div>

      {/* List */}
      {isLoading ? (
        <div className="flex justify-center py-16">
          <Loader2 className="w-6 h-6 animate-spin text-muted-foreground" />
        </div>
      ) : filtered.length === 0 ? (
        <div className="text-center py-16 text-muted-foreground">
          {inventory.length === 0
            ? "No chemicals yet. Add one to get started."
            : "No chemicals match your search."}
        </div>
      ) : (
        <div className="space-y-2">
          {filtered.map(item => {
            const isExpanded = expandedId === item.id;
            const days = item.expirationDate ? daysUntil(item.expirationDate) : null;
            const expired = days !== null && days < 0;
            const expiringSoon = days !== null && days >= 0 && days <= 30;
            const lowStock = item.percentageFull != null && item.percentageFull < 20;

            return (
              <Card key={item.id} className={`overflow-hidden transition-shadow ${isExpanded ? "shadow-md" : "hover:shadow-sm"}`}>
                {/* Summary row */}
                <button
                  className="w-full text-left px-5 py-4 flex items-center gap-4"
                  onClick={() => setExpandedId(isExpanded ? null : item.id)}
                >
                  {/* Name + state */}
                  <div className="flex-1 min-w-0">
                    <div className="flex items-center gap-2 flex-wrap">
                      <span className="font-medium text-foreground">{item.chemicalName}</span>
                      <span className="text-xs text-muted-foreground bg-muted px-1.5 py-0.5 rounded">{item.physicalState}</span>
                      {expired && <Badge className="bg-red-100 text-red-700 border-red-200 border text-xs py-0">Expired</Badge>}
                      {expiringSoon && !expired && <Badge className="bg-amber-100 text-amber-700 border-amber-200 border text-xs py-0">Exp. {days}d</Badge>}
                      {lowStock && <Badge className="bg-red-100 text-red-700 border-red-200 border text-xs py-0">Low stock</Badge>}
                    </div>
                    <p className="text-sm text-muted-foreground mt-0.5">{item.lab} · {item.storageLocation || "—"}</p>
                  </div>

                  {/* Amount */}
                  <div className="text-sm text-muted-foreground shrink-0 hidden sm:block">
                    {item.numberOfContainers} × {item.amountPerContainer} {item.unitOfMeasure}
                  </div>

                  {/* Fill bar */}
                  {item.percentageFull != null && (
                    <div className="flex items-center gap-2 shrink-0 hidden md:flex">
                      <div className="w-20 h-1.5 bg-muted rounded-full overflow-hidden">
                        <div className={`h-full rounded-full ${fillBarColor(item.percentageFull)}`} style={{ width: `${item.percentageFull}%` }} />
                      </div>
                      <span className="text-xs text-muted-foreground w-8">{item.percentageFull}%</span>
                    </div>
                  )}

                  {/* Chevron */}
                  {isExpanded
                    ? <ChevronUp className="w-4 h-4 text-muted-foreground shrink-0" />
                    : <ChevronDown className="w-4 h-4 text-muted-foreground shrink-0" />}
                </button>

                {/* Expanded detail */}
                {isExpanded && (
                  <div className="border-t border-border px-5 py-4 bg-secondary/40">
                    <div className="grid grid-cols-1 sm:grid-cols-3 gap-6 mb-5">

                      {/* Storage */}
                      <div className="space-y-3">
                        <p className="text-xs font-semibold text-muted-foreground uppercase tracking-wide">Storage</p>
                        <Field label="Building" value={item.bldgCode} required />
                        <Field label="Lab" value={item.lab} required />
                        <Field label="Location" value={item.storageLocation} required />
                        <Field label="Device" value={item.storageDevice} required />
                        <Field label="Containers" value={item.numberOfContainers} required />
                        <Field label="Amount / Container" value={`${item.amountPerContainer} ${item.unitOfMeasure}`} required />
                        {item.percentageFull != null && (
                          <div>
                            <p className="text-xs text-muted-foreground mb-1">Fill level</p>
                            <div className="flex items-center gap-2">
                              <div className="flex-1 h-2 bg-muted rounded-full overflow-hidden">
                                <div className={`h-full rounded-full ${fillBarColor(item.percentageFull)}`} style={{ width: `${item.percentageFull}%` }} />
                              </div>
                              <span className="text-sm font-medium">{item.percentageFull}%</span>
                            </div>
                          </div>
                        )}
                      </div>

                      {/* Chemical info */}
                      <div className="space-y-3">
                        <p className="text-xs font-semibold text-muted-foreground uppercase tracking-wide">Chemical</p>
                        <Field label="CAS #" value={item.casNumber} required />
                        <Field label="Physical State" value={item.physicalState} required />
                        <Field label="Formula" value={item.chemicalFormula} />
                        <Field label="Molecular Weight" value={item.molecularWeight ? `${item.molecularWeight} g/mol` : undefined} />
                        <Field label="Concentration" value={item.concentration} />
                        <Field label="PI" value={item.piFirstName} />
                        <Field label="Contact" value={item.contact} />
                      </div>

                      {/* Procurement */}
                      <div className="space-y-3">
                        <p className="text-xs font-semibold text-muted-foreground uppercase tracking-wide">Procurement</p>
                        <Field label="Vendor" value={item.vendor} />
                        <Field label="Catalog #" value={item.catalogNumber} />
                        <Field label="Lot #" value={item.lotNumber} />
                        {item.expirationDate && (
                          <div>
                            <p className="text-xs text-muted-foreground mb-0.5">Expiration</p>
                            <p className={`text-sm font-medium ${expired ? "text-red-600" : expiringSoon ? "text-amber-600" : "text-foreground"}`}>
                              {item.expirationDate}
                              {expired && ` (expired ${Math.abs(days!)}d ago)`}
                              {expiringSoon && ` (${days}d left)`}
                            </p>
                          </div>
                        )}
                        <Field label="Barcode" value={item.barcode} />
                        {item.comments && (
                          <div>
                            <p className="text-xs text-muted-foreground mb-0.5">Comments</p>
                            <p className="text-sm text-foreground whitespace-pre-wrap">{item.comments}</p>
                          </div>
                        )}
                      </div>
                    </div>

                    <div className="flex gap-2 pt-2 border-t border-border">
                      <Button size="sm" variant="outline" onClick={() => openEdit(item)}>Edit</Button>
                      <Button size="sm" variant="ghost" className="text-red-600 hover:text-red-700 hover:bg-red-50" onClick={() => handleDelete(item.id)}>
                        <Trash2 className="w-4 h-4 mr-1" /> Delete
                      </Button>
                    </div>
                  </div>
                )}
              </Card>
            );
          })}
        </div>
      )}

      {/* Table View dialog */}
      <Dialog open={tableViewOpen} onOpenChange={setTableViewOpen}>
        <DialogContent className="sm:max-w-[95vw] w-[95vw] h-[90vh] flex flex-col p-0">
          <DialogHeader className="px-5 pt-5 pb-3 shrink-0 border-b border-border">
            <div className="flex items-center justify-between">
              <DialogTitle className="flex items-center gap-2">
                <Table2 className="w-5 h-5" /> Inventory Table
                <span className="text-sm font-normal text-muted-foreground ml-1">
                  ({filtered.length} {filtered.length === 1 ? "chemical" : "chemicals"})
                </span>
              </DialogTitle>
              <div className="flex gap-2 mr-6">
                <Button size="sm" variant="outline" className="gap-1.5" onClick={handleDownloadCSV}>
                  <FileDown className="w-4 h-4" /> CSV
                </Button>
                <Button size="sm" variant="outline" className="gap-1.5" onClick={handleDownloadExcel}>
                  <FileSpreadsheet className="w-4 h-4" /> Excel
                </Button>
              </div>
            </div>
          </DialogHeader>
          <div className="table-scroll flex-1">
            <table className="text-xs border-collapse min-w-max">
              <thead className="sticky top-0 z-10 bg-muted">
                <tr>
                  {TABLE_COLUMNS.map(col => (
                    <th
                      key={col.key}
                      className="text-left px-3 py-2 font-semibold text-muted-foreground whitespace-nowrap border-b border-r border-border last:border-r-0"
                    >
                      {col.label}
                    </th>
                  ))}
                </tr>
              </thead>
              <tbody>
                {filtered.map((item, i) => (
                  <tr key={item.id} className={i % 2 === 0 ? "bg-background" : "bg-muted/30"}>
                    {TABLE_COLUMNS.map(col => (
                      <td
                        key={col.key}
                        className="px-3 py-1.5 whitespace-nowrap border-b border-r border-border/50 last:border-r-0 max-w-[200px] overflow-hidden text-ellipsis"
                        title={String(item[col.key] ?? "")}
                      >
                        {String(item[col.key] ?? "")}
                      </td>
                    ))}
                  </tr>
                ))}
                {filtered.length === 0 && (
                  <tr>
                    <td colSpan={TABLE_COLUMNS.length} className="text-center py-10 text-muted-foreground">
                      No chemicals to display.
                    </td>
                  </tr>
                )}
              </tbody>
            </table>
          </div>
        </DialogContent>
      </Dialog>

      {/* Add / Edit dialog */}
      <Dialog open={dialogOpen} onOpenChange={setDialogOpen}>
        <DialogContent className="max-w-2xl max-h-[90vh] overflow-y-auto">
          <DialogHeader>
            <DialogTitle>{editingItem ? "Edit Chemical" : "Add Chemical"}</DialogTitle>
          </DialogHeader>

          <div className="space-y-5 py-2">
            {/* Required fields */}
            <div>
              <p className="text-xs font-semibold text-muted-foreground uppercase tracking-wide mb-3">Required fields</p>
              <div className="grid grid-cols-2 gap-3">

                <div className="space-y-1">
                  <Label className="text-xs">Chemical Name <span className="text-red-500">*</span></Label>
                  <Input value={form.chemicalName || ""} onChange={e => setField("chemicalName", e.target.value)} />
                </div>

                <div className="space-y-1">
                  <Label className="text-xs">CAS # <span className="text-red-500">*</span></Label>
                  <Input
                    value={form.casNumber || ""}
                    onChange={e => setField("casNumber", e.target.value)}
                    placeholder="e.g. 67-56-1"
                    inputMode="numeric"
                    pattern="\d{2,7}-\d{2}-\d"
                    title="CAS format: digits-digits-digit (e.g. 67-56-1)"
                  />
                </div>

                <div className="space-y-1">
                  <Label className="text-xs">Physical State <span className="text-red-500">*</span></Label>
                  <Select value={form.physicalState || ""} onValueChange={v => setField("physicalState", v)}>
                    <SelectTrigger><SelectValue placeholder="Select…" /></SelectTrigger>
                    <SelectContent>{physicalStates.map(s => <SelectItem key={s} value={s}>{s}</SelectItem>)}</SelectContent>
                  </Select>
                </div>

                <div className="space-y-1">
                  <Label className="text-xs">Storage Device <span className="text-red-500">*</span></Label>
                  <Select value={form.storageDevice || ""} onValueChange={v => setField("storageDevice", v)}>
                    <SelectTrigger><SelectValue placeholder="Select…" /></SelectTrigger>
                    <SelectContent>{storageDeviceOptions.map(s => <SelectItem key={s} value={s}>{s}</SelectItem>)}</SelectContent>
                  </Select>
                </div>

                <div className="space-y-1">
                  <Label className="text-xs">PI First Name <span className="text-red-500">*</span></Label>
                  <Input value={form.piFirstName || ""} onChange={e => setField("piFirstName", e.target.value)} />
                </div>

                <div className="space-y-1">
                  <Label className="text-xs">Building Code <span className="text-red-500">*</span></Label>
                  <Input value={form.bldgCode || ""} onChange={e => setField("bldgCode", e.target.value)} />
                </div>

                <div className="space-y-1">
                  <Label className="text-xs">Lab <span className="text-red-500">*</span></Label>
                  <Input value={form.lab || ""} onChange={e => setField("lab", e.target.value)} />
                </div>

                <div className="space-y-1">
                  <Label className="text-xs">Storage Location <span className="text-red-500">*</span></Label>
                  <Input value={form.storageLocation || ""} onChange={e => setField("storageLocation", e.target.value)} placeholder="e.g. Cabinet A-3" />
                </div>

                <div className="space-y-1">
                  <Label className="text-xs"># of Containers <span className="text-red-500">*</span></Label>
                  <Input type="number" min={1} value={form.numberOfContainers || ""} onChange={e => setField("numberOfContainers", e.target.value)} />
                </div>

                <div className="space-y-1">
                  <Label className="text-xs">Amount / Container <span className="text-red-500">*</span></Label>
                  <Input
                    type="number"
                    min={0}
                    step="any"
                    value={form.amountPerContainer || ""}
                    onChange={e => setField("amountPerContainer", e.target.value)}
                    placeholder="e.g. 500"
                  />
                </div>

                <div className="space-y-1 col-span-2">
                  <Label className="text-xs">Unit of Measure <span className="text-red-500">*</span></Label>
                  <Select value={form.unitOfMeasure || ""} onValueChange={v => setField("unitOfMeasure", v)}>
                    <SelectTrigger><SelectValue placeholder="Select…" /></SelectTrigger>
                    <SelectContent>
                      {unitOptions.map(u => <SelectItem key={u} value={u}>{u}</SelectItem>)}
                      <SelectItem value="other">Other</SelectItem>
                    </SelectContent>
                  </Select>
                </div>
              </div>
            </div>

            {/* Optional fields toggle */}
            <button
              type="button"
              className="flex items-center gap-1.5 text-sm text-primary hover:underline"
              onClick={() => setShowOptional(v => !v)}
            >
              {showOptional ? <ChevronUp className="w-4 h-4" /> : <ChevronDown className="w-4 h-4" />}
              {showOptional ? "Hide" : "Show"} optional fields
            </button>

            {showOptional && (
              <div>
                <p className="text-xs font-semibold text-muted-foreground uppercase tracking-wide mb-3">Optional fields</p>
                <div className="grid grid-cols-2 gap-3">
                  <div className="space-y-1">
                    <Label className="text-xs">Chemical Formula</Label>
                    <Input value={form.chemicalFormula || ""} onChange={e => setField("chemicalFormula", e.target.value)} placeholder="e.g. CH₃OH" />
                  </div>
                  <div className="space-y-1">
                    <Label className="text-xs">Molecular Weight</Label>
                    <Input
                      type="number"
                      min={0}
                      step="any"
                      value={form.molecularWeight || ""}
                      onChange={e => setField("molecularWeight", e.target.value)}
                      placeholder="g/mol"
                    />
                  </div>
                  <div className="space-y-1">
                    <Label className="text-xs">Concentration</Label>
                    <Input value={form.concentration || ""} onChange={e => setField("concentration", e.target.value)} placeholder="e.g. 99.8%" />
                  </div>
                  <div className="space-y-1">
                    <Label className="text-xs">% Full</Label>
                    <Input type="number" min={0} max={100} value={form.percentageFull ?? ""} onChange={e => setField("percentageFull", e.target.value ? parseFloat(e.target.value) : undefined)} />
                  </div>
                  <div className="space-y-1">
                    <Label className="text-xs">Vendor</Label>
                    <Input value={form.vendor || ""} onChange={e => setField("vendor", e.target.value)} />
                  </div>
                  <div className="space-y-1">
                    <Label className="text-xs">Catalog #</Label>
                    <Input value={form.catalogNumber || ""} onChange={e => setField("catalogNumber", e.target.value)} />
                  </div>
                  <div className="space-y-1">
                    <Label className="text-xs">Lot #</Label>
                    <Input value={form.lotNumber || ""} onChange={e => setField("lotNumber", e.target.value)} />
                  </div>
                  <div className="space-y-1">
                    <Label className="text-xs">Expiration Date</Label>
                    <Input type="date" value={form.expirationDate || ""} onChange={e => setField("expirationDate", e.target.value)} />
                  </div>
                  <div className="space-y-1">
                    <Label className="text-xs">Barcode</Label>
                    <Input value={form.barcode || ""} onChange={e => setField("barcode", e.target.value)} />
                  </div>
                  <div className="space-y-1">
                    <Label className="text-xs">Contact</Label>
                    <Input
                      value={form.contact || ""}
                      onChange={e => setField("contact", e.target.value)}
                      placeholder="Phone (e.g. 555-123-4567) or email"
                    />
                  </div>
                  <div className="space-y-1 col-span-2">
                    <Label className="text-xs">Comments</Label>
                    <Input value={form.comments || ""} onChange={e => setField("comments", e.target.value)} />
                  </div>
                </div>
              </div>
            )}

            {formError && <p className="text-sm text-red-600">{formError}</p>}

            <div className="flex gap-2 pt-1">
              <Button className="flex-1 bg-primary hover:bg-primary/90" onClick={handleSave} disabled={isSaving}>
                {isSaving ? <Loader2 className="w-4 h-4 animate-spin" /> : editingItem ? "Save Changes" : "Add to Inventory"}
              </Button>
              <Button variant="outline" onClick={() => setDialogOpen(false)}>Cancel</Button>
            </div>
          </div>
        </DialogContent>
      </Dialog>
    </div>
  );
}
