"use client";

import Image from "next/image";
import Link from "next/link";
import { useEffect, useRef, useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { playfair, montserrat } from "@/lib/fonts";


const CMS_BASE_URL =
  process.env.NEXT_PUBLIC_CMS_BASE_URL?.replace(/\/$/, "") ?? "";

import {
  type RichTextRoot,
  type RichTextChild,
  renderLexical,
  extractPlainText
} from "../utils";

type MediaSizes = {
  small?: { url?: string | null };
  medium?: { url?: string | null };
  large?: { url?: string | null };
  og?: { url?: string | null };
};

type MediaDocument = {
  url?: string | null;
  alt?: string | null;
  sizes?: MediaSizes | null;
};

type OfferBannerBlock = {
  type?: string;
  props?: {
    variant?: string | null;
    desktopImageId?: number | null;
    desktopImage?: number | null;
    mobileImageId?: number | null;
    backgroundImageId?: number | null;
    headline?: string | RichTextRoot | null;
    subheadline?: string | RichTextRoot | null;
    inclusionText?: string | RichTextRoot | null;
    footerText?: string | RichTextRoot | null;
    expiresAt?: string | null;
    ctas?: {
      label?: string | null;
      href?: string | null;
      ctaId?: string | null;
    }[];
    price?: {
      prefix?: string | null;
      amount?: string | null;
      suffix?: string | null;
    } | null;
    meta?: {
      anchorId?: string | null;
    } | null;
  } | null;
};

type ScillyPageData = {
  layout?: OfferBannerBlock[];
  included?: {
    media?: Record<string, MediaDocument>;
  } | null;
};

type TimeLeft = {
  hours: string;
  minutes: string;
  seconds: string;
  expired: boolean;
};

function isOfferBannerBlock(
  block: OfferBannerBlock | undefined,
): block is OfferBannerBlock {
  return (
    block?.type === "heroOfferV1" && block?.props?.variant === "offer-banner"
  );
}

function toAbsoluteUrl(url?: string | null) {
  if (!url) return null;
  if (url.startsWith("http://") || url.startsWith("https://")) return url;
  if (!CMS_BASE_URL || !url.startsWith("/")) return url;
  return `${CMS_BASE_URL}${url}`;
}

function resolvePreferredImageUrl(media: MediaDocument | null) {
  return toAbsoluteUrl(
    media?.sizes?.large?.url ??
    media?.sizes?.medium?.url ??
    media?.sizes?.small?.url ??
    media?.url,
  );
}

function parseCountdownTarget(endTime?: string | null) {
  if (!endTime) return null;

  const value = endTime.trim();
  if (!value) return null;


  if (/[zZ]|[+\-]\d{2}:\d{2}$/.test(value)) {
    const timestamp = new Date(value).getTime();
    return Number.isNaN(timestamp) ? null : timestamp;
  }


  const dateOnlyMatch = value.match(/^(\d{4})-(\d{2})-(\d{2})$/);
  if (dateOnlyMatch) {
    const [, year, month, day] = dateOnlyMatch;
    return new Date(
      Number(year),
      Number(month) - 1,
      Number(day),
      23,
      59,
      59,
      999,
    ).getTime();
  }

  const localDateTimeMatch = value.match(
    /^(\d{4})-(\d{2})-(\d{2})[T\s](\d{2})(?::(\d{2}))?(?::(\d{2}))?$/,
  );
  if (localDateTimeMatch) {
    const [, year, month, day, hours, minutes = "0", seconds = "0"] =
      localDateTimeMatch;

    return new Date(
      Number(year),
      Number(month) - 1,
      Number(day),
      Number(hours),
      Number(minutes),
      Number(seconds),
      0,
    ).getTime();
  }

  const fallbackTimestamp = new Date(value).getTime();
  return Number.isNaN(fallbackTimestamp) ? null : fallbackTimestamp;
}

function calculateTimeLeft(endTime?: string | null): TimeLeft {
  const endTimestamp = parseCountdownTarget(endTime);

  if (!endTimestamp) {
    return {
      hours: "00",
      minutes: "00",
      seconds: "00",
      expired: true,
    };
  }

  const now = Date.now();
  const diff = endTimestamp - now;

  if (diff <= 0) {
    return {
      hours: "00",
      minutes: "00",
      seconds: "00",
      expired: true,
    };
  }

  const totalSeconds = Math.floor(diff / 1000);
  const hours = Math.floor(totalSeconds / 3600);
  const minutes = Math.floor((totalSeconds % 3600) / 60);
  const seconds = totalSeconds % 60;

  return {
    hours: String(hours).padStart(2, "0"),
    minutes: String(minutes).padStart(2, "0"),
    seconds: String(seconds).padStart(2, "0"),
    expired: false,
  };
}

function splitPriceSuffix(value?: string | null) {
  const parts = value?.trim().split(/\s+/).filter(Boolean) ?? [];

  if (parts.length === 0) {
    return ["", ""] as const;
  }

  if (parts.length === 1) {
    return [parts[0], ""] as const;
  }

  return [parts[0], parts.slice(1).join(" ")] as const;
}

function normalizeHref(href?: string | null) {
  if (!href) return null;
  if (href.startsWith("#")) return href;
  if (href.startsWith("http://") || href.startsWith("https://")) return href;
  return `https://${href}`;
}

export default function WeekendEscapeSection({
  data,
}: {
  data: ScillyPageData;
}) {
  const offerBlock = data.layout?.find(isOfferBannerBlock);
  const mediaMap = data.included?.media ?? {};

  const backgroundImageId =
    offerBlock?.props?.desktopImageId ??
    offerBlock?.props?.desktopImage ??
    offerBlock?.props?.backgroundImageId ??
    null;
  const backgroundImage =
    backgroundImageId != null
      ? (mediaMap[String(backgroundImageId)] ?? null)
      : null;
  const backgroundImageSrc = resolvePreferredImageUrl(backgroundImage);
  const backgroundAlt =
    backgroundImage?.alt?.trim() ||
    extractPlainText(offerBlock?.props?.subheadline) ||
    extractPlainText(offerBlock?.props?.headline) ||
    "";

  const countdownTarget = offerBlock?.props?.expiresAt ?? null;
  const [timeLeft, setTimeLeft] = useState<TimeLeft>(() =>
    calculateTimeLeft(countdownTarget),
  );
  const [tooltipPos, setTooltipPos] = useState<{ x: number; y: number } | null>(null);
  const hoverTimerRef = useRef<NodeJS.Timeout | null>(null);

  useEffect(() => {
    setTimeLeft(calculateTimeLeft(countdownTarget));

    if (!countdownTarget) return undefined;

    const timer = setInterval(() => {
      setTimeLeft(calculateTimeLeft(countdownTarget));
    }, 1000);

    return () => clearInterval(timer);
  }, [countdownTarget]);

  if (!offerBlock?.props) {
    return null;
  }

  const headline = offerBlock.props.headline;
  const subheadline = offerBlock.props.subheadline;
  const inclusionText = offerBlock.props.inclusionText;
  const footerText = offerBlock.props.footerText;
  const pricePrefix = offerBlock.props.price?.prefix?.trim() ?? "";
  const priceAmount = offerBlock.props.price?.amount?.trim() ?? "";
  const priceSuffix = offerBlock.props.price?.suffix?.trim() ?? "";
  const [suffixTop, suffixBottom] = splitPriceSuffix(priceSuffix);
  const activeCta = timeLeft.expired
    ? (offerBlock.props.ctas?.[1] ?? offerBlock.props.ctas?.[0])
    : offerBlock.props.ctas?.[0];
  const ctaHref = normalizeHref(activeCta?.href);
  const ctaLabel = activeCta?.label?.trim() ?? "";

  return (
    <section
      id={offerBlock.props.meta?.anchorId ?? undefined}
      className="relative w-full overflow-hidden text-white lg:min-h-[664px]"
      onMouseMove={(e) => {
        const r = e.currentTarget.getBoundingClientRect();
        if (hoverTimerRef.current) clearTimeout(hoverTimerRef.current);
        setTooltipPos(null);
        hoverTimerRef.current = setTimeout(() => setTooltipPos({ x: e.clientX - r.left, y: e.clientY - r.top }), 1000);
      }}
      onMouseLeave={() => {
        if (hoverTimerRef.current) clearTimeout(hoverTimerRef.current);
        setTooltipPos(null);
      }}
    >
      {backgroundImageSrc ? (
        <Image
          src={backgroundImageSrc}
          alt={backgroundAlt}
          fill
          className="object-cover"
          style={{ objectPosition: "center center" }}
          sizes="100vw"
          loading="lazy"
        />
      ) : null}

      <AnimatePresence>
        {tooltipPos && backgroundAlt && (
          <motion.div
            initial={{ opacity: 0, scale: 0.95 }}
            animate={{ opacity: 1, scale: 1 }}
            exit={{ opacity: 0, scale: 0.95 }}
            transition={{ duration: 0.12 }}
            style={{
              position: "absolute",
              left: tooltipPos.x,
              top: tooltipPos.y,
              transform: "translate(-50%, calc(-100% - 8px))",
              pointerEvents: "none",
              zIndex: 100,
              whiteSpace: "nowrap",
            }}
            className="rounded border border-black bg-white px-3 py-1.5 text-sm font-semibold text-black shadow-sm"
          >
            {backgroundAlt}
          </motion.div>
        )}
      </AnimatePresence>



      <div className="relative z-10 mx-auto flex w-full max-w-[1905px] flex-col items-center px-4 pt-8 pb-[30px] text-center sm:px-6 sm:pb-[34px] md:px-10 md:pb-[38px] lg:min-h-[664px] lg:px-[60px] lg:pt-[29px] lg:pb-[42px]">
        <div
          className="relative w-full max-w-[1080px] px-4 pt-6 pb-8 sm:px-6 sm:pt-8 md:px-8 lg:h-[450px] lg:px-0 lg:pt-0 lg:pb-0"
        >

          <span className="absolute inset-x-0 top-0 hidden h-[60px] rounded-t-[32px] border-x-[2.7px] border-t-[2.7px] border-[#85714D] sm:block" />

          <span className="absolute bottom-[60px] left-0 top-[60px] hidden w-[2.7px] bg-[#85714D] sm:block" />
          <span className="absolute bottom-[60px] right-0 top-[60px] hidden w-[2.7px] bg-[#85714D] sm:block" />


          <span className="absolute bottom-[20px] left-0 hidden h-[110px] w-[calc(50%_-_150px)] rounded-bl-[32px] border-b-[2.7px] border-l-[2.7px] border-[#85714D] sm:block md:bottom-[30px] md:w-[calc(50%_-_220px)] lg:bottom-0 lg:w-[calc(50%_-_290px)]" />
          <span className="absolute bottom-[20px] right-0 hidden h-[110px] w-[calc(50%_-_150px)] rounded-br-[32px] border-b-[2.7px] border-r-[2.7px] border-[#85714D] sm:block md:bottom-[30px] md:w-[calc(50%_-_220px)] lg:bottom-0 lg:w-[calc(50%_-_290px)]" />

          <div className="flex h-full flex-col items-center lg:pt-[38px]">
            {headline ? (
              <div
                className={`hidden w-full text-center text-[14px] font-medium uppercase leading-[18px] tracking-[0.12em] text-white sm:block sm:text-[16px] sm:leading-[20px] md:text-[18px] lg:w-[932.4px] lg:text-[28.8px] lg:leading-[36px] lg:tracking-[0.05em] ${montserrat.className}`}
              >
                {renderLexical(headline)}
              </div>
            ) : null}

            {subheadline ? (
              <h2
                className={`mt-[17px] hidden text-[28px] font-bold italic leading-none tracking-[0.03em] sm:block sm:text-[34px] md:text-[40px] lg:mt-[32px] lg:block lg:text-[50px] lg:tracking-[0.04em] ${playfair.className}`}
              >
                {renderLexical(subheadline)}
              </h2>
            ) : null}

            <div className="mt-5 flex w-full flex-col items-center gap-4 lg:mt-[40px] lg:w-[1022px] lg:flex-row lg:items-center lg:justify-between lg:gap-[20px]">
              <div className="flex w-full flex-col items-center gap-2 lg:w-[423px] lg:items-start lg:gap-[4px]">
                <div className="flex flex-col items-start gap-0">
                  {pricePrefix ? (
                    <div
                      className={`text-left text-[22px] font-normal leading-none text-white sm:text-[26px] md:text-[28px] lg:w-[97px] lg:pl-[4px] lg:text-[40px] ${playfair.className}`}
                    >
                      {pricePrefix}
                    </div>
                  ) : null}

                  <div className="flex items-end justify-start gap-0 lg:gap-1 -mt-2 sm:-mt-3 lg:-mt-3">
                    {priceAmount ? (
                      <span
                        className={`text-left text-[58px] font-bold leading-[100%] text-white sm:text-[72px] md:text-[80px] lg:text-[110px] ${playfair.className}`}
                      >
                        {priceAmount}
                      </span>
                    ) : null}

                    {priceSuffix ? (
                      <div className="flex flex-col items-center justify-end gap-1 pb-1 sm:gap-2 lg:w-[129px] lg:gap-[9.48px]">
                        <span className="flex items-center text-center uppercase text-white lg:h-[44px]">
                          <span
                            className={`text-[28px] font-normal leading-none sm:text-[34px] md:text-[36px] lg:text-[70px] ${playfair.className}`}
                          >
                            {suffixTop}
                          </span>
                        </span>

                        {suffixBottom ? (
                          <span className="flex items-center text-center uppercase text-white lg:h-[31px]">
                            <span
                              className={`text-[18px] font-normal leading-none sm:text-[22px] md:text-[24px] lg:text-[40px] ${playfair.className}`}
                            >
                              {suffixBottom}
                            </span>
                          </span>
                        ) : null}
                      </div>
                    ) : null}
                  </div>
                </div>
              </div>

              {priceAmount && inclusionText ? (
                <div className="flex items-center justify-center lg:translate-y-[28px]">
                  <span
                    className={`text-[38px] font-normal leading-none sm:text-[48px] md:text-[56px] lg:text-[72px] ${playfair.className}`}
                  >
                    +
                  </span>
                </div>
              ) : null}

              {inclusionText ? (
                <div
                  className={`flex w-full items-end justify-center text-center text-[24px] font-normal leading-[1.2] sm:text-[28px] md:text-[32px] lg:w-[516px] lg:translate-y-[21px] lg:justify-start lg:text-left lg:text-[54px] lg:leading-[54px] ${playfair.className}`}
                >
                  <div>
                    {typeof inclusionText === 'string' ? (
                      <>
                        <span className="block sm:hidden whitespace-pre-line">
                          {inclusionText.split(/\s+/).filter(Boolean).join("\n")}
                        </span>
                        <span className="hidden sm:block">{inclusionText}</span>
                      </>
                    ) : (
                      renderLexical(inclusionText)
                    )}
                  </div>
                </div>
              ) : null}
            </div>

            {footerText ? (
              <div className="mt-8 max-w-[528px] text-center text-[11px] font-light uppercase leading-[18px] tracking-[0.05em] text-white/80 sm:text-[12px] sm:leading-[20px] md:text-[16px] md:leading-[22px] lg:mt-[65.8px] lg:text-[20px] lg:leading-[25px]">
                {renderLexical(footerText)}
              </div>
            ) : null}
          </div>
        </div>

        {ctaHref && ctaLabel ? (
          <Link
            href={ctaHref}
            id={activeCta?.ctaId ?? undefined}
            className="mirror-cta group mt-8 flex h-[56px] w-[260px] items-center justify-center overflow-hidden rounded-full text-[14px] font-semibold uppercase tracking-[0.14em] text-white transition-all duration-300 ease-out sm:mt-10 sm:h-[62px] sm:w-[290px] sm:text-[16px] md:h-[68px] md:w-[320px] md:text-[18px] lg:mt-[110px] lg:h-[73px] lg:w-[350px] lg:text-[20px] lg:tracking-[0.18em]"
          >
            <svg
              className="mirror-cta-svg"
              viewBox="0 0 350 73"
              preserveAspectRatio="none"
              aria-hidden="true"
            >
              <rect
                className="mirror-cta-stroke"
                x="1.4"
                y="1.4"
                width="347.2"
                height="70.2"
                rx="35.1"
                ry="35.1"
              />
              <rect
                className="mirror-cta-stroke-glow"
                x="1.4"
                y="1.4"
                width="347.2"
                height="70.2"
                rx="35.1"
                ry="35.1"
              />
            </svg>
            <span className="mirror-cta-highlight" />
            <span className="mirror-cta-shadow" />

            <span className="mirror-cta-content flex items-center justify-center gap-3 sm:gap-4 lg:gap-[18px]">
              <span>{ctaLabel}</span>
              <span className="translate-x-0 text-[24px] font-normal leading-none transition-transform duration-300 group-hover:translate-x-[4px] sm:text-[28px] lg:text-[34px]">
                &rarr;
              </span>
            </span>
          </Link>
        ) : null}

        {countdownTarget && !timeLeft.expired ? (
          <div className="mt-4 flex items-center justify-center gap-3 text-[20px] font-medium tracking-[0.08em] sm:mt-5 sm:gap-4 sm:text-[24px] md:mt-6 md:text-[30px] lg:mt-[27px] lg:gap-[27px] lg:text-[40px]">
            <span>{timeLeft.hours} H</span>
            <span>:</span>
            <span>{timeLeft.minutes} M</span>
            <span>:</span>
            <span>{timeLeft.seconds} S</span>
          </div>
        ) : null}
      </div>
    </section>
  );
}