"use client";

import type { CSSProperties } from "react";
import { useEffect, useMemo, useRef } from "react";
import Image from "next/image";
import {
  ImageIcon,
  LockKeyhole,
  RefreshCw,
  Sparkles,
} from "lucide-react";

import type { PrivateRoomMoment } from "@/data/dto/private-room";
import { AppBottomNav, MobileShell } from "@/app/_components/core";
import { useGuestLoginBootstrap } from "@/hooks/use-guest-login-bootstrap";
import { ROUTES } from "@/router/routes";
import { useAppNavigator } from "@/router/use-app-navigator";
import { useAuthDispatch, useAuthState } from "@/stores/auth/auth-context";
import {
  usePrivateRoomDispatch,
  usePrivateRoomState,
} from "@/stores/private-room";
import { useUserDispatch } from "@/stores/user/user-context";

import styles from "./private-room-screen.module.css";

const FALLBACK_PROFILE = {
  name: "Elio Silvestri",
  handle: "@elio.private",
  avatar: "/images/chat/pic-chat-elio.png",
  title: "Elio Private room",
  subtitle: "Join me, unlock my private room",
  bio: "Soft moments, private photos, and a little sweetness just for you.",
} as const;

export function PrivateRoomScreen() {
  const navigator = useAppNavigator();
  const authState = useAuthState();
  const authDispatch = useAuthDispatch();
  const userDispatch = useUserDispatch();
  const state = usePrivateRoomState();
  const dispatch = usePrivateRoomDispatch();
  const previousLoginStatusRef = useRef(authState.loginStatus);
  const lastUnlockSuccessNonceRef = useRef(0);

  useGuestLoginBootstrap({
    dispatch: authDispatch,
    hasInitialized: authState.hasInitialized,
    isLoading: authState.isLoading,
    loginStatus: authState.loginStatus,
  });

  useEffect(() => {
    if (!authState.hasInitialized || authState.isLoading) return;
    if (authState.loginStatus === "notLoggedIn") return;

    const previousLoginStatus = previousLoginStatusRef.current;
    previousLoginStatusRef.current = authState.loginStatus;

    if (state.status === "idle") {
      dispatch({ type: "PrivateRoomInit" });
      return;
    }

    if (
      previousLoginStatus !== authState.loginStatus &&
      state.status !== "loading"
    ) {
      dispatch({ type: "PrivateRoomRefresh" });
    }
  }, [
    authState.hasInitialized,
    authState.isLoading,
    authState.loginStatus,
    dispatch,
    state.status,
  ]);

  useEffect(() => {
    const request = state.unlockPaywallRequest;
    if (!request) return;

    if (
      authState.loginStatus === "guest" ||
      authState.loginStatus === "notLoggedIn"
    ) {
      navigator.openAuth(ROUTES.privateRoom);
    } else {
      navigator.openSubscription({ type: "topup" });
    }
    dispatch({ type: "PrivateRoomUnlockPaywallConsumed" });
  }, [
    authState.loginStatus,
    dispatch,
    navigator,
    state.unlockPaywallRequest,
  ]);

  useEffect(() => {
    if (state.unlockSuccessNonce <= lastUnlockSuccessNonceRef.current) return;
    lastUnlockSuccessNonceRef.current = state.unlockSuccessNonce;
    userDispatch({ type: "UserFetch" });
  }, [state.unlockSuccessNonce, userDispatch]);

  const profile = state.profile;
  const displayName =
    profile?.displayName || profile?.authorName || FALLBACK_PROFILE.name;
  const avatarUrl = profile?.avatarUrl || FALLBACK_PROFILE.avatar;
  const title = profile?.title || FALLBACK_PROFILE.title;
  const subtitle = profile?.subtitle || FALLBACK_PROFILE.subtitle;
  const pendingMoment = useMemo(
    () =>
      state.items.find(
        (item) => item.momentId === state.pendingConfirmMomentId,
      ) ?? null,
    [state.items, state.pendingConfirmMomentId],
  );

  const handleTopUpClick = () => {
    if (
      authState.loginStatus === "guest" ||
      authState.loginStatus === "notLoggedIn"
    ) {
      navigator.openAuth(ROUTES.privateRoom);
      return;
    }
    navigator.openSubscription({ type: "topup" });
  };

  return (
    <MobileShell background="#fff7ed">
      <main className={styles.shell}>
        <div className={styles.backgroundGlowOne} />
        <div className={styles.backgroundGlowTwo} />

        <section className={styles.hero} aria-labelledby="private-room-title">
          <div className={styles.heroTopline}>
            <span className={styles.liveDot} aria-hidden="true" />
            <span>Private room is open</span>
          </div>

          <div className={styles.identity}>
            <div className={styles.avatarFrame}>
              <Image
                src={avatarUrl}
                alt={displayName}
                width={72}
                height={72}
                priority
              />
            </div>

            <div className={styles.identityText}>
              <h1 id="private-room-title" className={styles.title}>
                {displayName}
              </h1>
              <p className={styles.handle}>{title}</p>
            </div>
          </div>

          <p className={styles.bio}>{subtitle || FALLBACK_PROFILE.bio}</p>

          <button
            type="button"
            className={styles.primaryCta}
            onClick={handleTopUpClick}
          >
            <Sparkles size={16} aria-hidden="true" />
            <span>Top up credits</span>
          </button>
        </section>

        <section className={styles.postsSection} aria-labelledby="posts-title">
          <div className={styles.sectionHeader}>
            <div>
              <p className={styles.kicker}>Posts</p>
              <h2 id="posts-title" className={styles.sectionTitle}>
                Private moments
              </h2>
            </div>
            <span className={styles.postCount}>{state.items.length}</span>
          </div>

          {state.errorMessage ? (
            <StatusCard
              message={state.errorMessage}
              actionLabel="Retry"
              onAction={() => dispatch({ type: "PrivateRoomRefresh" })}
            />
          ) : null}

          {state.isLoading && state.items.length === 0 ? (
            <StatusCard message="Loading private moments..." />
          ) : null}

          {!state.isLoading && state.items.length === 0 && !state.errorMessage ? (
            <StatusCard
              message="No private moments yet."
              actionLabel="Refresh"
              onAction={() => dispatch({ type: "PrivateRoomRefresh" })}
            />
          ) : null}

          <div className={styles.timeline}>
            {state.items.map((moment, index) => (
              <PrivateRoomPostCard
                key={moment.momentId}
                moment={moment}
                displayName={displayName}
                avatarUrl={avatarUrl}
                index={index}
                isUnlocking={state.unlockingMomentId === moment.momentId}
                onUnlock={() =>
                  dispatch({
                    type: "PrivateRoomUnlockRequested",
                    momentId: moment.momentId,
                  })
                }
              />
            ))}
          </div>

          {state.hasMore ? (
            <button
              type="button"
              className={styles.loadMoreButton}
              disabled={state.isLoadingMore}
              onClick={() => dispatch({ type: "PrivateRoomLoadMore" })}
            >
              <RefreshCw size={15} aria-hidden="true" />
              {state.isLoadingMore ? "Loading..." : "Load more"}
            </button>
          ) : null}
        </section>

        <AppBottomNav
          activeItem="privateRoom"
          onChatClick={() => navigator.openChat({ replace: false })}
          onPrivateRoomClick={() => undefined}
        />

        {pendingMoment ? (
          <UnlockConfirmDialog
            moment={pendingMoment}
            isUnlocking={state.isUnlocking}
            errorMessage={state.unlockErrorMessage}
            onCancel={() => dispatch({ type: "PrivateRoomUnlockCancelled" })}
            onConfirm={() => dispatch({ type: "PrivateRoomUnlockConfirmed" })}
          />
        ) : state.unlockErrorMessage ? (
          <div className={styles.toast} role="status">
            {state.unlockErrorMessage}
          </div>
        ) : null}
      </main>
    </MobileShell>
  );
}

