// Import necessary components and hooks from WordPress packages.
const { useEffect, useRef } = wp.element;
const { Button } = wp.components;
const { RichText, MediaUpload, MediaUploadCheck } = wp.blockEditor;
const { __ } = wp.i18n;

import { animate, inView } from "motion";
import planeIcon from './../../assets/plane.svg';
import AOS from 'aos';
import 'aos/dist/aos.css';

import {
  getResponsivePaddingStyle,
  getResponsiveMarginStyle,
  getResponsiveFontSize,
  getResponsiveLineHeight,
  getTextShadowStyle
} from './../../utils/styleHelpers';

/**
 * JourneyEntry Component.
 *
 * Represents a single entry within a timeline block for the Our Journey section.
 * Supports responsive styles, editable text fields, image upload, and dynamic removal.
 *
 * @param {Object} props
 * @param {Object} props.attributes - Block attributes.
 * @param {Object} props.entries - Current timeline entry data (heading, year, title, description, image).
 * @param {number} props.index - Entry index in the timeline array
 * @param {string} props.activeDevice - Current selected device view (desktop/tablet/mobile)
 * @param {Function} props.updateEntry - Function to update this specific entry's data
 * @param {Function} props.removeEntry - Function to remove this entry.
 */

const LayoutOne = ({
  activeDevice,
  updateEntry,
  attributes,
  entries,
  index,
  removeEntry,
  setAttributes
}) => {

  // Destructure relevant styling and visibility settings from block attributes.
  const {
    showHeading,
    showYear,
    showImage,
    showTitle,
    showDescription,

    sectionItemContentBgColor,
    sectionItemYearBgColor,

    headingFontSize,
    headingFontSizeUnit,
    headingLineHeight,
    headingLineHeightUnit,
    headingFontFamily,
    headingFontWeight,
    headingFontColor,
    headingBgColor,

    yearTag = 'p',
    yearFontSize,
    yearFontSizeUnit,
    yearLineHeight,
    yearLineHeightUnit,
    yearFontFamily,
    yearFontWeight,
    yearFontColor,

    titleTag = 'h4',
    titleFontSize,
    titleFontSizeUnit,
    titleLineHeight,
    titleLineHeightUnit,
    titleFontFamily,
    titleFontWeight,
    titleFontColor,

    descriptionFontSize,
    descriptionFontSizeUnit,
    descriptionLineHeight,
    descriptionLineHeightUnit,
    descriptionFontFamily,
    descriptionFontWeight,
    descriptionFontColor,

    imageSize
  } = attributes;

  // Get responsive image dimensions.
  const widthValue = ( imageSize?.[activeDevice]?.width ) || 'auto';
  const heightValue = ( imageSize?.[activeDevice]?.height ) || 'auto';
  const imgStyle = {
    ...( 'auto' !== widthValue && { width: widthValue }),
    ...( 'auto' !== heightValue && { height: heightValue }),
    ...( 'auto' === widthValue && 'auto' === heightValue && {

      // Default fallback style if both are auto.
      maxWidth: '100%',
      height: 'auto',
      display: 'block'
    })
  };

  const uniqueWrapperIdRef = useRef( `creativeWrapper-${Math.random().toString( 36 ).substr( 2, 9 )}` );
  const uniqueJourneyTitleIdRef = useRef( `journeyTitle-${Math.random().toString( 36 ).substr( 2, 9 )}` );
  const uniqueUnderlineIdRef = useRef( `creativeUnderline-${Math.random().toString( 36 ).substr( 2, 9 )}` );
  const uniqueUnderlinePathIdRef = useRef( `creativeUnderlinePath-${Math.random().toString( 36 ).substr( 2, 9 )}` );

  const uniquePlaneIdRef = useRef( `plane-${Math.random().toString( 36 ).substr( 2, 9 )}` );
  const uniquePathIdRef = useRef( `path-${Math.random().toString( 36 ).substr( 2, 9 )}` );

  const timelineRef = useRef([]);
  const planeRef = useRef( null );
  const pathRef = useRef( null );
  const comp = useRef();

  useEffect( () => {
    let ctx;

    const initAnimations = () => {
      const plane = document.getElementById(uniquePlaneIdRef.current);
            const pathSvg = document.getElementById(uniquePathIdRef.current);
            const path = pathSvg ? pathSvg.querySelector("path") : null;

            if (plane && path) {
                const pathLength = path.getTotalLength();
                let lastScrollY = 0;

                const bindScroll = (scrollContainer, label) => {

                    const handleScroll = () => {
                        const rect = comp.current?.getBoundingClientRect?.();
                        if (!rect) {
                            console.warn("No rect found for comp");
                            return;
                        }

                        const windowHeight = scrollContainer === window
                            ? window.innerHeight
                            : scrollContainer.clientHeight;

                        const isVisible = rect.top < windowHeight && rect.bottom > 0;

                        if (!isVisible) return;

                        const visibleTop = Math.max(0, -rect.top);
                        const visibleHeight = Math.min(rect.height, windowHeight);
                        const scrollRange = rect.height - visibleHeight;
                        
                        let progress = scrollRange > 0 ? visibleTop / scrollRange : 0;
                        progress = Math.min(Math.max(progress, 0), 1);

                        const slowProgress = progress * 0.95;
                        const point = path.getPointAtLength(slowProgress * pathLength);

                        const ctm = path.getCTM();
                        const svgPoint = path.ownerSVGElement.createSVGPoint();
                        svgPoint.x = point.x - 3.5;
                        svgPoint.y = point.y;
                        const screenPoint = svgPoint.matrixTransform(ctm);

                        //Detect scroll direction
                        const currentScrollY = scrollContainer === window 
                            ? window.scrollY 
                            : scrollContainer.scrollTop;
                        let rotateDeg = 0;

                        if (currentScrollY > lastScrollY) {
                            // scrolling down
                            rotateDeg = 0;  // plane faces right/down
                        } else if (currentScrollY < lastScrollY) {
                            // scrolling up
                            rotateDeg = 180; // plane faces left/up
                        }

                        lastScrollY = currentScrollY;

                        //Apply both translate & rotate
                        plane.style.transform = `translate(${screenPoint.x}px, ${screenPoint.y}px) rotate(${rotateDeg}deg)`;
                    };
                    scrollContainer.addEventListener("scroll", handleScroll);
                };

                //Detect if we are in Gutenberg backend
                if (document.body.classList.contains("wp-admin")) {
                    // The actual scrolling wrapper in Gutenberg
                    const editorScrollContainer =
                        document.querySelector(".interface-interface-skeleton__content") ||
                        document.querySelector(".block-editor-writing-flow");

                    if (editorScrollContainer) {
                        bindScroll(editorScrollContainer, "Editor Scroll Container");
                    } else {
                        console.warn("Editor scroll container not found");
                    }
                } else {
                    bindScroll(window, "Window");
                }
            }

      const journeyTitleEl = document.querySelector(".ojb-section-heading");
                  
      if (journeyTitleEl) {
        // Animate heading, then underline sequentially
        inView(".ojb-section-heading", async (el) => {
          // Step 1: Heading text reveal
          
          await animate(
            el,
            {
              clipPath: ["inset(0% 100% 0% 0%)", "inset(0% 0% 0% 0%)"],
              opacity: [0, 1],
            },
            {
              duration: 1.5,
              easing: "ease-in-out",
            }
          ).finished;

          // Step 2: Find underline path (sibling or by dynamic ID)
          const pathEl = el.parentElement.querySelector("[id^='creativeUnderlinePath-']");
          if (pathEl) {
            const pathLength = pathEl.getTotalLength();
            // hide underline initially
            pathEl.style.strokeDasharray = pathLength;
            pathEl.style.strokeDashoffset = pathLength;

            const underlineAnim = pathEl.animate(
              [
                { strokeDashoffset: pathLength }, // hidden
                { strokeDashoffset: 0 }           // visible
              ],
              {
                duration: 1500,
                easing: "ease-in-out",
                fill: "forwards",  //keep final frame
              }
            );
            await underlineAnim.finished;
            pathEl.style.strokeDashoffset = 0;
          }
        });
      }
    };

    initAnimations(); // Run on mount
    
    const updateCircleSize = () => {

      const wrapper = document.getElementById( uniqueWrapperIdRef.current );
      const title = document.getElementById( uniqueJourneyTitleIdRef.current );
      const svg = document.getElementById( uniqueUnderlineIdRef.current );

      if ( ! wrapper || ! title ) {
        return;
      }

      // Get size of the h2 content.
      const titleRect = title.getBoundingClientRect();
      const style = getComputedStyle( title );
      const fontSize = parseFloat( style.fontSize );
      const padding = 30; // estimated total padding (left + right or top + bottom).

      // Calculate the desired diameter.
      const contentWidth = titleRect.width + padding;
      const contentHeight = titleRect.height + padding;

      // Set SVG width equal to the h2 width.
      svg.style.width = '50%';

      // Set SVG height proportional to font size (e.g., 30%).
      svg.style.height = `${fontSize * 0.6}px`;

      const diameter = Math.max( contentWidth, contentHeight, 100 ); // enforce min 100px.

      // Apply size to the wrapper.
      wrapper.style.width = `${diameter}px`;
      wrapper.style.height = `${diameter}px`;
    };
    updateCircleSize();
    let animationCircleSize;
    requestAnimationFrame( () => {
      animationCircleSize = requestAnimationFrame( updateCircleSize );
    });
    AOS.init({ duration: 1000, once: false });

    let animationFrameId;

    const refreshLoop = () => {
      AOS.refreshHard(); // Ensures recalculation.
      animationFrameId = requestAnimationFrame( refreshLoop );
    };

    refreshLoop(); // Start the loop.

    const handleResize = () => {
      initAnimations(); // Re-run animations on resize.
      updateCircleSize();
    };

    window.addEventListener( 'resize', handleResize );

    return () => {
      window.removeEventListener( 'resize', handleResize );
      cancelAnimationFrame( animationFrameId );
      cancelAnimationFrame( animationCircleSize );
      if ( ctx ) {
        ctx.revert();
      } // Clean up on unmount.
    };
  }, [ attributes, activeDevice ]);

  return (
    <div
      ref={comp}
      className={`journey-continer px-4 py-6 md:px-8 lg:px-5 max-md:pb-14 overflow-hidden ${attributes.layout}`}
    >
      {showHeading && (
        <div className="w-full text-center mb-7 md:mb-9">
          <div
            key={index + 'wrapper'}
            id={uniqueWrapperIdRef.current}
            className="creative-title-wrapper inline-flex items-center flex-wrap content-center justify-center rounded-full bg-blue-200 p-2 md:p-4 px-8 md:px-12 border-2 border-dashed border-white min-w-[150px] min-h-[150px] shadow-2xl"
            style={{
              backgroundColor: headingBgColor || undefined
            }}
          >
            <div className="flex flex-col items-center justify-center">
              <RichText
                tagName="h2"
                key={index + 'journeyTitle'}
                id={uniqueJourneyTitleIdRef.current}
                placeholder="Our Journey"
                value={attributes.heading}
                onChange={( value ) => setAttributes({ heading: value })}
                className="text-xl !mt-0 !mb-0 sm:text-2xl md:text-3xl lg:text-4xl text-blue-800 font-medium text-center uppercase break-word ojb-section-heading no-border-input"
                style={{
                  ...getResponsiveFontSize( headingFontSize, headingFontSizeUnit || 'px', activeDevice ),
                  ...getResponsiveLineHeight( headingLineHeight, headingLineHeightUnit || 'px', activeDevice ),
                  fontFamily: headingFontFamily || undefined,
                  fontWeight: headingFontWeight || undefined,
                  color: headingFontColor || undefined
                }}
              />
              <svg
                key={index + 'underline'}
                id={uniqueUnderlineIdRef.current}
                className="w-[80px] h-[20px] md:w-[100px] md:h-[25px]"
                viewBox="0 0 200 10"
                preserveAspectRatio="none"
                fill="none"
                xmlns="http://www.w3.org/2000/svg"
              >
                <path
                  key={index + 'underlinePath'}
                  id={uniqueUnderlinePathIdRef.current}
                  d="M0 5 L200 5"  // straight horizontal line.
                  stroke={headingFontColor || 'oklch(42.4% 0.199 265.638)'}
                  strokeWidth="2"
                  strokeLinecap="round"
                  fill="none"
                />
              </svg>
            </div>
          </div>
        </div>
      )}
      {Array.isArray( entries ) && 0 < entries.length ? (
        <div className={'relative journey-main'} style={{ position: 'relative'}} >
          {/* Curved Timeline Line (for the plane's motion path). */}
          {/* The viewBox is 0 0 100 100, meaning 50 0 is the top center, 50 100 is bottom center. */}
          <svg
            id={uniquePathIdRef.current}
            className="absolute top-0 left-0 w-full h-full pointer-events-none z-0 motion-path"
            viewBox="0 0 100 100"
            preserveAspectRatio="none"
            ref={pathRef}
          >
            <path
              d="M 50 0 L 50 100"  // Straight vertical line.
              stroke="#193cb8"
              vectorEffect="non-scaling-stroke"
              fill="none"
              strokeWidth={3}
              strokeLinecap="round"
            />
          </svg>
          {/* Plane Icon. */}
          <img
            id={uniquePlaneIdRef.current}
            ref={planeRef}
            src={planeIcon}
            alt="Plane"

            // Tailwind classes for positioning and size. z-5 keeps it above the path.
            // bg-white is added to ensure it covers the path if it moves over it, common for icons.
            className="absolute w-12 h-12 md:w-16 md:h-16 lg:w-20 lg:h-20 z-1 plane-img"
          />
          {/* Timeline Items Loop. */}
          {/* This section defines the layout for your milestone content. */}
          <div className="relative flex flex-col gap-16 pb-20">
            {entries.map( ( entry, index ) => (
            <div
              key={index}
              ref={( el ) => ( timelineRef.current[index] = el )}
              className="relative flex flex-wrap justify-center"
            >
              <div className={`w-full max-w-[300px] md:max-w-[1200px] flex flex-col items-center md:flex-row ${0 === index % 2 ? 'md:justify-end' : 'md:justify-start'} `}>
                {/* Milestone Text Content. */}
                <div
                  className={`w-full md:w-2/3 mt-7 py-3 p-5 md:p-5 lg:p-6 rounded-2xl mb-8 md:mb-0 text-center relative z-1 flex items-center max-md:flex-wrap ${0 === index % 2 ? 'md:order-1 md:ml-0 md:text-left' : 'md:order-3 md:mr-0 md:text-right'}`}
                >
                  <div
                    data-aos={0 === index % 2 ? 'fade-right' : 'fade-left'}
                    className={`bg-blue-800 max-md:w-[60%] m-auto md:w-[100%] py-4 md:py-22 px-5 max-md:pb-8 md:px-7 md:h-[80%] md:absolute -z-10 flex items-center rounded-t-full md:rounded-[100px] justify-center ${0 === index % 2 ? 'md:order-1 md:rounded-l-[100px] md:left-[-30%] md:justify-start' : 'md:order-2 md:rounded-r-[100px] md:right-[-30%] lg:right-[-10%] md:justify-end'}`}
                    style={{
                      backgroundColor: sectionItemYearBgColor || undefined
                    }}
                  >
                    {showYear && (
                      <RichText
                        tagName={yearTag}
                        placeholder="Enter Year..."
                        value={entry.year}
                        onChange={( value ) => updateEntry( index, 'year', value )}
                        className="block text-3xl !mt:0 !mb:0 md:text-5xl lg:text-6xl text-blue-200 font-semibold tracking-[2px] break-word ojb-year no-border-input"
                        style={{
                          ...getResponsiveFontSize( yearFontSize, yearFontSizeUnit || 'px', activeDevice ),
                          ...getResponsiveLineHeight( yearLineHeight, yearLineHeightUnit || 'px', activeDevice ),
                          ...getTextShadowStyle( attributes.yearTextShadow, activeDevice ),
                          fontFamily: yearFontFamily || undefined,
                          fontWeight: yearFontWeight || undefined,
                          color: yearFontColor || undefined
                        }}
                      />
                    )}
                  </div>
                  <div
                    data-aos={0 === index % 2 ? 'fade-left' : 'fade-right'}
                    className={`bg-white w-[100%] lg:w-[80%] md:h-full rounded-2xl md:rounded-[100px] p-5 md:p-10 shadow-2xl max-md:mt-[-20px] ${0 === index % 2 ? 'md:order-2' : 'md:order-1'}`}
                    style={{
                      backgroundColor: sectionItemContentBgColor || undefined
                    }}
                  >
                    <div
                      className={`w-full flex justify-center md:inline-block ${0 === index % 2 ? 'md:order-3' : 'md:order-1'}`}
                    >
                        {showImage && (
                          <MediaUploadCheck>
                            <MediaUpload
                              onSelect={( media ) => updateEntry( index, 'imageUrl', media.url )}
                              allowedTypes={[ 'image' ]}
                              value={entry.imageUrl}
                              render={({ open }) => (
                                <div className="image-upload-wrapper">
                                  {entry.imageUrl ? (
                                    <div className="image-preview">
                                      <img
                                        className = {`w-[50px] h-auto rounded-lg my-5 ${0 === index % 2 ? 'md:me-auto' : 'md:ms-auto'} md:w-[80px]`}
                                        src={entry.imageUrl}
                                        alt={entry.title}
                                        style={{
                                          ...imgStyle,
                                          marginBottom: '10px'
                                        }}
                                      />
                                      <div>
                                        <Button onClick={open} isSecondary style={{ marginRight: '10px' }}>
                                          {__( 'Change Image', 'journey-timeline-block' )}
                                        </Button>
                                        <Button
                                          onClick={() => updateEntry( index, 'imageUrl', '' )}
                                          variant="tertiary"
                                          isDestructive
                                        >
                                          {__( 'Remove Image', 'journey-timeline-block' )}
                                        </Button>
                                      </div>
                                    </div>
                                  ) : (
                                    <Button onClick={open} isSecondary>
                                      {__( 'Upload Image', 'journey-timeline-block' )}
                                    </Button>
                                  )}
                                </div>
                              )}
                            />
                          </MediaUploadCheck>
                        )}
                    </div>
                    {showTitle && (
                      <>
                        <RichText
                          tagName={titleTag}
                          placeholder="Enter Title..."
                          value={entry.title}
                          onChange={( value ) => updateEntry( index, 'title', value )}
                          className="block text-xl md:text-2xl lg:text-4xl text-purple-900 font-semibold !mt-1 !mb-0 tracking-[1px] md:tracking-[2px] uppercase break-word ojb-title no-border-input"
                          style={{
                            ...getResponsiveFontSize( titleFontSize, titleFontSizeUnit || 'px', activeDevice ),
                            ...getResponsiveLineHeight( titleLineHeight, titleLineHeightUnit || 'px', activeDevice ),
                            ...getTextShadowStyle( attributes.titleTextShadow, activeDevice ),
                            fontFamily: titleFontFamily || undefined,
                            fontWeight: titleFontWeight || undefined,
                            color: titleFontColor || undefined
                          }}
                        />
                      </>
                    )}
                    {showDescription && (
                      <>
                        <RichText
                          tagName="p"
                          placeholder="Enter Description..."
                          value={entry.description}
                          onChange={( value ) => updateEntry( index, 'description', value )}
                          className="text-gray-600 !mt-2 !mb-0 text-[15px] md:text-[17px] break-word ojb-description no-border-input"
                          style={{
                            ...getResponsiveFontSize( descriptionFontSize, descriptionFontSizeUnit || 'px', activeDevice ),
                            ...getResponsiveLineHeight( descriptionLineHeight, descriptionLineHeightUnit || 'px', activeDevice ),
                            fontFamily: descriptionFontFamily || undefined,
                            fontWeight: descriptionFontWeight || undefined,
                            color: descriptionFontColor || undefined
                          }}
                        />
                      </>
                    )}
                  </div>
                </div>
                {/* Spacer div for desktop layout to push content apart. */}
                {/* Milestone Image. */}
              </div>
              <div className="remove-items flex justify-end w-full">
                <Button
                  onClick={() => removeEntry( index )}
                  variant="primary"
                  isDestructive
                  style={{ marginTop: '10px' }}
                >
                  {__( 'Remove Entry', 'journey-timeline-block' )}
                </Button>
              </div>
            </div>
            ) )}
          </div>
        </div>
      ) : null}
    </div>
  );
};

export default LayoutOne;
