import { describe, it, expect, vi, afterEach } from "vitest";
import { render, screen, fireEvent, cleanup } from "@testing-library/react";
import { DividerPropertiesPanel } from "@/app/editor/panels/DividerPropertiesPanel";
import type { DividerBlockProps } from "@/features/editor/state/editorStore";

// DividerPropertiesPanel 컨트롤 TDD
// - 정렬/두께 select 변경 시 updateBlock 이 올바른 필드로 호출되는지
// - 색상 HEX 인풋 변경 시 colorHex 로 호출되는지
// - 위/아래 여백 커스텀(px) 입력 시 marginYPx 로 호출되는지

describe("DividerPropertiesPanel", () => {
  const baseProps: DividerBlockProps = {
    align: "left",
    thickness: "thin",
    widthMode: "full",
    colorHex: "#475569",
    marginY: "md",
  };

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

  it("정렬 select 변경 시 updateBlock 이 align 으로 호출되어야 한다", () => {
    const updateBlock = vi.fn();

    render(
      <DividerPropertiesPanel
        dividerProps={baseProps}
        selectedBlockId="divider-1"
        updateBlock={updateBlock}
      />,
    );

    const select = screen.getByLabelText("Divider alignment");
    fireEvent.change(select, { target: { value: "center" } });

    expect(updateBlock).toHaveBeenCalledWith(
      "divider-1",
      expect.objectContaining({ align: "center" }),
    );
  });

  it("두께 select 변경 시 updateBlock 이 thickness 로 호출되어야 한다", () => {
    const updateBlock = vi.fn();

    render(
      <DividerPropertiesPanel
        dividerProps={baseProps}
        selectedBlockId="divider-2"
        updateBlock={updateBlock}
      />,
    );

    const select = screen.getByLabelText("Divider thickness");
    fireEvent.change(select, { target: { value: "medium" } });

    expect(updateBlock).toHaveBeenCalledWith(
      "divider-2",
      expect.objectContaining({ thickness: "medium" }),
    );
  });

  it("길이 모드 select 변경 시 updateBlock 이 widthMode 로 호출되어야 한다", () => {
    const updateBlock = vi.fn();

    render(
      <DividerPropertiesPanel
        dividerProps={{ ...baseProps, widthMode: "full" }}
        selectedBlockId="divider-5"
        updateBlock={updateBlock}
      />,
    );

    const select = screen.getByLabelText("Divider length mode");
    fireEvent.change(select, { target: { value: "fixed" } });

    expect(updateBlock).toHaveBeenCalledWith(
      "divider-5",
      expect.objectContaining({ widthMode: "fixed" }),
    );
  });

  it("고정 길이 커스텀 인풋 변경 시 updateBlock 이 widthPx 로 호출되어야 한다", () => {
    const updateBlock = vi.fn();

    render(
      <DividerPropertiesPanel
        dividerProps={{ ...baseProps, widthMode: "fixed", widthPx: 320 }}
        selectedBlockId="divider-6"
        updateBlock={updateBlock}
      />,
    );

    const widthInput = screen.getByLabelText("Fixed length 커스텀");
    fireEvent.change(widthInput, { target: { value: "480" } });

    expect(updateBlock).toHaveBeenCalledWith(
      "divider-6",
      expect.objectContaining({ widthPx: 480 }),
    );
  });

  it("색상 HEX 인풋 변경 시 updateBlock 이 colorHex 로 호출되어야 한다", () => {
    const updateBlock = vi.fn();

    render(
      <DividerPropertiesPanel
        dividerProps={{ ...baseProps, colorHex: "#111111" }}
        selectedBlockId="divider-3"
        updateBlock={updateBlock}
      />,
    );

    const hexInputs = screen.getAllByLabelText("Divider color HEX");
    const hexInput = hexInputs[0] as HTMLInputElement;
    fireEvent.change(hexInput, { target: { value: "#123456" } });

    expect(updateBlock).toHaveBeenCalledWith(
      "divider-3",
      expect.objectContaining({ colorHex: "#123456" }),
    );
  });

  it("위/아래 여백 커스텀 인풋 변경 시 updateBlock 이 marginYPx 로 호출되어야 한다", () => {
    const updateBlock = vi.fn();

    render(
      <DividerPropertiesPanel
        dividerProps={baseProps}
        selectedBlockId="divider-4"
        updateBlock={updateBlock}
      />,
    );

    const marginInputs = screen.getAllByLabelText("Vertical margin 커스텀");
    const marginInput = marginInputs[0] as HTMLInputElement;

    fireEvent.change(marginInput, { target: { value: "24" } });

    expect(updateBlock).toHaveBeenCalledWith(
      "divider-4",
      expect.objectContaining({ marginYPx: 24 }),
    );
  });

  it("DividerPropertiesPanel 주요 셀렉트 컨트롤은 라이트/다크 듀얼 테마 크롬을 사용해야 한다", () => {
    const updateBlock = vi.fn();

    render(
      <DividerPropertiesPanel
        dividerProps={baseProps}
        selectedBlockId="divider-theme-1"
        updateBlock={updateBlock}
      />,
    );

    const alignSelect = screen.getByLabelText("Divider alignment") as HTMLSelectElement;
    const alignClass = alignSelect.getAttribute("class") ?? "";
    expect(alignClass).toContain("bg-white");
    expect(alignClass).toContain("text-slate-900");
    expect(alignClass).toContain("border-slate-300");
    expect(alignClass).toContain("dark:bg-slate-900");
    expect(alignClass).toContain("dark:text-slate-100");
    expect(alignClass).toContain("dark:border-slate-700");

    const thicknessSelect = screen.getByLabelText("Divider thickness") as HTMLSelectElement;
    const thicknessClass = thicknessSelect.getAttribute("class") ?? "";
    expect(thicknessClass).toContain("bg-white");
    expect(thicknessClass).toContain("text-slate-900");
    expect(thicknessClass).toContain("border-slate-300");
    expect(thicknessClass).toContain("dark:bg-slate-900");
    expect(thicknessClass).toContain("dark:text-slate-100");
    expect(thicknessClass).toContain("dark:border-slate-700");

    const widthModeSelect = screen.getByLabelText("Divider length mode") as HTMLSelectElement;
    const widthModeClass = widthModeSelect.getAttribute("class") ?? "";
    expect(widthModeClass).toContain("bg-white");
    expect(widthModeClass).toContain("text-slate-900");
    expect(widthModeClass).toContain("border-slate-300");
    expect(widthModeClass).toContain("dark:bg-slate-900");
    expect(widthModeClass).toContain("dark:text-slate-100");
    expect(widthModeClass).toContain("dark:border-slate-700");
  });
});
