import { useState, useRef } from "react";
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import { Beaker, Home, AlertTriangle } from "lucide-react";
import { Link } from "react-router-dom";
import FabricLabCanvas from "@/components/lab/FabricLabCanvas";
import Inventory from "@/components/lab/Inventory";
import ResultsPanel from "@/components/lab/ResultsPanel";
import WorkspaceManager, { Workspace } from "@/components/lab/WorkspaceManager";
import { TimelapseRecorder } from "@/components/lab/TimelapseRecorder";
import { ChemicalCalculator } from "@/components/lab/ChemicalCalculator";
import { useEffect } from "react";
import { experimentTemplates } from "@/data/experimentTemplates";
import { substances } from "@/data/substances";
import { toast } from "sonner";
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
import { generateAiMixObservation } from "@/services/aiMix";

const STORAGE_KEY = 'lab-workspaces';

const Lab = () => {
  const [selectedItem, setSelectedItem] = useState<string | null>(null);
  const [results, setResults] = useState<{ observation: string; equation: string; application: string }[]>([]);
  const [safetyWarning, setSafetyWarning] = useState<string | null>(null);
  const [temperatureC, setTemperatureC] = useState<number>(20);
  const canvasRef = useRef<{ getSnapshot: () => string | null; loadSnapshot: (data: string) => void } | null>(null);
  const pendingMixKeyRef = useRef<string>("");
  const lastSuccessMixKeyRef = useRef<string>("");

  // Load workspaces from localStorage or use default
  const loadWorkspaces = (): Workspace[] => {
    try {
      const saved = localStorage.getItem(STORAGE_KEY);
      if (saved) {
        const parsed = JSON.parse(saved);
        if (Array.isArray(parsed) && parsed.length > 0) {
          toast.success("Expériences restaurées depuis la dernière session");
          return parsed;
        }
      }
    } catch (error) {
      console.error("Erreur lors du chargement:", error);
    }
    return [
      {
        id: "1",
        name: "Expérience 1",
        canvasData: null,
        isFavorite: false,
        history: [],
        historyIndex: -1
      },
    ];
  };

  // Workspace management
  const [workspaces, setWorkspaces] = useState<Workspace[]>(loadWorkspaces);
  const [activeWorkspaceId, setActiveWorkspaceId] = useState(() => {
    const saved = loadWorkspaces();
    return saved[0]?.id || "1";
  });

  const activeWorkspace = workspaces.find((w) => w.id === activeWorkspaceId);

  const canUndo = (activeWorkspace?.historyIndex ?? -1) > 0;
  const canRedo = (activeWorkspace?.historyIndex ?? -1) < (activeWorkspace?.history?.length ?? 0) - 1;

  // Auto-save workspaces to localStorage
  useEffect(() => {
    try {
      localStorage.setItem(STORAGE_KEY, JSON.stringify(workspaces));
    } catch (error) {
      console.error("Erreur lors de la sauvegarde:", error);
    }
  }, [workspaces]);

  const checkSafety = (substanceIds: string[]) => {
    const picked = substanceIds
      .map((id) => substances.find((s) => s.id === id))
      .filter(Boolean);
    if (picked.length < 2) return;

    const high = picked.filter((s: any) => s.hazard === "high");
    if (high.length >= 2) {
      setSafetyWarning(
        `⚠️ DANGER: Plusieurs substances très dangereuses sont présentes (${high
          .map((s: any) => s.name)
          .join(" + ")}). Portez un équipement de protection complet !`,
      );
      setTimeout(() => setSafetyWarning(null), 8000);
      return;
    }

    if (high.length === 1) {
      setSafetyWarning(`⚠️ ATTENTION: Substance dangereuse (${high[0].name}). Manipulez avec précaution.`);
      setTimeout(() => setSafetyWarning(null), 6000);
    }
  };

  const handleMix = async (substanceIds: string[]) => {
    const unique = Array.from(new Set(substanceIds)).filter(Boolean);
    if (unique.length < 2) return;

    // Safety banner (instant feedback), then ask the IA.
    checkSafety(unique);
    const key = `${[...unique].sort().join("+")}@${temperatureC}`;
    if (pendingMixKeyRef.current === key || lastSuccessMixKeyRef.current === key) return;

    pendingMixKeyRef.current = key;
    try {
      const picked = unique
        .map((id) => substances.find((s) => s.id === id))
        .filter(Boolean)
        .map((s: any) => ({
          id: s.id,
          name: s.name,
          formula: s.formula,
          state: s.state,
          hazard: s.hazard,
          description: s.description,
        }));

      if (picked.length < 2) throw new Error("Substances invalides pour l'IA");

      const text = await generateAiMixObservation({
        substances: picked,
        substanceIds: unique,
        temperatureC,
      });
      setResults((prev) => [...prev, text]);
      lastSuccessMixKeyRef.current = key;
    } catch (error) {
      console.error("AI mix error:", error);
      toast.error(error instanceof Error ? error.message : "Erreur lors de la génération IA");
    } finally {
      if (pendingMixKeyRef.current === key) pendingMixKeyRef.current = "";
    }
  };

  const handleWorkspaceChange = (id: string) => {
    setActiveWorkspaceId(id);
  };

  const handleWorkspaceAdd = () => {
    const newId = String(Date.now());
    const newWorkspace: Workspace = {
      id: newId,
      name: `Expérience ${workspaces.length + 1}`,
      canvasData: null,
      isFavorite: false,
      history: [],
      historyIndex: -1,
    };
    setWorkspaces((prev) => [...prev, newWorkspace]);
    setActiveWorkspaceId(newId);
  };

  const handleWorkspaceDelete = (id: string) => {
    if (workspaces.length === 1) return;

    setWorkspaces((prev) => prev.filter((w) => w.id !== id));

    if (activeWorkspaceId === id) {
      const remainingWorkspaces = workspaces.filter((w) => w.id !== id);
      setActiveWorkspaceId(remainingWorkspaces[0].id);
    }
  };

  const handleWorkspaceRename = (id: string, name: string) => {
    setWorkspaces((prev) =>
      prev.map((w) => (w.id === id ? { ...w, name } : w))
    );
  };

  const handleWorkspaceFavorite = (id: string) => {
    setWorkspaces((prev) =>
      prev.map((w) => (w.id === id ? { ...w, isFavorite: !w.isFavorite } : w))
    );
  };

  const handleCanvasChange = (data: string) => {
    setWorkspaces((prev) =>
      prev.map((w) => {
        if (w.id === activeWorkspaceId) {
          const currentHistory = w.history || [];
          const currentIndex = w.historyIndex ?? -1;

          // Remove any "future" history if we're not at the end
          const newHistory = currentHistory.slice(0, currentIndex + 1);

          // Add new state to history (limit to 50 states)
          const updatedHistory = [...newHistory, data].slice(-50);

          return {
            ...w,
            canvasData: data,
            history: updatedHistory,
            historyIndex: updatedHistory.length - 1,
          };
        }
        return w;
      })
    );
  };

  const handleUndo = () => {
    if (!canUndo || !activeWorkspace) return;

    const newIndex = (activeWorkspace.historyIndex ?? 0) - 1;
    const previousState = activeWorkspace.history?.[newIndex];

    if (previousState !== undefined) {
      setWorkspaces((prev) =>
        prev.map((w) =>
          w.id === activeWorkspaceId
            ? { ...w, canvasData: previousState, historyIndex: newIndex }
            : w
        )
      );
    }
  };

  const handleRedo = () => {
    if (!activeWorkspace || !canRedo) return;

    const newIndex = activeWorkspace.historyIndex! + 1;
    const canvasData = activeWorkspace.history![newIndex];

    setWorkspaces((prev) =>
      prev.map((w) =>
        w.id === activeWorkspaceId
          ? { ...w, canvasData, historyIndex: newIndex }
          : w
      )
    );
  };

  // Import workspace from JSON
  const handleImportWorkspace = () => {
    const input = document.createElement('input');
    input.type = 'file';
    input.accept = '.json';
    input.onchange = (e) => {
      const file = (e.target as HTMLInputElement).files?.[0];
      if (!file) return;

      const reader = new FileReader();
      reader.onload = (event) => {
        try {
          const imported = JSON.parse(event.target?.result as string) as Workspace;

          // Validate structure
          if (!imported.id || !imported.name) {
            toast.error("Fichier JSON invalide");
            return;
          }

          // Generate new ID to avoid conflicts
          const newWorkspace: Workspace = {
            ...imported,
            id: String(Date.now()),
            name: `${imported.name} (importé)`
          };

          setWorkspaces((prev) => [...prev, newWorkspace]);
          setActiveWorkspaceId(newWorkspace.id);
          toast.success(`Plan de travail "${newWorkspace.name}" importé avec succès`);
        } catch (error) {
          toast.error("Erreur lors de l'importation du fichier JSON");
          console.error(error);
        }
      };
      reader.readAsText(file);
    };
    input.click();
  };

  // Export workspace to JSON
  const handleExportWorkspace = () => {
    if (!activeWorkspace) return;

    const dataStr = JSON.stringify(activeWorkspace, null, 2);
    const dataBlob = new Blob([dataStr], { type: 'application/json' });
    const url = URL.createObjectURL(dataBlob);
    const link = document.createElement('a');
    link.href = url;
    link.download = `${activeWorkspace.name.replace(/\s+/g, '_')}_${Date.now()}.json`;
    link.click();
    URL.revokeObjectURL(url);
    toast.success("Plan de travail exporté");
  };

  // Load experiment template
  const handleLoadTemplate = (templateId: string) => {
    const template = experimentTemplates.find(t => t.id === templateId);
    if (!template) return;

    const newId = String(Date.now());
    const newWorkspace: Workspace = {
      id: newId,
      name: template.name,
      canvasData: null,
      isFavorite: false,
      history: [],
      historyIndex: -1,
    };

    setWorkspaces((prev) => [...prev, newWorkspace]);
    setActiveWorkspaceId(newId);

    // Show instructions
    toast.success(`Modèle "${template.name}" chargé`, {
      description: template.instructions[0]
    });
  };

  // Keyboard shortcuts for undo/redo
  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if ((e.ctrlKey || e.metaKey) && e.key === 'z' && !e.shiftKey) {
        e.preventDefault();
        handleUndo();
      } else if ((e.ctrlKey || e.metaKey) && (e.key === 'y' || (e.key === 'z' && e.shiftKey))) {
        e.preventDefault();
        handleRedo();
      }
    };

    window.addEventListener('keydown', handleKeyDown);
    return () => window.removeEventListener('keydown', handleKeyDown);
  }, [canUndo, canRedo, activeWorkspaceId, workspaces]);

  return (
    <div className="min-h-screen bg-gradient-to-br from-background via-background to-primary/5">
      <div className="container mx-auto p-4 space-y-4">
        {/* Header */}
        <Card className="p-4 bg-card/50 backdrop-blur-sm border-border/50">
          <div className="flex items-center justify-between">
            <div className="flex items-center gap-3">
              <Beaker className="w-8 h-8 text-primary" />
              <div>
                <h1 className="text-2xl font-bold text-foreground">Laboratoire Virtuel</h1>
                <p className="text-sm text-muted-foreground">
                  Simulez des expériences chimiques en toute sécurité
                </p>
              </div>
            </div>
            <Link to="/">
              <Button variant="outline" size="sm">
                <Home className="w-4 h-4 mr-2" />
                Accueil
              </Button>
            </Link>
          </div>
        </Card>

        {/* Safety Warning */}
        {safetyWarning && (
          <Alert variant="destructive" className="animate-fade-in">
            <AlertTriangle className="h-4 w-4" />
            <AlertTitle>Avertissement de sécurité</AlertTitle>
            <AlertDescription>{safetyWarning}</AlertDescription>
          </Alert>
        )}

        {/* Workspace Manager */}
        <WorkspaceManager
          workspaces={workspaces}
          activeWorkspaceId={activeWorkspaceId}
          onWorkspaceChange={handleWorkspaceChange}
          onWorkspaceAdd={handleWorkspaceAdd}
          onWorkspaceDelete={handleWorkspaceDelete}
          onWorkspaceRename={handleWorkspaceRename}
          onWorkspaceFavorite={handleWorkspaceFavorite}
          onUndo={handleUndo}
          onRedo={handleRedo}
          canUndo={canUndo}
          canRedo={canRedo}
          onImport={handleImportWorkspace}
          onExport={handleExportWorkspace}
          onLoadTemplate={handleLoadTemplate}
          templates={experimentTemplates}
        />

        <div className="grid grid-cols-1 lg:grid-cols-4 gap-6">
          {/* Inventory Sidebar */}
          <div className="lg:col-span-1 space-y-4">
            <Inventory
              selectedItem={selectedItem}
              onSelectItem={setSelectedItem}
            />
            <ChemicalCalculator />
          </div>

          {/* Main Lab Area */}
          <div className="lg:col-span-2">
            <Card className="p-6 shadow-elegant">
              <div className="mb-4">
                <h2 className="text-xl font-semibold mb-2">
                  {activeWorkspace?.name}
                </h2>
                <p className="text-sm text-muted-foreground">
                  Ajoutez des substances et déplacez-les librement
                </p>
              </div>
              <FabricLabCanvas
                ref={canvasRef}
                selectedItem={selectedItem}
                onMix={handleMix}
                canvasData={activeWorkspace?.canvasData || null}
                onCanvasChange={handleCanvasChange}
                temperatureC={temperatureC}
                onTemperatureChange={setTemperatureC}
              />
            </Card>
          </div>

          {/* Results Panel */}
          <div className="lg:col-span-1 space-y-4">
            <ResultsPanel results={results} onClear={() => setResults([])} />
            <TimelapseRecorder
              onRequestSnapshot={() => canvasRef.current?.getSnapshot() || null}
              onLoadSnapshot={(data) => canvasRef.current?.loadSnapshot(data)}
            />
          </div>
        </div>
      </div>
    </div>
  );
};

export default Lab;
