import { describe, it, expect } from "vitest";
import React from "react";
import ReactDOMServer from "react-dom/server";

import type { Block, ProjectConfig } from "@/features/editor/state/editorStore";
import { PublicPageRenderer } from "@/features/editor/components/PublicPageRenderer";
import { buildStaticHtml } from "@/app/api/export/route";

describe("프리뷰와 정적 내보내기 일치 (고수준)", () => {
  it("여러 블록이 섞인 페이지에서 핵심 텍스트는 프리뷰와 정적 HTML 모두에 존재해야 한다", () => {
    const blocks: Block[] = [
      {
        id: "text_root",
        type: "text",
        props: {
          text: "텍스트 블록",
          align: "left",
          size: "base",
        },
      } as any,
      {
        id: "btn_root",
        type: "button",
        props: {
          label: "버튼 A",
          href: "#",
          align: "center",
        },
      } as any,
      {
        id: "img_root",
        type: "image",
        props: {
          src: "/api/image/sample-id",
          alt: "이미지 설명",
          align: "center",
          widthMode: "auto",
          borderRadius: "md",
        },
      } as any,
      {
        id: "sec_1",
        type: "section",
        props: {
          background: "primary",
          paddingY: "lg",
          columns: [
            {
              id: "sec_1_col_1",
              span: 12,
            },
          ],
          maxWidthMode: "normal",
          gapX: "md",
          alignItems: "top",
        },
      } as any,
      {
        id: "sec_1_text",
        type: "text",
        props: {
          text: "섹션 안 텍스트",
          align: "left",
          size: "base",
        },
        sectionId: "sec_1",
        columnId: "sec_1_col_1",
      } as any,
      {
        id: "sec_1_btn",
        type: "button",
        props: {
          label: "섹션 버튼",
          href: "#",
          align: "left",
        },
        sectionId: "sec_1",
        columnId: "sec_1_col_1",
      } as any,
      {
        id: "divider_1",
        type: "divider",
        props: {
          align: "center",
          thickness: "medium",
          widthMode: "full",
        },
      } as any,
      {
        id: "list_1",
        type: "list",
        props: {
          items: ["리스트 아이템 1", "리스트 아이템 2"],
          ordered: false,
          align: "left",
        },
      } as any,
      {
        id: "form_1",
        type: "form",
        props: {
          kind: "contact",
          submitTarget: "internal",
          // v1 fallback 필드를 사용해 양쪽 렌더러가 동일한 폼 필드를 가지도록 한다.
          fields: [
            { id: "f_name", name: "name", label: "폼 이름", type: "text", required: true },
            { id: "f_email", name: "email", label: "폼 이메일", type: "email", required: true },
            { id: "f_msg", name: "message", label: "폼 메시지", type: "textarea", required: true },
          ],
          fieldIds: [],
          submitButtonId: null,
          formWidthMode: "full",
        },
      } as any,
      {
        id: "input_standalone",
        type: "formInput",
        props: {
          label: "입력(단독)",
          formFieldName: "single_input",
          required: true,
        },
      } as any,
      {
        id: "select_standalone",
        type: "formSelect",
        props: {
          label: "선택(단독)",
          formFieldName: "single_select",
          options: [
            { label: "옵션 A", value: "a" },
            { label: "옵션 B", value: "b" },
          ],
          required: false,
        },
      } as any,
      {
        id: "checkbox_standalone",
        type: "formCheckbox",
        props: {
          groupLabel: "체크 그룹",
          formFieldName: "checks",
          options: [
            { label: "체크 A", value: "a" },
            { label: "체크 B", value: "b" },
          ],
          required: false,
        },
      } as any,
      {
        id: "radio_standalone",
        type: "formRadio",
        props: {
          groupLabel: "라디오 그룹",
          formFieldName: "radios",
          options: [
            { label: "라디오 A", value: "a" },
            { label: "라디오 B", value: "b" },
          ],
          required: false,
        },
      } as any,
    ];

    const projectConfig: ProjectConfig = {
      title: "프리뷰-내보내기 고수준 테스트",
      slug: "preview-export-parity",
      canvasPreset: "full",
    };

    const previewHtml = ReactDOMServer.renderToString(
      React.createElement(PublicPageRenderer, { blocks }),
    );

    const staticHtml = buildStaticHtml(blocks, projectConfig);

    const importantStrings = [
      "텍스트 블록",
      "버튼 A",
      "이미지 설명",
      "섹션 안 텍스트",
      "섹션 버튼",
      "리스트 아이템 1",
      "입력(단독)",
      "선택(단독)",
      "체크 A",
      "라디오 A",
    ];

    for (const text of importantStrings) {
      expect(previewHtml).toContain(text);
      expect(staticHtml).toContain(text);
    }
  });

  it(
    "리스트+폼+구분선 조합에서 리스트 컨테이너와 구분선이 프리뷰/정적 HTML 모두에 존재하고, 리스트는 pb-list 클래스를 사용하며 li 에 margin-bottom 인라인 스타일을 사용하지 않아야 한다",
    () => {
      const blocks: Block[] = [
        {
          id: "divider_combo",
          type: "divider",
          props: {
            align: "center",
            thickness: "medium",
            widthMode: "full",
          },
        } as any,
        {
          id: "list_combo",
          type: "list",
          props: {
            items: ["리스트 아이템 1", "리스트 아이템 2"],
            ordered: false,
            align: "left",
          },
        } as any,
        {
          id: "form_combo",
          type: "form",
          props: {
            kind: "contact",
            submitTarget: "internal",
            // v1 fallback 필드를 사용해 양쪽 렌더러가 동일한 폼 필드를 가지도록 한다.
            fields: [
              { id: "f_name", name: "name", label: "이름", type: "text", required: true },
            ],
            fieldIds: [],
            submitButtonId: null,
            formWidthMode: "full",
          },
        } as any,
      ];

      const projectConfig: ProjectConfig = {
        title: "리스트+폼+구분선 레이아웃 테스트",
        slug: "list-form-divider-layout",
        canvasPreset: "full",
      };

      const previewHtml = ReactDOMServer.renderToString(
        React.createElement(PublicPageRenderer, { blocks }),
      );

      const staticHtml = buildStaticHtml(blocks, projectConfig);

      // 리스트 텍스트는 양쪽에 존재해야 한다.
      expect(previewHtml).toContain("리스트 아이템 1");
      expect(staticHtml).toContain("리스트 아이템 1");

      // 구분선은 프리뷰/Export 모두에 존재해야 한다.
      expect(previewHtml).toContain('data-testid="preview-divider"');
      expect(staticHtml).toContain('<hr class="pb-divider"');

      // 리스트 컨테이너는 pb-list 클래스를 사용해야 한다.
      expect(previewHtml).toContain('class="pb-list');
      expect(staticHtml).toContain('class="pb-list"');

      // 프리뷰에서는 리스트 gap 이 li 의 margin-bottom 인라인 스타일로 표현된다.
      // Export HTML 은 여전히 li 인라인 margin-bottom 을 사용하지 않고 CSS 에서 처리한다.
      expect(previewHtml).toMatch(/<li[^>]*style=\"[^\"]*margin-bottom:/);
      expect(staticHtml).not.toMatch(/<li[^>]*style=\"[^\"]*margin-bottom:/);
    },
  );
});
