// Import necessary components and hooks from WordPress packages.
const { useEffect, useRef } = wp.element;
const { Button } = wp.components;
const { RichText, MediaUpload, MediaUploadCheck, useBlockProps } = 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,

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

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

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

    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 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( null );

  const isEditor11 = 'undefined' !== typeof wp && wp.data?.select( 'core/editor' );
  
  useEffect( () => {
    let ctx;

    const initAnimations = () => {
      if (ctx) {
        ctx = null;
      }
      
      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;
            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(); // Initial run.

    const updateUnderline = () => {
      const title = document.getElementById( uniqueJourneyTitleIdRef.current );
      const svg = document.getElementById( uniqueUnderlineIdRef.current );

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

      const titleRect = title.getBoundingClientRect();
      const fontSize = parseFloat( getComputedStyle( title ).fontSize );

      // Set SVG width equal to the h2 width.
      svg.style.width = `${titleRect.width}px`;

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

    AOS.init({
      duration: 1000,
      once: false
    });
    let animationFrameId;
    const refreshLoop = () => {
      AOS.refreshHard(); // Ensures recalculation.
      animationFrameId = requestAnimationFrame( refreshLoop );
    };
    refreshLoop(); // Start the loop
    // Resize handler
    const handleResize = () => {

      initAnimations();
      updateUnderline();
    };

    window.addEventListener( 'resize', handleResize );

    return () => {
      window.removeEventListener( 'resize', handleResize );
      cancelAnimationFrame( animationFrameId );
      if ( ctx ) {
        ctx.revert();
      }
    };

  }, [ attributes, activeDevice ]);

  return (
    <div ref={comp} className={`journey-continer px-4 py-6 md:px-8 lg:px-5 ${attributes.layout}`}>
      {showHeading && (
        <div className="w-full text-center mb-20 md:mb-24">
          <div className="creative-title-wrapper flex flex-col items-center">
            <>
              <RichText
                tagName="h2"
                id={uniqueJourneyTitleIdRef.current}
                placeholder="Our Journey"
                value={attributes.heading}
                onChange={( value ) => setAttributes({ heading: value })}
                className="text-3xl !mt-0 !mb-0 sm:text-4xl md:text-5xl lg:text-6xl text-purple-900 font-semibold text-center 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
              id={uniqueUnderlineIdRef.current}
              className="w-[150px] h-[25px] md:w-[320px] md:h-[45px] mt-[5px] md:mt-[10px]"
              viewBox="0 0 200 10" preserveAspectRatio="none" fill="none" xmlns="http://www.w3.org/2000/svg"
            >
              <path
                id={uniqueUnderlinePathIdRef.current}
                d="M0 5 Q 50 0 100 5 T 200 5"
                stroke={headingFontColor || '#59168b'}
                strokeWidth="2"
                strokeLinecap="round"
                fill="none"
              />
            </svg>
          </div>
        </div>
      )}
      {Array.isArray( entries ) && 0 < entries.length ? (
        <div className={'relative journey-main'} style={{ position: 'relative' }} >
          {/* Curved Timeline Line. */}
          <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}
            style={{ display: 'block', margin: '0 auto' }}
          >
            <path
              d="M 50 0 Q 55 10 50 20 Q 45 30 50 40 Q 55 50 50 60 Q 45 70 50 80 Q 55 90 50 100"
              stroke="#59168b"
              vectorEffect="non-scaling-stroke"
              fill="none"
              strokeWidth={3}
              strokeDasharray="1 5"
              strokeLinecap="round"
            />
          </svg>

          {/* Plane. */}
          <img
            id={uniquePlaneIdRef.current}
            ref={planeRef}
            src={planeIcon}
            alt="Plane"
            className="absolute w-12 h-12 md:w-16 md:h-16 lg:w-20 lg:h-20 z-5 plane-img"
            style={{
              position: 'absolute',
              top: 0,
              left: 0,
              zIndex: 10
            }}
          />

          {/* Timeline Items. */}
          <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 md:justify-between overflow-hidden'}>
                  {/* Content Box. */}
                  <div
                    data-aos={0 === index % 2 ? 'fade-right ' : 'fade-left'}
                    className={`
                      w-full md:w-2/5
                      bg-white py-6 p-5 md:p-5 lg:p-6
                      rounded-2xl border-double border-purple-900
                      mb-8 md:mb-0 text-center ${0 === index % 2 ? 'md:order-1 md:border-l-6 md:ml-0 md:text-left' : 'md:order-3 md:border-r-6 md:mr-0 md:text-right'}
                  `}
                    style={{
                      backgroundColor: sectionItemContentBgColor || undefined
                    }}
                  >
                    {showYear && (
                      <>
                        <RichText
                          tagName={yearTag}
                          placeholder="Enter Year..."
                          value={entry.year}
                          onChange={( value ) => updateEntry( index, 'year', value )}
                          className="block text-4xl md:text-5xl lg:text-6xl text-purple-200 font-semibold tracking-[2px] !mb-5 !mt-0 lg:!mb-10 break-word ojb-year no-border-input"
                          style={{
                            ...getResponsiveFontSize( yearFontSize, yearFontSizeUnit || 'px', activeDevice ),
                            ...getResponsiveLineHeight( yearLineHeight, yearLineHeightUnit || 'px', activeDevice ),
                            ...getTextShadowStyle( yearTextShadow, activeDevice ),
                            fontFamily: yearFontFamily || undefined,
                            fontWeight: yearFontWeight || undefined,
                            color: yearFontColor || undefined
                          }}
                        />
                      </>
                    )}

                    {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( 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>

                  {/* Spacer for md screens and up. */}
                  <div className="hidden md:block md:w-1/5 md:inline-block md:h-full md:order-2"></div>

                  {/* Image. */}
                  <div data-aos={0 === index % 2 ? 'fade-left' : 'fade-right'} className={`w-full md:w-2/5 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 m-auto my-5 ${0 === index % 2 ? 'md:me-auto' : 'md:ms-auto'} md:w-[80px] ojb-image`}
                                    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>
                </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;
