"use client";

import { useEffect, useRef, useState } from "react";
import { useParams } from "next/navigation";

type EventItem = {
  name: string;
  headline: string;
  tagline: string;
  accent: string;
  theme: string;
  status: "active" | "deactivated";
  logoUrl: string | null;
  backgroundImageUrl: string | null;
  customFontUrl: string | null;
  showNames: boolean;
  backgroundColour: string;
  textColour: string;
  cardColourOne: string;
  cardColourTwo: string;
  cardColourThree: string;
  cardColourFour: string;
  headingFont: string;
  messageFont: string;
  titleAlignment: "center" | "left" | "right";
  decorativeMotif: "circles" | "leaves" | "confetti" | "none";
  cardShape: string;
  layout: "collage" | "grid" | "spotlight";
  rotationSpeed: string;
};
type Message = { id: number | string; name: string; message: string; imageUrl: string | null };

function copySize(message: string) {
  if (message.length <= 55) return "short";
  if (message.length <= 135) return "medium";
  return "long";
}

function fontStack(font: string, custom: boolean) {
  if (font === "custom" && custom) return '"FlowMoments Custom", Georgia, serif';
  const fonts: Record<string, string> = {
    georgia: 'Georgia, "Times New Roman", serif',
    palatino: '"Palatino Linotype", "Book Antiqua", Palatino, serif',
    times: '"Times New Roman", Times, serif',
    avenir: 'Avenir, "Avenir Next", Montserrat, sans-serif',
    arial: 'Arial, Helvetica, sans-serif',
    trebuchet: '"Trebuchet MS", Arial, sans-serif',
    courier: '"Courier New", Courier, monospace',
  };
  return fonts[font] || fonts.georgia;
}

