﻿import { useEffect, useCallback, useMemo } from "react";
import { useBuilder } from "../contexts/builder/BuilderContext";
import { useCanvasSettings } from "../contexts/CanvasSettingsContext";
import { LoadTemplatePayload, TemplateState, Element as PDFElement } from "../types/elements";
import { debugError, debugWarn, debugLog } from "../utils/debug";
import {
  getPdfBuilderData,
  updatePdfBuilderData,
  type PdfBuilderExistingTemplate,
} from "../utils/editorFeatures";
import {
  serializeCanvasData,
  deserializeCanvasData,
  debugCanvasData,
} from "../utils/CanvasPersistence";
import { ClientNonceManager } from "../utils/ClientNonceManager";
import { configureRealDataElements } from "../utils/RealDataElementsHelper"; // ✅ NEW: Auto-configure RealData elements

export function useTemplate() {
  const { state, dispatch } = useBuilder();
  const canvasSettings = useCanvasSettings();

  const getTemplateSerializationSource = useCallback(
    (templateData: PdfBuilderExistingTemplate): string | object => {
      const templatePayload = templateData.template_data;

      if (
        typeof templatePayload === "string" ||
        (typeof templatePayload === "object" && templatePayload !== null)
      ) {
        return templatePayload;
      }

      return templateData;
    },
    [],
  );

  const getLocalizedTemplateId = useCallback((): string | null => {
    const pdfBuilderData = getPdfBuilderData();
    const localizedTemplateId =
      pdfBuilderData.templateId ??
      pdfBuilderData.existingTemplate?.id ??
      pdfBuilderData.existingTemplate?.template_id ??
      null;

    if (localizedTemplateId === null || localizedTemplateId === undefined) {
      return null;
    }

    const normalizedTemplateId = String(localizedTemplateId).trim();

    return normalizedTemplateId !== "" && normalizedTemplateId !== "0"
      ? normalizedTemplateId
      : null;
  }, []);

  // Détecter si on est sur un template existant via l'URL ou les données localisées
  const getTemplateIdFromUrl = useCallback((): string | null => {
    // Priorité 1: Utiliser le templateId du state template (après sauvegarde)
    if (state.template.id) {
      return state.template.id.toString();
    }

    // Priorité 2: Utiliser le templateId des données PHP localisées
    const localizedTemplateId = getLocalizedTemplateId();
    if (localizedTemplateId) {
      return localizedTemplateId;
    }

    // Priorité 3: Utiliser le paramètre URL (pour compatibilité)
    const urlParams = new URLSearchParams(window.location.search);
    const urlTemplateId = urlParams.get("template") || urlParams.get("template_id");
    if (urlTemplateId) {
      return urlTemplateId;
    }

    return null;
  }, [getLocalizedTemplateId, state.template.id]);

  const isEditingExistingTemplate = (): boolean => {
    return getTemplateIdFromUrl() !== null;
  };

  // Charger un template existant
  const loadExistingTemplate = useCallback(
    async (templateId: string) => {
      try {
        const pdfBuilderData = getPdfBuilderData();

        // ✅ PRIORITÉ: Utiliser les données localisées si disponibles (plus rapide et fiable)
        if (
          pdfBuilderData.existingTemplate &&
          pdfBuilderData.hasExistingData
        ) {
          const templateData = pdfBuilderData.existingTemplate;
          const templateName = templateData?.name?.trim()
            ? templateData.name
            : `[Template ${templateId}]`;

          // ✅ UTILISER LA COUCHE UNIFIÉE DE DÉSÉRIALISATION
          // Mode édition: utiliser les valeurs fictives
          const { elements, canvas } = deserializeCanvasData(
            getTemplateSerializationSource(templateData),
            { mode: "editor" },
          );

          // ✅ Initialiser les propriétés RealData sur les éléments
          const configuredElements = configureRealDataElements(elements);

          debugLog(
            `📂 LOAD - ${configuredElements.length} éléments depuis données localisées`,
          );
          debugCanvasData(
            { elements: configuredElements as PDFElement[], canvasWidth: canvas?.width ?? 0, canvasHeight: canvas?.height ?? 0, version: "1.0" },
            "Données chargées",
          );

          dispatch({
            type: "LOAD_TEMPLATE",
            payload: {
              id: templateId,
              name: templateName,
              elements: configuredElements,
              canvas,
              lastSaved: new Date(),
              showGuides: templateData.showGuides ?? true,
              snapToGrid: templateData.snapToGrid ?? false,
              marginTop: templateData.marginTop ?? 0,
              marginBottom: templateData.marginBottom ?? 0,
              marginLeft: templateData.marginLeft ?? 0,
              marginRight: templateData.marginRight ?? 0,
              description: templateData.description ?? "",
            } as LoadTemplatePayload,
          });

          return true;
        }

        // ✅ FALLBACK: Utiliser AJAX si les données localisées ne sont pas disponibles

        // Détecter le navigateur pour des en-têtes spécifiques
        const isChrome =
          typeof navigator !== "undefined" &&
          /Chrome/.test(navigator.userAgent) &&
          /Google Inc/.test(navigator.vendor);

        const isFirefox =
          typeof navigator !== "undefined" &&
          /Firefox/.test(navigator.userAgent);

        const isSafari =
          typeof navigator !== "undefined" &&
          /Safari/.test(navigator.userAgent) &&
          !/Chrome/.test(navigator.userAgent) &&
          !/Chromium/.test(navigator.userAgent);

        // Préparer les options fetch avec des en-têtes spécifiques par navigateur
        const fetchOptions: RequestInit = {
          method: "GET",
          headers: {
            "Content-Type": "application/json",
            "X-Requested-With": "XMLHttpRequest",
            // En-têtes anti-cache spécifiques
            "Cache-Control": "no-cache, no-store, must-revalidate",
            Pragma: "no-cache",
            Expires: "0",
          },
          // Mode spécifique selon le navigateur
          mode: "cors" as RequestMode,
          credentials: "same-origin" as RequestCredentials,
        };

        // Ajustements spécifiques par navigateur
        if (isChrome) {
          // Chrome peut avoir besoin d'un mode plus permissif
          fetchOptions.mode = "cors";
          fetchOptions.cache = "no-cache";
        } else if (isFirefox) {
          // Firefox gère bien le cache par défaut
          fetchOptions.cache = "no-cache";
        } else if (isSafari) {
          // Safari peut avoir des problèmes avec certains modes
          fetchOptions.mode = "cors";
        }

        const cacheBreaker = Date.now();
        const url = ClientNonceManager.addToUrl(
          `${ClientNonceManager.getAjaxUrl()}?action=pdfib_get_template&template_id=${templateId}&t=${cacheBreaker}`,
        );

        const response = await fetch(url, fetchOptions);

        if (!response.ok) {
          const errorText = await response.text();
          debugError("[useTemplate] Response error text:", errorText);
          throw new Error(
            `Erreur HTTP ${response.status}: ${response.statusText}`,
          );
        }

        const result = await response.json();

        if (!result.success) {
          throw new Error(
            result.data || "Erreur lors du chargement du template",
          );
        }

        // ✅ FIX: ajaxGetTemplate() retourne {template: {...}, template_name: '...', ...}
        // On doit accéder à result.data.template pour obtenir l'objet template réel
        const templateData = result.data?.template || result.data || {};

        // 🔍 Récupérer les éléments du templateData pour parsing
        const ajaxTemplateName = result.data
          ? result.data.template_name || result.data.name
          : result.name || result.template_name;

        // Appliquer la même logique de fallback que pour les données localisées
        const templateName =
          ajaxTemplateName && ajaxTemplateName.trim() !== ""
            ? ajaxTemplateName
            : templateData?.name && templateData.name.trim() !== ""
              ? templateData.name
              : `[NOM NON RÉCUPÉRÉ - ID: ${templateId}]`;

        // 🔍 Tracer les éléments reçus du serveur
        if (templateData.elements) {
        }

        // ✅ UTILISER LA COUCHE UNIFIÉE POUR LE FALLBACK AUSSI
        // Mode édition: utiliser les valeurs fictives
        const { elements, canvas } = deserializeCanvasData(templateData, {
          mode: "editor",
        });

        // ✅ Initialiser les propriétés RealData sur les éléments
        const configuredElements = configureRealDataElements(elements);

        debugLog(
          `📂 LOAD FALLBACK - ${configuredElements.length} éléments depuis AJAX`,
        );
        debugCanvasData(
          { elements: configuredElements as PDFElement[], canvasWidth: canvas?.width ?? 0, canvasHeight: canvas?.height ?? 0, version: "1.0" },
          "Données AJAX",
        );

        dispatch({
          type: "LOAD_TEMPLATE",
          payload: {
            id: templateId,
            name: templateName,
            elements: configuredElements,
            canvas,
            lastSaved: new Date(),
            showGuides: (templateData as any)?.showGuides ?? true,
            snapToGrid: (templateData as any)?.snapToGrid ?? false,
            marginTop: (templateData as any)?.marginTop ?? 0,
            marginBottom: (templateData as any)?.marginBottom ?? 0,
            marginLeft: (templateData as any)?.marginLeft ?? 0,
            marginRight: (templateData as any)?.marginRight ?? 0,
            description: (templateData as any)?.description ?? "",
          } as LoadTemplatePayload,
        });

        return true;
      } catch (error) {
        debugError("❌ [LOAD TEMPLATE] Erreur lors du chargement:", error);

        // Diagnostics spécifiques selon le navigateur
        const isChrome =
          typeof navigator !== "undefined" &&
          /Chrome/.test(navigator.userAgent) &&
          /Google Inc/.test(navigator.vendor);

        const isFirefox =
          typeof navigator !== "undefined" &&
          /Firefox/.test(navigator.userAgent);

        const isSafari =
          typeof navigator !== "undefined" &&
          /Safari/.test(navigator.userAgent) &&
          !/Chrome/.test(navigator.userAgent) &&
          !/Chromium/.test(navigator.userAgent);

        debugError(
          `❌ [LOAD TEMPLATE] Échec du chargement sur ${
            isChrome
              ? "Chrome"
              : isFirefox
                ? "Firefox"
                : isSafari
                  ? "Safari"
                  : "navigateur inconnu"
          }`,
        );
        debugError("❌ [LOAD TEMPLATE] Détails de l'erreur:", {
          message: error instanceof Error ? error.message : "Unknown error",
          stack: error instanceof Error ? error.stack : undefined,
          name: error instanceof Error ? error.name : "Unknown",
          templateId: templateId,
          ajaxUrl: getPdfBuilderData().ajaxUrl,
          userAgent: navigator.userAgent,
        });

        // Tentative de fallback pour Chrome
        if (
          isChrome &&
          error instanceof Error &&
          error.message.includes("fetch")
        ) {
          debugWarn(
            "🔄 [LOAD TEMPLATE] Tentative de fallback pour Chrome - Nouvelle tentative avec options différentes",
          );

          try {
            // Attendre un peu avant retry
            await new Promise((resolve) => setTimeout(resolve, 1000));

            // Retry avec des options différentes
            const fallbackOptions: RequestInit = {
              method: "GET",
              headers: {
                Accept: "application/json, text/plain, */*",
                "X-Requested-With": "XMLHttpRequest",
              },
              mode: "no-cors" as RequestMode,
              cache: "reload",
            };

            const fallbackUrl = ClientNonceManager.addToUrl(
              `${ClientNonceManager.getAjaxUrl()}?action=pdfib_get_template&template_id=${templateId}&fallback=1&t=${Date.now()}`,
            );

            const fallbackResponse = await fetch(fallbackUrl, fallbackOptions);

            if (fallbackResponse.ok || fallbackResponse.status === 0) {
              // no-cors peut retourner status 0
              // Traiter la réponse même si elle est opaque
              return true;
            }
          } catch (fallbackError) {
            debugError("❌ [LOAD TEMPLATE] Échec du fallback:", fallbackError);
          }
        }

        return false;
      }
    },
    [dispatch],
  );

  /**
   * 📊 Charger template en mode APERÇU (preview)
   *
   * Récupère les données réelles WooCommerce pour une commande
   * et charge le template avec ces données injectées
   * (aperçu miroir avec vraies données)
   */
  const loadTemplateForPreview = useCallback(
    async (templateId: string, orderId: string | number) => {
      try {
        // 1️⃣ D'abord, récupérer les données réelles de la commande
        debugLog(
          `📊 [PREVIEW] Récupération des données pour commande ID ${orderId}`,
        );

        const orderDataUrl = ClientNonceManager.addToUrl(
          `${ClientNonceManager.getAjaxUrl()}?action=pdfib_get_order_data_for_preview&orderId=${orderId}`,
        );

        const orderDataResponse = await fetch(orderDataUrl, {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            "X-Requested-With": "XMLHttpRequest",
          },
          body: JSON.stringify({
            nonce: ClientNonceManager.getCurrentNonce() || "",
          }),
        });

        if (!orderDataResponse.ok) {
          throw new Error(
            `Erreur HTTP ${orderDataResponse.status}: Impossible de récupérer les données de la commande`,
          );
        }

        const orderDataResult = await orderDataResponse.json();
        if (!orderDataResult.success) {
          throw new Error(
            orderDataResult.data?.message ||
              "Erreur lors de la récupération des données",
          );
        }

        const realOrderData = orderDataResult.data;
        debugLog(
          `✅ [PREVIEW] ${Object.keys(realOrderData).length} propriétés récupérées pour la commande`,
        );
        debugLog("[PREVIEW] Données:", realOrderData);

        // 2️⃣ Charger le template avec les données réelles en mode preview
        const templateLoaded = await loadExistingTemplate(templateId);
        if (!templateLoaded) {
          throw new Error("Impossible de charger le template");
        }

        // 3️⃣ Récupérer les éléments du state et les déserialiser en mode preview
        // (C'est fait dans BuilderContext après SET_ELEMENTS)
        const templateData = getPdfBuilderData().existingTemplate;
        if (!templateData) {
          throw new Error("Données du template manquantes");
        }

        // 4️⃣ Réinjecter avec les données réelles
        const { elements, canvas } = deserializeCanvasData(
          getTemplateSerializationSource(templateData),
          {
            mode: "preview",
            realOrderData: realOrderData,
          },
        );

        // 🔧 Initialiser les propriétés RealData (même si déjà en mode preview)
        const configuredElements = configureRealDataElements(elements);

        debugLog(
          `📊 [PREVIEW] ${configuredElements.length} éléments chargés avec données réelles`,
        );
        debugCanvasData(
          { elements: configuredElements as PDFElement[], canvasWidth: canvas?.width ?? 0, canvasHeight: canvas?.height ?? 0, version: "1.0" },
          "📊 Aperçu avec données réelles",
        );

        // 5️⃣ Dispatcher pour mettre à jour le canvas avec les éléments du preview
        dispatch({
          type: "SET_ELEMENTS",
          payload: configuredElements,
        });

        // 6️⃣ Mettre à jour le state de preview
        dispatch({
          type: "SET_PREVIEW_MODE",
          payload: "command",
        });

        dispatch({
          type: "SET_ORDER_ID",
          payload: String(orderId),
        });

        return true;
      } catch (error) {
        debugError(
          "❌ [PREVIEW] Erreur lors du chargement de l'aperçu:",
          error,
        );
        return false;
      }
    },
    [dispatch, loadExistingTemplate],
  );

  // 🎯 DISABLED: Event-based template loading causes race conditions with useEffect
  // Both methods try to load the same template, causing flashing/alternating canvas
  // The useEffect approach (reading URL) is more reliable and runs once per page load
  useEffect(() => {
    // ✅ Event listener disabled to prevent race conditions
    // Only useEffect with URL reading will load templates now
    return () => {
      // cleanup
    };
  }, []);

  // Effet pour charger automatiquement un template existant au montage
  // ✅ Dépendance vide: charger une seule fois au montage du composant
  useEffect(() => {
    const templateId = getTemplateIdFromUrl();

    // Détecter le mode preview depuis l'URL
    const urlParams = new URLSearchParams(window.location.search);
    const isPreviewMode = urlParams.get("preview") === "1";
    const orderId = urlParams.get("order_id");

    if (templateId) {
      // Timeout de sécurité : forcer isLoading à false après 10 secondes si le chargement échoue
      const loadingTimeout = setTimeout(() => {
        debugError(
          "[useTemplate] Loading timeout reached, forcing isLoading to false",
        );
        dispatch({ type: "SET_TEMPLATE_LOADING", payload: false });
      }, 10000);

      // Si mode preview avec order_id, charger l'aperçu avec données réelles
      if (isPreviewMode && orderId) {
        debugLog(
          `🔍 [PREVIEW] Détection du mode preview pour commande #${orderId}`,
        );
        loadTemplateForPreview(templateId, orderId)
          .then(() => {
            clearTimeout(loadingTimeout);
            debugLog("✅ [PREVIEW] Aperçu chargé avec succès");
          })
          .catch((error) => {
            clearTimeout(loadingTimeout);
            debugError("[useTemplate] Preview loading failed:", error);
            dispatch({ type: "SET_TEMPLATE_LOADING", payload: false });
          });
      } else {
        // Charger le template en mode édition normale
        loadExistingTemplate(templateId)
          .then(() => {
            clearTimeout(loadingTimeout);
          })
          .catch((error) => {
            clearTimeout(loadingTimeout);
            debugError("[useTemplate] Template loading failed:", error);
            // Force isLoading to false on error
            dispatch({ type: "SET_TEMPLATE_LOADING", payload: false });
          });
      }
    } else {
      // Si pas de template ID, forcer isLoading à false pour nouveau template
      dispatch({ type: "NEW_TEMPLATE" });
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // Sauvegarder un template manuellement
  const saveTemplate = useCallback(async () => {
    dispatch({ type: "SET_TEMPLATE_SAVING", payload: true });

    try {
      const templateId = state.template.id?.toString() || getTemplateIdFromUrl();

      // Générer un nom par défaut s'il est vide
      let templateName = (state.template.name || "").trim();
      if (!templateName) {
        const now = new Date();
        templateName = `Nouveau template - ${now.toLocaleDateString('fr-FR')} ${now.toLocaleTimeString('fr-FR')}`;
      }

      // Sérialiser les données du canvas
      const jsonData = serializeCanvasData(state.elements, {
        width: state.template.canvasWidth || canvasSettings.canvasWidth,
        height: state.template.canvasHeight || canvasSettings.canvasHeight,
      });
      debugLog(
        `💾 SAVE - ${state.elements.length} éléments, ID: ${templateId}`,
      );

      // Préparer la requête
      const formData = new FormData();
      formData.append("action", "pdfib_save_template");
      if (templateId) {
        formData.append("template_id", templateId);
      }
      formData.append("template_name", templateName);
      formData.append("template_description", state.template.description || "");

      formData.append("template_data", jsonData);
      formData.append("margin_top", String(state.template.marginTop ?? 0));
      formData.append(
        "margin_bottom",
        String(state.template.marginBottom ?? 0),
      );
      formData.append("margin_left", String(state.template.marginLeft ?? 0));
      formData.append("margin_right", String(state.template.marginRight ?? 0));
      ClientNonceManager.addToFormData(formData);

      const response = await fetch(ClientNonceManager.getAjaxUrl(), {
        method: "POST",
        body: formData,
      });

      if (!response.ok) {
        throw new Error(`Erreur HTTP: ${response.status}`);
      }

      const result = await response.json();

      if (!result.success) {
        debugError("[SAVE] Save failed:", result.data);
        if (result.data?.code === "nonce_invalid") {
          try {
            let freshNonce = result.data?.nonce;

            if (!freshNonce) {
              freshNonce = await ClientNonceManager.refreshNonce(
                ClientNonceManager.getCurrentNonce() || undefined,
              );
            } else {
              ClientNonceManager.setNonce(freshNonce);
            }

            if (freshNonce) {
              return await saveTemplate();
            }
          } catch (nonceError) {
            // error
          }
        }

        throw new Error(
          result.data || "Erreur lors de la sauvegarde du template",
        );
      }

      dispatch({
        type: "SAVE_TEMPLATE",
        payload: {
          id: result.data.template_id || result.data.id,
          name: result.data.name || templateName,
        },
      });

      const savedTemplateId = String(result.data.template_id || result.data.id || "").trim();

      if (savedTemplateId) {
        const currentUrl = new URL(window.location.href);
        currentUrl.searchParams.set("template_id", savedTemplateId);
        currentUrl.searchParams.delete("template");
        window.history.replaceState({}, "", currentUrl.toString());

        updatePdfBuilderData((pdfBuilderData) => {
          pdfBuilderData.templateId = savedTemplateId;
        });
      }

      // Update the shared editor payload to reflect the latest saved data
      // This prevents issues if the component re-mounts and loads old data
      updatePdfBuilderData((pdfBuilderData) => {
      if (!pdfBuilderData.existingTemplate) {
        pdfBuilderData.existingTemplate = {};
      }

      pdfBuilderData.existingTemplate.id =
        result.data.template_id || result.data.id || state.template.id;
      pdfBuilderData.existingTemplate.template_id =
        result.data.template_id || result.data.id || state.template.id;
      pdfBuilderData.existingTemplate.template_data = jsonData;
      pdfBuilderData.existingTemplate.name = state.template.name;
      pdfBuilderData.existingTemplate.description =
        state.template.description || "";
      });

      return true;
    } catch (error) {
      debugError("[useTemplate] SAVE - Critical error:", error);
      dispatch({ type: "SET_TEMPLATE_SAVING", payload: false });
      throw error;
    } finally {
      dispatch({ type: "SET_TEMPLATE_SAVING", payload: false });
    }
  }, [
    canvasSettings.canvasHeight,
    canvasSettings.canvasWidth,
    dispatch,
    state.elements,
    state.template.canvasWidth,
    state.template.canvasHeight,
    state.template.id,
    state.template.name,
    state.template.description,
    getTemplateIdFromUrl,
  ]);

  const previewTemplate = useCallback(() => {
    dispatch({ type: "SET_SHOW_PREVIEW_MODAL", payload: true });
  }, [dispatch]);

  // ✅ NEW: Exposer loadTemplateForPreview au niveau global pour que le header puisse l'appeler
  useEffect(() => {
    if (typeof window !== "undefined") {
      (window as any).pdfBuilderLoadTemplateForPreview = loadTemplateForPreview;
    }
  }, [loadTemplateForPreview]);

  const newTemplate = useCallback(() => {
    dispatch({ type: "NEW_TEMPLATE" });
  }, [dispatch]);

  const setTemplateModified = useCallback(
    (modified: boolean) => {
      dispatch({ type: "SET_TEMPLATE_MODIFIED", payload: modified });
    },
    [dispatch],
  );

  const updateTemplateSettings = useCallback(
    (settings: Partial<TemplateState>) => {
      dispatch({ type: "UPDATE_TEMPLATE_SETTINGS", payload: settings });
    },
    [dispatch],
  );

  return useMemo(
    () => ({
      templateName: state.template.name,
      templateDescription: state.template.description,
      templateTags: state.template.tags,
      canvasWidth: state.template.canvasWidth || canvasSettings.canvasWidth,
      canvasHeight: state.template.canvasHeight || canvasSettings.canvasHeight,
      marginTop: state.template.marginTop || canvasSettings.marginTop,
      marginBottom: state.template.marginBottom || canvasSettings.marginBottom,
      marginLeft: state.template.marginLeft ?? canvasSettings.marginLeft,
      marginRight: state.template.marginRight ?? canvasSettings.marginRight,
      showGuides: state.template.showGuides,
      snapToGrid: state.template.snapToGrid,
      isNewTemplate: state.template.isNew,
      isModified: state.template.isModified,
      isSaving: state.template.isSaving,
      isLoading: state.template.isLoading, // ✅ NEW: Template is loading
      lastSaved: state.template.lastSaved,
      isEditingExistingTemplate: isEditingExistingTemplate(),
      saveTemplate,
      previewTemplate,
      newTemplate,
      setTemplateModified,
      updateTemplateSettings,
      loadTemplateForPreview, // ✅ NEW: Charger template avec données réelles
    }),
    [
      state.template.id,
      state.template.name,
      state.template.description,
      state.template.tags,
      state.template.canvasWidth,
      state.template.canvasHeight,
      state.template.marginTop,
      state.template.marginBottom,
      state.template.showGuides,
      state.template.snapToGrid,
      state.template.isNew,
      state.template.isModified,
      state.template.isSaving,
      state.template.isLoading,
      state.template.lastSaved,
      canvasSettings, // ✅ AJOUT: Inclure tous les paramètres du canvas
      saveTemplate,
      previewTemplate,
      newTemplate,
      setTemplateModified,
      updateTemplateSettings,
      loadTemplateForPreview, // ✅ NEW: Ajouter aux dépendances
      getTemplateIdFromUrl,
    ],
  );
}