function PrivateRoomPostCard({
  moment,
  displayName,
  avatarUrl,
  index,
  isUnlocking,
  onUnlock,
}: {
  moment: PrivateRoomMoment;
  displayName: string;
  avatarUrl: string;
  index: number;
  isUnlocking: boolean;
  onUnlock: () => void;
}) {
  const isLocked = moment.locked || moment.lockDetail.locked;
  const imageUrls = moment.images
    .filter((image) => !image.locked && image.url)
    .map((image) => image.url as string);
  const photoCount = moment.mediaCount || moment.images.length || 1;

  return (
    <article
      className={styles.postCard}
      style={{ "--reveal-index": index } as CSSProperties}
    >
      <header className={styles.postHeader}>
        <div className={styles.postAuthor}>
          <Image
            src={avatarUrl}
            alt=""
            width={38}
            height={38}
            className={styles.postAvatar}
          />
          <div>
            <p className={styles.authorName}>{moment.author.name || displayName}</p>
            <p className={styles.authorSubline}>
              {moment.title || "Private room drop"}
            </p>
          </div>
        </div>
        <time className={styles.postTime}>
          {moment.timeText || formatMomentTime(moment.publishedAt)}
        </time>
      </header>

      {moment.text || moment.content ? (
        <p className={styles.postText}>{moment.text || moment.content}</p>
      ) : null}

      {isLocked ? (
        <button
          type="button"
          className={styles.lockedPreview}
          disabled={isUnlocking}
          onClick={onUnlock}
          aria-label={`Unlock ${photoCount} private room photos from ${displayName}`}
        >
          <div className={styles.previewIcon}>
            <LockKeyhole size={18} aria-hidden="true" />
          </div>
          <div className={styles.previewText}>
            <strong>{moment.unlockCost} credits</strong>
            <span>{moment.textPreview || "Unlock to view"}</span>
            <small>
              <ImageIcon size={13} aria-hidden="true" />
              {photoCount} {photoCount === 1 ? "photo" : "photos"}
            </small>
          </div>
        </button>
      ) : (
        <div className={styles.imageGrid}>
          {imageUrls.map((url, imageIndex) => (
            <Image
              key={`${moment.momentId}-${imageIndex}`}
              src={url}
              alt=""
              width={420}
              height={420}
              className={styles.unlockedImage}
              sizes="(max-width: 540px) 86vw, 460px"
            />
          ))}
        </div>
      )}
    </article>
  );
}