export default function WallPage() {
  const { slug } = useParams<{ slug: string }>();
  const [event, setEvent] = useState<EventItem>({
    name: "Garden of Thanks",
    headline: "Garden of Thanks",
    tagline: "Small moments. Big gratitude.",
    accent: "#f15a3b",
    theme: "garden",
    status: "active",
    logoUrl: null,
    backgroundImageUrl: null,
    customFontUrl: null,
    showNames: true,
    backgroundColour: "#18201f",
    textColour: "#ffffff",
    cardColourOne: "#bc7969",
    cardColourTwo: "#a95e72",
    cardColourThree: "#c28c58",
    cardColourFour: "#4e7169",
    headingFont: "georgia",
    messageFont: "georgia",
    titleAlignment: "center",
    decorativeMotif: "circles",
    cardShape: "10",
    layout: "collage",
    rotationSpeed: "10",
  });
  const [messages, setMessages] = useState<Message[]>([]);
  const [pageIndex, setPageIndex] = useState(0);
  const [updated, setUpdated] = useState(false);
  const [isFullscreen, setIsFullscreen] = useState(false);
  const knownIds = useRef<Set<string>>(new Set());
  const hasLoaded = useRef(false);
  const updateTimer = useRef<number | null>(null);
  const refreshInFlight = useRef(false);
  const eventSignature = useRef("");
  const messageSignature = useRef("");
  const wakeLock = useRef<{ release: () => Promise<void> } | null>(null);

  useEffect(() => {
    let cancelled = false;

    const preloadNewPhotos = (items: Message[]) => Promise.all(
      items
        .filter((item) => item.imageUrl && !knownIds.current.has(String(item.id)))
        .map((item) => new Promise<void>((resolve) => {
          const image = new Image();
          const timeout = window.setTimeout(resolve, 2500);
          image.onload = image.onerror = () => {
            window.clearTimeout(timeout);
            resolve();
          };
          image.src = String(item.imageUrl);
        }))
    );

    const refresh = async () => {
      if (refreshInFlight.current) return;
      refreshInFlight.current = true;

      try {
        const [eventResponse, messageResponse] = await Promise.all([
          fetch(`/api/events/${slug}`, { cache: "no-store" }),
          fetch(`/api/events/${slug}/messages`, { cache: "no-store" }),
        ]);
        if (!eventResponse.ok || !messageResponse.ok) return;

        const [eventData, messageData] = await Promise.all([
          eventResponse.json(),
          messageResponse.json(),
        ]);
        if (cancelled) return;

        if (eventData.event) {
          const nextEventSignature = JSON.stringify(eventData.event);
          if (nextEventSignature !== eventSignature.current) {
            eventSignature.current = nextEventSignature;
            setEvent(eventData.event);
          }
        }

        const nextMessages = (messageData.messages || []) as Message[];
        const hasNewMessage = hasLoaded.current
          && nextMessages.some((item) => !knownIds.current.has(String(item.id)));
        await preloadNewPhotos(nextMessages);
        if (cancelled) return;

        const nextMessageSignature = JSON.stringify(
          nextMessages.map((item) => [item.id, item.name, item.message, item.imageUrl])
        );
        if (nextMessageSignature !== messageSignature.current) {
          messageSignature.current = nextMessageSignature;
          setMessages(nextMessages);
          setPageIndex(0);
        }

        knownIds.current = new Set(nextMessages.map((item) => String(item.id)));
        hasLoaded.current = true;
        if (hasNewMessage) {
          setUpdated(true);
          if (updateTimer.current) window.clearTimeout(updateTimer.current);
          updateTimer.current = window.setTimeout(() => setUpdated(false), 1800);
        }
      } catch {
        // Keep the currently displayed wall intact through brief network interruptions.
      } finally {
        refreshInFlight.current = false;
      }
    };

    refresh().catch(() => undefined);
    const timer = window.setInterval(() => refresh().catch(() => undefined), 6000);
    return () => {
      cancelled = true;
      window.clearInterval(timer);
      if (updateTimer.current) window.clearTimeout(updateTimer.current);
    };
  }, [slug]);

  const pageSize = event.layout === "spotlight" ? 1 : event.layout === "grid" ? 6 : 8;
  const pageCount = Math.max(1, Math.ceil(messages.length / pageSize));
  const visibleMessages = messages.slice(
    (pageIndex % pageCount) * pageSize,
    (pageIndex % pageCount) * pageSize + pageSize
  );

  useEffect(() => {
    if (pageCount <= 1) return;
    const seconds = Math.max(5, Math.min(30, Number(event.rotationSpeed) || 10));
    const timer = window.setInterval(() => {
      setPageIndex((current) => (current + 1) % pageCount);
    }, seconds * 1000);
    return () => window.clearInterval(timer);
  }, [event.layout, event.rotationSpeed, pageCount]);

  useEffect(() => {
    const updateFullscreenState = () => {
      const fullscreenDocument = document as Document & { webkitFullscreenElement?: Element };
      const active = Boolean(document.fullscreenElement || fullscreenDocument.webkitFullscreenElement);
      setIsFullscreen(active);
      if (!active && wakeLock.current) {
        wakeLock.current.release().catch(() => undefined);
        wakeLock.current = null;
      }
    };
    document.addEventListener("fullscreenchange", updateFullscreenState);
    document.addEventListener("webkitfullscreenchange", updateFullscreenState);
    return () => {
      document.removeEventListener("fullscreenchange", updateFullscreenState);
      document.removeEventListener("webkitfullscreenchange", updateFullscreenState);
      wakeLock.current?.release().catch(() => undefined);
      wakeLock.current = null;
    };
  }, []);

  useEffect(() => {
    if (!event.customFontUrl) return;
    const face = new FontFace("FlowMoments Custom", `url("${event.customFontUrl}")`);
    face.load().then((loaded) => document.fonts.add(loaded)).catch(() => undefined);
    return () => {
      document.fonts.delete(face);
    };
  }, [event.customFontUrl]);

  async function toggleFullscreen() {
    const fullscreenDocument = document as Document & {
      webkitExitFullscreen?: () => Promise<void>;
      webkitFullscreenElement?: Element;
    };
    const fullscreenElement = document.documentElement as HTMLElement & {
      webkitRequestFullscreen?: () => Promise<void>;
    };
    const active = document.fullscreenElement || fullscreenDocument.webkitFullscreenElement;

    try {
      if (active) {
        if (document.exitFullscreen) await document.exitFullscreen();
        else await fullscreenDocument.webkitExitFullscreen?.();
        await wakeLock.current?.release();
        wakeLock.current = null;
        return;
      }

      if (fullscreenElement.requestFullscreen) {
        await fullscreenElement.requestFullscreen({ navigationUI: "hide" });
      } else {
        await fullscreenElement.webkitRequestFullscreen?.();
      }

      const orientation = screen.orientation as unknown as {
        lock?: (orientation: string) => Promise<void>;
      };
      await orientation.lock?.("landscape").catch(() => undefined);

      const wakeLockNavigator = navigator as Navigator & {
        wakeLock?: { request: (type: "screen") => Promise<{ release: () => Promise<void> }> };
      };
      wakeLock.current = await wakeLockNavigator.wakeLock?.request("screen") || null;
    } catch {
      // Some Android browsers keep their own browser controls; the wall still uses 100dvh.
    }
  }

  return (
    <main
      className={`live-wall theme-${event.theme} ${event.backgroundImageUrl ? "has-event-background" : ""}`}
      style={{
        "--event-accent": event.accent,
        "--wall-heading": fontStack(event.headingFont, Boolean(event.customFontUrl)),
        "--wall-message": fontStack(event.messageFont, Boolean(event.customFontUrl)),
        "--wall-background": event.backgroundColour,
        "--wall-text": event.textColour,
        "--card-one": event.cardColourOne,
        "--card-two": event.cardColourTwo,
        "--card-three": event.cardColourThree,
        "--card-four": event.cardColourFour,
        "--card-radius": `${Number(event.cardShape) || 10}px`,
        backgroundImage: event.backgroundImageUrl
          ? `linear-gradient(rgba(12,18,17,.68), rgba(12,18,17,.78)), url("${event.backgroundImageUrl}")`
          : undefined,
        backgroundColor: event.backgroundColour,
        color: event.textColour,
      } as React.CSSProperties}
    >
      <header className="wall-header">
        <div className="wall-brand">
          {event.logoUrl ? <img className="wall-event-logo" src={event.logoUrl} alt={`${event.name} logo`} /> : null}
          <span>LIVE</span><i /> FLOWMOMENTS <a href="https://www.flowlab.works" target="_blank" rel="noreferrer">BY FLOWLAB</a>
        </div>
        <div className="wall-title" style={{ textAlign: event.titleAlignment }}><small>WELCOME TO</small><h1>{event.headline}</h1><p>{event.tagline}</p></div>
        <div className="wall-actions">
          <div className={`live-status ${updated ? "updated" : ""}`}>
            <i />
            {updated
              ? "New moment added"
              : `${messages.length} ${messages.length === 1 ? "moment" : "moments"} live`}
          </div>
          <button className="fullscreen-button" type="button" onClick={toggleFullscreen}>
            <span aria-hidden="true">{isFullscreen ? "×" : "⛶"}</span>
            {isFullscreen ? "Exit" : "Full screen"}
          </button>
        </div>
      </header>

      {event.status === "deactivated" ? (
        <section className="wall-empty" aria-live="polite">
          <span>EVENT CLOSED</span>
          <h2>This wall has been deactivated.</h2>
          <p>The organiser can reactivate it from the Event Library.</p>
        </section>
      ) : visibleMessages.length ? (
        <section
          className={`mosaic count-${visibleMessages.length} layout-${event.layout} motif-${event.decorativeMotif}`}
          aria-live="polite"
        >
          {visibleMessages.map((item, index) => (
            <article
              className={[
                "moment-card",
                `moment-${index + 1}`,
                item.imageUrl ? "has-photo" : "text-only",
                `copy-${copySize(item.message)}`,
              ].join(" ")}
              key={item.id}
              style={{ animationDelay: `${index * 65}ms` }}
            >
              {item.imageUrl ? (
                <img src={item.imageUrl} alt={`Moment shared by ${item.name}`} />
              ) : (
                <div className={`memory-art memory-${(index % 8) + 1}`}>
                  <span /><i /><b />
                </div>
              )}
              <div className="moment-copy">
                <small>MOMENT {String(index + 1).padStart(2, "0")}</small>
                <blockquote>“{item.message}”</blockquote>
                {event.showNames && item.name && item.name !== "Anonymous" ? <span>— {item.name}</span> : null}
              </div>
            </article>
          ))}
        </section>
      ) : (
        <section className="wall-empty" aria-live="polite">
          <span>LIVE WALL</span>
          <h2>Your wall is ready for its first moment.</h2>
          <p>New stories and messages will appear here as they are added.</p>
        </section>
      )}

      <footer className="wall-footer">
        <p>Thank you for being part of our story.</p>
        <div><span className="qr-placeholder">↗</span><span><small>ADD YOUR MOMENT</small>Scan the event QR code</span></div>
      </footer>
    </main>
  );
}
