import type { CSSProperties } from "react";
import { LockKeyhole, Play } from "lucide-react";

import { CharacterAvatar } from "@/app/_components";
import type { PrivateZoneVideoPost } from "@/data/schemas/private-zone";

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

export interface PrivateZoneVideoPostCardProps {
  post: PrivateZoneVideoPost;
  displayName: string;
  avatarUrl: string;
  index: number;
  isUnlocking: boolean;
  onUnlock: () => void;
  onPlaybackError: () => void;
}

export function PrivateZoneVideoPostCard({
  post,
  displayName,
  avatarUrl,
  index,
  isUnlocking,
  onUnlock,
  onPlaybackError,
}: PrivateZoneVideoPostCardProps) {
  return (
    <article
      className={styles.postCard}
      style={{ "--reveal-index": index } as CSSProperties}
    >
      <header className={styles.postHeader}>
        <div className={styles.postAuthor}>
          <CharacterAvatar
            src={avatarUrl}
            alt=""
            size={38}
            imageSize={38}
            className={styles.postAvatar}
          />
          <div>
            <p className={styles.authorName}>{displayName}</p>
            <p className={styles.authorSubline}>Private moment</p>
          </div>
        </div>
        <time className={styles.postTime}>{formatMomentTime(post.publishedAt)}</time>
      </header>

      {post.caption ? <p className={styles.postText}>{post.caption}</p> : null}

      {post.unlocked && post.videoUrl ? (
        <video
          className={styles.momentVideo}
          controls
          playsInline
          preload="metadata"
          poster={post.posterUrl ?? undefined}
          onError={onPlaybackError}
        >
          <source src={post.videoUrl} type={post.videoMimeType || "video/mp4"} />
          Your browser cannot play this video.
        </video>
      ) : (
        <div className={styles.momentLockedMedia}>
          {post.posterUrl ? (
            // Signed private media URLs intentionally bypass Next image optimization.
            // eslint-disable-next-line @next/next/no-img-element
            <img
              className={styles.momentPoster}
              src={post.posterUrl}
              alt="Private video cover"
            />
          ) : (
            <div className={styles.momentPosterFallback}>
              <Play size={34} aria-hidden="true" />
            </div>
          )}
          <div className={styles.momentLockPanel}>
            <span className={styles.momentLockIcon} aria-hidden="true">
              <LockKeyhole size={18} />
            </span>
            <strong>Private video</strong>
            <span>
              {post.durationSeconds == null
                ? "Unlock to watch"
                : `${formatDuration(post.durationSeconds)} · Unlock to watch`}
            </span>
            <button
              type="button"
              data-analytics-key="private_zone_video.unlock"
              data-analytics-label="Unlock Private Zone video moment"
              disabled={isUnlocking || !post.availableForNewUnlock}
              onClick={onUnlock}
            >
              {isUnlocking
                ? "Unlocking..."
                : post.availableForNewUnlock
                  ? `Unlock for ${post.unlockCostCredits} credits`
                  : "No longer available"}
            </button>
          </div>
        </div>
      )}
    </article>
  );
}

function formatDuration(seconds: number): string {
  const safe = Math.max(0, Math.round(seconds));
  const minutes = Math.floor(safe / 60);
  const remainder = String(safe % 60).padStart(2, "0");
  return `${minutes}:${remainder}`;
}

function formatMomentTime(value: string): string {
  const parsed = new Date(value);
  if (Number.isNaN(parsed.getTime())) return "Just now";
  const seconds = Math.max(0, Math.floor((Date.now() - parsed.getTime()) / 1000));
  if (seconds < 60) return "Just now";
  if (seconds < 3600) return `${Math.floor(seconds / 60)}m`;
  if (seconds < 86400) return `${Math.floor(seconds / 3600)}h`;
  if (seconds < 604800) return `${Math.floor(seconds / 86400)}d`;
  return parsed.toLocaleDateString(undefined, { month: "short", day: "numeric" });
}
