import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
import { render, screen, cleanup } from "@testing-library/react";
import type { Block, ProjectConfig } from "@/features/editor/state/editorStore";
import EditorPage from "@/app/editor/page";
import { createHeroTemplateBlocks } from "@/app/editor/templates/heroTemplate";

let mockState: any;

beforeEach(() => {
  const baseProjectConfig: ProjectConfig = {
    title: "섹션 레이아웃 테스트",
    slug: "section-layout-test",
    canvasPreset: "full",
    canvasWidthPx: 1024,
    canvasBgColorHex: "#0f172a",
    bodyBgColorHex: "#020617",
  } as ProjectConfig;

  mockState = {
    blocks: [] as Block[],
    projectConfig: baseProjectConfig,
    selectedBlockId: null as string | null,
    selectedListItemId: null as string | null,
    // 에디터 액션들은 모두 더미 함수로 채워 EditorPage 렌더링이 가능하도록 한다.
    undo: vi.fn(),
    redo: vi.fn(),
    removeBlock: vi.fn(),
    duplicateBlock: vi.fn(),
    selectBlock: vi.fn(),
    selectListItem: vi.fn(),
    addTextBlock: vi.fn(),
    addButtonBlock: vi.fn(),
    addImageBlock: vi.fn(),
    addDividerBlock: vi.fn(),
    addListBlock: vi.fn(),
    addSectionBlock: vi.fn(),
    addFormBlock: vi.fn(),
    addFormInputBlock: vi.fn(),
    addFormSelectBlock: vi.fn(),
    addFormCheckboxBlock: vi.fn(),
    addFormRadioBlock: vi.fn(),
    addHeroTemplateSection: vi.fn(),
    addFeaturesTemplateSection: vi.fn(),
    addCtaTemplateSection: vi.fn(),
    addFaqTemplateSection: vi.fn(),
    addPricingTemplateSection: vi.fn(),
    addTestimonialsTemplateSection: vi.fn(),
    addBlogTemplateSection: vi.fn(),
    addTeamTemplateSection: vi.fn(),
    addFooterTemplateSection: vi.fn(),
    updateBlock: vi.fn(),
    replaceBlocks: vi.fn(),
    reorderBlocks: vi.fn(),
    moveBlock: vi.fn(),
  };
});

afterEach(() => {
  cleanup();
});

vi.mock("@/features/editor/state/editorStore", () => {
  const useEditorStore = (selector: (state: any) => any) => selector(mockState);
  (useEditorStore as any).getState = () => mockState;

  return {
    __esModule: true,
    useEditorStore,
  };
});

vi.mock("next/link", () => {
  return {
    __esModule: true,
    default: ({ href, children }: any) => <a href={href}>{children}</a>,
  };
});

vi.mock("next/navigation", () => {
  return {
    __esModule: true,
    useRouter: () => ({
      push: vi.fn(),
    }),
    useSearchParams: () => ({
      get: () => null,
    }),
  };
});

describe("EditorPage - 섹션 레이아웃 속성", () => {
  it("backgroundColorCustom / paddingYPx / maxWidthPx / gapXPx 가 editor-section 스타일에 반영되어야 한다", () => {
    const section: Block = {
      id: "sec_layout",
      type: "section",
      props: {
        background: "default",
        paddingY: "md",
        columns: [
          { id: "sec_layout_col_1", span: 12 },
        ],
        maxWidthMode: "normal",
        gapX: "md",
        alignItems: "top",
        backgroundColorCustom: "#123456",
        paddingYPx: 80,
        maxWidthPx: 960,
        gapXPx: 32,
      },
    } as any;

    const child: Block = {
      id: "txt_1",
      type: "text",
      props: {
        text: "섹션 안 텍스트",
        align: "left",
        size: "base",
      },
      sectionId: "sec_layout",
      columnId: "sec_layout_col_1",
    } as any;

    mockState.blocks = [section, child];
    mockState.selectedBlockId = "sec_layout";

    render(<EditorPage />);

    const sectionEl = screen.getByTestId("editor-section") as HTMLElement;
    // 배경색: #123456 → rgb(18, 52, 86)
    expect(sectionEl.style.backgroundColor).toBe("rgb(18, 52, 86)");
    // 세로 패딩(px)이 스타일에 반영되어야 한다.
    expect(sectionEl.style.paddingTop).toBe("80px");
    expect(sectionEl.style.paddingBottom).toBe("80px");

    // 내부 maxWidth
    const inner = sectionEl.querySelector("div.mx-auto") as HTMLElement;
    expect(inner).toBeTruthy();
    expect(inner.style.maxWidth).toBe("960px");

    // 컬럼 간 간격(gapXPx)
    const columns = sectionEl.querySelector("div.flex") as HTMLElement;
    expect(columns).toBeTruthy();
    expect(columns.style.columnGap).toBe("32px");
  });

  it("alignItems 값에 따라 섹션 컬럼 컨테이너가 items-*- 정렬 클래스를 가져야 한다", () => {
    const section: Block = {
      id: "sec_align",
      type: "section",
      props: {
        background: "default",
        paddingY: "md",
        columns: [
          { id: "sec_align_col_1", span: 12 },
        ],
        maxWidthMode: "normal",
        gapX: "md",
        alignItems: "center",
      },
    } as any;

    const child: Block = {
      id: "txt_align",
      type: "text",
      props: {
        text: "세로 정렬 테스트",
        align: "left",
        size: "base",
      },
      sectionId: "sec_align",
      columnId: "sec_align_col_1",
    } as any;

    mockState.blocks = [section, child];
    mockState.selectedBlockId = "sec_align";

    render(<EditorPage />);

    const sectionEl = screen.getByTestId("editor-section") as HTMLElement;
    const columns = sectionEl.querySelector("div.flex") as HTMLElement;
    expect(columns).toBeTruthy();
    // alignItems="center" 인 경우 items-center 클래스가 포함되어야 한다.
    expect(columns.className).toContain("items-center");
  });

  it("Hero 템플릿 섹션의 레이아웃 속성이 EditorPage 섹션 렌더에 반영되어야 한다", () => {
    const sectionId = "hero_section_layout";
    const createId = (() => {
      let i = 0;
      return () => `hero_${++i}`;
    })();

    const { blocks } = createHeroTemplateBlocks({ sectionId, createId });

    mockState.blocks = blocks as Block[];
    mockState.selectedBlockId = sectionId;

    render(<EditorPage />);

    const sectionEl = screen.getByTestId("editor-section") as HTMLElement;
    // Hero 템플릿 배경색(#020617)과 패딩, 최대 폭, gap 이 에디터 섹션에도 반영되어야 한다.
    expect(sectionEl.style.backgroundColor).toBe("rgb(2, 6, 23)");
    expect(sectionEl.style.paddingTop).toBe("96px");
    expect(sectionEl.style.paddingBottom).toBe("96px");

    const inner = sectionEl.querySelector("div.mx-auto") as HTMLElement;
    expect(inner.style.maxWidth).toBe("960px");

    const columns = sectionEl.querySelector("div.flex") as HTMLElement;
    expect(columns.style.columnGap).toBe("40px");
  });
});
