import { describe, it, expect, afterEach, vi } from "vitest";
import { render, cleanup, fireEvent } from "@testing-library/react";
import { PublicPageRenderer } from "@/features/editor/components/PublicPageRenderer";
import type { Block } from "@/features/editor/state/editorStore";

// PublicPageRenderer 비디오 블록 스타일 TDD
// - YouTube URL 은 iframe + pb-video-wrapper 로 렌더링되어야 한다.
// - 업로드(/api/video/:id) URL 은 <video> 태그로 렌더되고 widthPx 가 em 단위로 반영되어야 한다.

describe("PublicPageRenderer - 비디오 블록 스타일", () => {
  afterEach(() => {
    cleanup();
  });

  it("YouTube URL 비디오 블록은 iframe 으로 렌더되고 기본 16:9 wrapper 를 가져야 한다", () => {
    const blocks: Block[] = [
      {
        id: "video_youtube_preview_1",
        type: "video" as any,
        props: {
          sourceUrl: "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
          align: "center",
          widthMode: "auto",
          aspectRatio: "16:9",
        } as any,
      },
    ];

    const { container } = render(<PublicPageRenderer blocks={blocks} />);

    const iframe = container.querySelector('iframe[title="비디오"]') as HTMLIFrameElement | null;
    expect(iframe).not.toBeNull();
    expect(iframe!.src).toContain("youtube.com/embed");

    const wrapper = iframe!.parentElement as HTMLElement | null;
    expect(wrapper).not.toBeNull();
    expect(wrapper!.className).toContain("pb-video-wrapper");
  });

  it("업로드 비디오 URL 은 video 태그로 렌더되고 widthPx 가 em 단위 너비로 반영되어야 한다", () => {
    const blocks: Block[] = [
      {
        id: "video_upload_preview_1",
        type: "video" as any,
        props: {
          sourceUrl: "/api/video/abc123",
          align: "left",
          widthMode: "fixed",
          widthPx: 640,
          aspectRatio: "16:9",
        } as any,
      },
    ];

    const { container } = render(<PublicPageRenderer blocks={blocks} />);

    const video = container.querySelector("video") as HTMLVideoElement | null;
    expect(video).not.toBeNull();
    expect(video!.getAttribute("controls")).not.toBeNull();
    // 640px / 16 = 40em
    expect(video!.style.width).toBe("40em");
  });

  it("posterImageSrc 가 설정된 HTML5 비디오는 video 태그 poster 속성으로 렌더되어야 한다", () => {
    const blocks: Block[] = [
      {
        id: "video_poster_preview_1",
        type: "video" as any,
        props: {
          sourceUrl: "/videos/sample-preview.mp4",
          align: "center",
          widthMode: "auto",
          aspectRatio: "16:9",
          posterImageSrc: "/images/sample-poster-preview.png",
        } as any,
      },
    ];

    const { container } = render(<PublicPageRenderer blocks={blocks} />);

    const video = container.querySelector("video") as HTMLVideoElement | null;
    expect(video).not.toBeNull();
    expect(video!.getAttribute("poster")).toBe("/images/sample-poster-preview.png");
  });

  it("startTimeSec/endTimeSec 가 설정된 HTML5 비디오는 프리뷰에서도 loadedmetadata/timeupdate 로 시작/종료 범위가 적용되어야 한다", () => {
    const blocks: Block[] = [
      {
        id: "video_range_preview_1",
        type: "video" as any,
        props: {
          sourceUrl: "/videos/range-preview.mp4",
          align: "center",
          widthMode: "auto",
          aspectRatio: "16:9",
          startTimeSec: 3,
          endTimeSec: 8,
        } as any,
      },
    ];

    const { container } = render(<PublicPageRenderer blocks={blocks} />);

    const video = container.querySelector("video") as HTMLVideoElement | null;
    expect(video).not.toBeNull();

    fireEvent(video as HTMLVideoElement, new Event("loadedmetadata"));
    expect((video as HTMLVideoElement).currentTime).toBe(3);

    (video as any).pause = vi.fn();
    (video as HTMLVideoElement).currentTime = 8.2;
    fireEvent(video as HTMLVideoElement, new Event("timeupdate"));
    expect((video as any).pause).toHaveBeenCalled();
  });

  it("HTML5 비디오의 ariaLabel/titleText/captionText 는 프리뷰에서 aria-label 및 캡션 요소로 반영되어야 한다", () => {
    const blocks: Block[] = [
      {
        id: "video_a11y_preview",
        type: "video" as any,
        props: {
          sourceUrl: "/videos/a11y-preview.mp4",
          align: "center",
          widthMode: "auto",
          aspectRatio: "16:9",
          titleText: "프리뷰 접근성 타이틀",
          ariaLabel: "프리뷰 접근성 설명",
          captionText: "프리뷰 비디오 캡션입니다.",
        } as any,
      },
    ];

    const { container, getByTestId } = render(<PublicPageRenderer blocks={blocks} />);

    const video = container.querySelector("video") as HTMLVideoElement | null;
    expect(video).not.toBeNull();
    expect(video!.getAttribute("aria-label")).toBe("프리뷰 접근성 설명");

    const caption = getByTestId("preview-video-caption");
    expect(caption.textContent).toBe("프리뷰 비디오 캡션입니다.");
  });

  it("titleText 가 설정된 YouTube 비디오는 iframe title 로 반영되어야 한다", () => {
    const blocks: Block[] = [
      {
        id: "video_youtube_a11y_1",
        type: "video" as any,
        props: {
          sourceUrl: "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
          align: "center",
          widthMode: "auto",
          aspectRatio: "16:9",
          titleText: "사용자 정의 비디오 제목",
        } as any,
      },
    ];

    const { container } = render(<PublicPageRenderer blocks={blocks} />);

    const iframe = container.querySelector('iframe[title="사용자 정의 비디오 제목"]') as HTMLIFrameElement | null;
    expect(iframe).not.toBeNull();
  });

  it("비디오 카드 스타일 props(backgroundColorCustom/cardPaddingPx/borderRadiusPx)는 wrapper 의 스타일에 반영되어야 한다", () => {
    const blocks: Block[] = [
      {
        id: "video_card_preview_1",
        type: "video" as any,
        props: {
          sourceUrl: "/api/video/preview-card",
          align: "center",
          widthMode: "fixed",
          widthPx: 320,
          aspectRatio: "16:9",
          backgroundColorCustom: "#123456",
          cardPaddingPx: 32,
          borderRadiusPx: 16,
        } as any,
      },
    ];

    const { container } = render(<PublicPageRenderer blocks={blocks} />);

    const video = container.querySelector("video") as HTMLVideoElement | null;
    expect(video).not.toBeNull();
    const wrapper = video!.parentElement as HTMLElement | null;
    expect(wrapper).not.toBeNull();

    // #123456 -> rgb(18, 52, 86)
    expect(wrapper!.style.backgroundColor).toBe("rgb(18, 52, 86)");
    // 32px / 16 = 2em, 16px / 16 = 1em
    expect(wrapper!.style.padding).toBe("2em");
    expect(wrapper!.style.borderRadius).toBe("1em");
  });
});
