"use client";

import { useEffect, useRef, useState } from "react";

export interface OfferCardData {
  id: number;
  name: string;
  code: string;
  /** Pre-formatted "25%" / "10%" / "$10" / "A10" — see `formatDiscountBadge`. */
  discountLabel: string;
  /** `strip_tags(description)`, truncated to 150 chars server-side (matches `offers.php`'s own `substr(..., 0, 150)`). */
  truncatedDescription: string;
  /** Whether the real description is longer than 150 chars (only then does a "Read More" link exist on the live site). */
  hasMore: boolean;
  /** Raw CMS description HTML, only needed once "Read More" is clicked. */
  fullDescriptionHtml: string;
  cartUrl: string;
}

/**
 * Wires up `/offers`' "Read More" slide-out panel (`.coupon-code-deatil`) and
 * the three animated stat counters (`.overview`'s orders/writers/reviews),
 * replicating `offers.php`'s own inline `<script>` — `changeSliderData()` and
 * `counter()`/`callcounter()` — with React state instead of jQuery/DOM
 * mutation. The panel's open/close slide (`right: 0` ↔ `right: -100%`) is
 * driven by `offers.css`'s own `.coupon-code-deatil` transition, so this only
 * ever toggles the `open` class — no inline animation needed here.
 */
export function OfferCard({ offer, onReadMore }: { offer: OfferCardData; onReadMore: (offer: OfferCardData) => void }) {
  return (
    <div className="offerbox">
      <p className="title">
        {offer.discountLabel}
        <br />
        OFF
      </p>
      <div className="detailbox">
        <div className="detail-inner-box">
          <p className="offer-list-head">{offer.name}</p>
          <p className="offer-content">
            {offer.truncatedDescription}
            {offer.hasMore && (
              <>
                ...
                <button type="button" className="read-btn-more" onClick={() => onReadMore(offer)}>
                  Read More
                </button>
              </>
            )}
          </p>
        </div>
        <div className="btn-offer">
          <p className="promo-title">
            Promocode
            <span className="promo-cod">{offer.code}</span>
          </p>
          <a href={`${offer.cartUrl}${offer.code}`} className="offer-list-btn">
            Get Deal
          </a>
        </div>
      </div>
    </div>
  );
}

export function OffersSlidePanel({ offer, onClose }: { offer: OfferCardData | null; onClose: () => void }) {
  useEffect(() => {
    if (offer) document.body.style.overflow = "hidden";
    return () => {
      document.body.style.overflow = "";
    };
  }, [offer]);

  return (
    <>
      {/* `right` set inline (not a CSS class) because the real site slides
          this via jQuery `.animate({right: "0"/"-100%"})` — `offers.css`'s
          own `.coupon-code-deatil{right:-100%;transition:all 0.4s ease}`
          already animates smoothly off a plain inline-style change, no
          extra class/CSS needed. */}
      <div className="coupon-code-deatil" style={{ right: offer ? "0" : "-100%" }}>
        {offer && (
          <>
            <div className="promo-bg">
              <span className="detail-head">{offer.name}</span>
              <p className="code-labels">
                Promocode -<span className="code-li">{offer.code}</span>
              </p>
            </div>
            <a href="javascript:;" aria-label="cross" className="close-promo" onClick={onClose} />
            <p className="code-detail" dangerouslySetInnerHTML={{ __html: offer.fullDescriptionHtml }} />
            <a href={`${offer.cartUrl}${offer.code}`} className="place-order">
              Get Deal
            </a>
          </>
        )}
      </div>
      <div className={`overlying${offer ? " overlayy" : ""}`} onClick={onClose} />
    </>
  );
}

export function OffersList({
  offers,
  /** Extra static markup (the affiliate-partner card + offer strip) spliced in before `offers[index]` — matches `offers.php`'s own `if ($key == 1)` insertion point. */
  insertBefore,
}: {
  offers: OfferCardData[];
  insertBefore?: { index: number; content: React.ReactNode };
}) {
  const [activeOffer, setActiveOffer] = useState<OfferCardData | null>(null);
  return (
    <>
      {offers.map((offer, index) => (
        <div key={offer.id} style={{ display: "contents" }}>
          {insertBefore?.index === index && insertBefore.content}
          <OfferCard offer={offer} onReadMore={setActiveOffer} />
        </div>
      ))}
      <OffersSlidePanel offer={activeOffer} onClose={() => setActiveOffer(null)} />
    </>
  );
}

/** One `.overview .list` stat — counts up from `start` to `end` once scrolled into view, same as the real `counter()`/`callcounter()` pair. */
export function AnimatedCount({ id, start, end }: { id: string; start: number; end: number }) {
  const ref = useRef<HTMLSpanElement>(null);

  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    let timer: ReturnType<typeof setInterval> | undefined;
    const observer = new IntersectionObserver(
      (entries) => {
        entries.forEach((entry) => {
          if (!entry.isIntersecting) return;
          observer.unobserve(entry.target);
          let current = start;
          const range = end - start;
          const increment = end > start ? 1 : -1;
          const step = Math.abs(Math.floor(3000 / range));
          timer = setInterval(() => {
            current += increment;
            el.textContent = String(current);
            if (current === end) clearInterval(timer);
          }, step);
        });
      },
      { threshold: 0.3 }
    );
    observer.observe(el);
    return () => {
      observer.disconnect();
      if (timer) clearInterval(timer);
    };
  }, [start, end, id]);

  return <span ref={ref} id={id} suppressHydrationWarning>{start}</span>;
}