function UnlockConfirmDialog({
  moment,
  isUnlocking,
  errorMessage,
  onCancel,
  onConfirm,
}: {
  moment: PrivateRoomMoment;
  isUnlocking: boolean;
  errorMessage: string | null;
  onCancel: () => void;
  onConfirm: () => void;
}) {
  return (
    <div className={styles.dialogOverlay} role="alertdialog" aria-modal="true">
      <div className={styles.dialog}>
        <h2 className={styles.dialogTitle}>Unlock private moment?</h2>
        <p className={styles.dialogCopy}>
          This will use {moment.unlockCost} credits.
        </p>
        {errorMessage ? (
          <p className={styles.dialogError}>{errorMessage}</p>
        ) : null}
        <div className={styles.dialogActions}>
          <button
            type="button"
            className={styles.dialogSecondary}
            disabled={isUnlocking}
            onClick={onCancel}
          >
            Cancel
          </button>
          <button
            type="button"
            className={styles.dialogPrimary}
            disabled={isUnlocking}
            onClick={onConfirm}
          >
            {isUnlocking ? "Unlocking..." : "Unlock"}
          </button>
        </div>
      </div>
    </div>
  );
}

function StatusCard({
  message,
  actionLabel,
  onAction,
}: {
  message: string;
  actionLabel?: string;
  onAction?: () => void;
}) {
  return (
    <div className={styles.statusCard}>
      <p>{message}</p>
      {actionLabel && onAction ? (
        <button type="button" onClick={onAction}>
          {actionLabel}
        </button>
      ) : null}
    </div>
  );
}

function formatMomentTime(value: string | null): string {
  if (!value) return "";
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return "";
  return date.toLocaleDateString(undefined, {
    month: "short",
    day: "numeric",
  });
}
