"use client";

import { useState, useEffect, useRef } from "react";
import dynamic from "next/dynamic";
import { getFormsAction } from "@/src/lib/actions/formsAction";
import { useLanguage } from "@/src/lib/context/LanguageContext";
import type { Form } from "@/src/lib/services/formsService";
import type { GeneralSettings, TenantData } from "@/src/lib/types/header";

const FooterFormComponent = dynamic(
  () => import("./form/Footer-Form"),
  {
    ssr: false,
  }
);

interface FormLazyWrapperProps {
  page?: string;
  generalSettings?: GeneralSettings;
  tenant?: TenantData;
  isDetailsPage?: boolean;
  cwProgramId?: string | number | null;
  /**
   * Fetch the form on mount instead of waiting for the IntersectionObserver.
   *
   * Deliberately separate from `isDetailsPage`: that flag is not a loading
   * switch, it rewires the form itself (skips the class/location steps,
   * autofills from ClassDetailsContext, changes the step count) and is meant
   * for the class-registration page. Reusing it just to load eagerly would
   * silently change the form's behaviour.
   *
   * Needed because the observer watches a wrapper that is empty until the
   * ssr:false chunk arrives, so it is a zero-height target sitting far below
   * the fold. On a reload — where the browser also restores scroll and the
   * page height shifts underneath it — that intersection can be missed, and
   * the fetch then never fires: no spinner, no form, just a gap.
   */
  eager?: boolean;
}

export default function FormLazyWrapper({ page, generalSettings, tenant, isDetailsPage = false, cwProgramId, eager = false }: FormLazyWrapperProps) {
  const ref = useRef<HTMLDivElement>(null);
  const observerRef = useRef<IntersectionObserver | null>(null);
  const [formData, setFormData] = useState<Form | null>(null);
  const [isLoading, setIsLoading] = useState(false);
  const [hasLoaded, setHasLoaded] = useState(false);
  const { currentLanguage } = useLanguage();
  const prevLanguageRef = useRef<string>(currentLanguage);

  const fetchFormWithFallback = async (franchiseeId: string | null | undefined, languageCode: string | null, pageSlug: string = "home") => {
    try {
      const response = await getFormsAction(franchiseeId, languageCode, pageSlug);
      // Check if we received a valid form with steps
      if (response.success && response.data && response.data.fields && response.data.fields.steps && response.data.fields.steps.length > 0) {
        return response.data;
      }
      
      // If we requested a translated version and it wasn't valid, fallback to English (null languageCode)
      if (languageCode !== null) {
        const fallbackResponse = await getFormsAction(franchiseeId, null, pageSlug);
        if (fallbackResponse.success && fallbackResponse.data) {
          return fallbackResponse.data;
        }
      }
      
      // Return whatever we originally got (might be empty/invalid, but that's what the server has)
      return response.data || null;
    } catch (error) {
      console.error("[FormLazyWrapper] Error fetching form:", error);
      return null;
    }
  };

  // Handle language changes - refetch form with new language
  useEffect(() => {
    if (prevLanguageRef.current !== currentLanguage && hasLoaded) {
      prevLanguageRef.current = currentLanguage;
      setIsLoading(true);

      const params = new URLSearchParams(window.location.search);
      const franchiseeId = params.get("franchiseeId") || tenant?.franchiseeId;

      const languageCode = (function() {
        if (currentLanguage === "default") return null;
        if (currentLanguage === "translated") return generalSettings?.language_code || null;
        // If it's a specific code like 'de', use it directly
        return currentLanguage;
      })();

      fetchFormWithFallback(franchiseeId, languageCode, page || "home")
        .then((data) => {
          setFormData(data);
        })
        .finally(() => {
          setIsLoading(false);
        });
    }
  }, [currentLanguage, generalSettings?.language_code, hasLoaded, tenant?.franchiseeId]);

  // Initial load - lazy loading with intersection observer (only once)
  useEffect(() => {
    // If already loaded, don't set up observer again
    if (hasLoaded || isLoading) return;

    // Load immediately instead of waiting for intersection.
    if (isDetailsPage || eager) {
      setIsLoading(true);

      const params = new URLSearchParams(window.location.search);
      const franchiseeId = params.get("franchiseeId") || tenant?.franchiseeId;

      const languageCode = (function() {
        if (currentLanguage === "default") return null;
        if (currentLanguage === "translated") return generalSettings?.language_code || null;
        return currentLanguage;
      })();

      fetchFormWithFallback(franchiseeId, languageCode, page || "home")
        .then((data) => {
          setFormData(data);
          setHasLoaded(true);
          prevLanguageRef.current = currentLanguage;
        })
        .finally(() => {
          setIsLoading(false);
        });
      
      return;
    }

    const observer = new IntersectionObserver(
      (entries) => {
        if (entries[0].isIntersecting && !hasLoaded) {
          setIsLoading(true);

          // Extract franchiseeId from URL or fallback to tenant
          const params = new URLSearchParams(window.location.search);
          const franchiseeId = params.get("franchiseeId") || tenant?.franchiseeId;

          // Get language code from currentLanguage or fallback
          const languageCode = (function() {
            if (currentLanguage === "default") return null;
            if (currentLanguage === "translated") return generalSettings?.language_code || null;
            return currentLanguage;
          })();

          fetchFormWithFallback(franchiseeId, languageCode, page || "home")
            .then((data) => {
              setFormData(data);
              setHasLoaded(true);
              prevLanguageRef.current = currentLanguage;
            })
            .finally(() => {
              setIsLoading(false);
            });

          // Unobserve after fetching to prevent multiple fetches
          if (ref.current) {
            observer.unobserve(ref.current);
          }
        }
      },
      { rootMargin: "200px" }
    );

    if (ref.current) {
      observer.observe(ref.current);
      observerRef.current = observer;
    }

    return () => {
      if (ref.current && observerRef.current) {
        observerRef.current.unobserve(ref.current);
      }
    };
  }, [hasLoaded, isLoading, currentLanguage, generalSettings?.language_code, isDetailsPage, eager]);

  return (
    <div ref={ref} id="registration-form">
      <FooterFormComponent page={page} form={formData} isLoading={isLoading} tenant={tenant} isDetailsPage={isDetailsPage} cwProgramId={cwProgramId} />
    </div>
  );
}
