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";

let mockState: any;

beforeEach(() => {
  const baseProjectConfig: ProjectConfig = {
    title: "버튼 블록 스타일 테스트",
    slug: "editor-button-style-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,
    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("크기/변형/색상/패딩/텍스트 정렬이 에디터 버튼 렌더에 반영되어야 한다", () => {
    const blocks: Block[] = [
      {
        id: "btn_style_1",
        type: "button",
        props: {
          label: "테스트 버튼",
          href: "#",
          align: "center",
          size: "lg",
          variant: "outline",
          colorPalette: "success",
          borderRadius: "full",
          fullWidth: true,
          fontSizeCustom: "18px",
          lineHeightCustom: "1.8",
          letterSpacingCustom: "0.1em",
          fillColorCustom: "#123456",
          strokeColorCustom: "#654321",
          textColorCustom: "#ff0000",
          paddingX: 16,
          paddingY: 10,
        },
      } as any,
    ];

    mockState.blocks = blocks;
    mockState.selectedBlockId = "btn_style_1";

    render(<EditorPage />);

    const editorBlock = screen.getByTestId("editor-block") as HTMLElement;
    const button = screen.getByRole("button", { name: "테스트 버튼" }) as HTMLButtonElement;

    // 정렬: align="center" → editor-block 에 pb-text-center 클래스
    expect(editorBlock.className).toContain("pb-text-center");

    // 버튼 클래스: 크기/변형/둥글기 토큰이 pb-btn-* 클래스로 반영되어야 한다.
    expect(button.className).toContain("pb-btn-base");
    expect(button.className).toContain("pb-btn-size-lg");
    expect(button.className).toContain("pb-btn-radius-full");
    expect(button.className).toContain("pb-btn-variant-outline-success");

    // fullWidth=true 인 경우, 래퍼 div 가 w-full 클래스를 가져야 한다.
    const wrapper = button.parentElement as HTMLElement;
    expect(wrapper.className).toContain("w-full");

    // 스타일: 색상/패딩/타이포
    expect(button.style.backgroundColor).toBe("rgb(18, 52, 86)"); // #123456
    expect(button.style.borderColor).toBe("rgb(101, 67, 33)"); // #654321
    expect(button.style.color).toBe("rgb(255, 0, 0)"); // #ff0000
    expect(button.style.paddingInline).toBe("16px");
    expect(button.style.paddingBlock).toBe("10px");
    expect(button.style.fontSize).toBe("18px");
    expect(button.style.lineHeight).toBe("1.8");
    expect(button.style.letterSpacing).toBe("0.1em");
  });

  it("widthMode=fixed 인 경우 widthPx 가 에디터 버튼 width 스타일에 반영되어야 한다", () => {
    const blocks: Block[] = [
      {
        id: "btn_width_fixed",
        type: "button",
        props: {
          label: "고정 너비 버튼",
          href: "#",
          align: "left",
          size: "md",
          variant: "solid",
          colorPalette: "primary",
          borderRadius: "md",
          fullWidth: false,
          widthMode: "fixed",
          widthPx: 200,
        },
      } as any,
    ];

    mockState.blocks = blocks;
    mockState.selectedBlockId = "btn_width_fixed";

    render(<EditorPage />);

    const button = screen.getByRole("button", { name: "고정 너비 버튼" }) as HTMLButtonElement;

    // widthMode="fixed" + widthPx=200 이면 버튼 style.width 가 200px 이어야 한다.
    expect(button.style.width).toBe("200px");
  });
});
