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

// FormControllerPanel 컨트롤 TDD
// - 성공/에러 메시지 인풋이 updateBlock 을 통해 FormBlockProps.successMessage / errorMessage 를 갱신하는지 검증한다.

function makeFormBlock(id: string, props: Partial<FormBlockProps> = {}): Block {
  const base: FormBlockProps = {
    kind: "contact",
    submitTarget: "internal",
    fieldIds: [],
    submitButtonId: null,
  } as any;

  return {
    id,
    type: "form",
    props: { ...base, ...props } as any,
  } as any;
}

describe("FormControllerPanel", () => {
  afterEach(() => {
    cleanup();
  });

  it("성공 메시지 인풋 변경 시 updateBlock 이 successMessage 로 호출되어야 한다", () => {
    const formBlock = makeFormBlock("form-1", {
      successMessage: "기존 성공 메시지",
    });

    const updateBlock = vi.fn();

    render(
      <FormControllerPanel
        block={formBlock}
        blocks={[formBlock]}
        selectedBlockId="form-1"
        updateBlock={updateBlock}
      />,
    );

    const input = screen.getByLabelText("성공 메시지");
    fireEvent.change(input, { target: { value: "새 성공 메시지" } });

    expect(updateBlock).toHaveBeenCalledWith(
      "form-1",
      expect.objectContaining({ successMessage: "새 성공 메시지" }),
    );
  });

  it("에러 메시지 인풋 변경 시 updateBlock 이 errorMessage 로 호출되어야 한다", () => {
    const formBlock = makeFormBlock("form-2", {
      errorMessage: "기존 에러 메시지",
    });

    const updateBlock = vi.fn();

    render(
      <FormControllerPanel
        block={formBlock}
        blocks={[formBlock]}
        selectedBlockId="form-2"
        updateBlock={updateBlock}
      />,
    );

    const input = screen.getByLabelText("에러 메시지");
    fireEvent.change(input, { target: { value: "새 에러 메시지" } });

    expect(updateBlock).toHaveBeenCalledWith(
      "form-2",
      expect.objectContaining({ errorMessage: "새 에러 메시지" }),
    );
  });

  it("폼 필드 매핑 UI 에서 필드 라벨 대신 전송 키(formFieldName)를 우선적으로 표시해야 한다", () => {
    const formBlock = makeFormBlock("form-controller", {
      fieldIds: ["input-1", "checkbox-1"],
    });

    const inputBlock: Block = {
      id: "input-1",
      type: "formInput",
      props: {
        label: "이름",
        formFieldName: "name",
      } as any,
    } as any;

    const checkboxBlock: Block = {
      id: "checkbox-1",
      type: "formCheckbox",
      props: {
        groupLabel: "옵션",
        formFieldName: "options",
        options: [],
      } as any,
    } as any;

    const updateBlock = vi.fn();

    render(
      <FormControllerPanel
        block={formBlock}
        blocks={[formBlock, inputBlock, checkboxBlock]}
        selectedBlockId="form-controller"
        updateBlock={updateBlock}
      />,
    );

    const nameLabel = screen.getByText("name (이름)");
    const optionsLabel = screen.getByText("options (옵션)");

    expect(nameLabel).toBeTruthy();
    expect(optionsLabel).toBeTruthy();
  });

  it("Submit 버튼 셀렉트에서 버튼 블록의 전송 키(formFieldName)를 기준으로 표시해야 한다", () => {
    const formBlock = makeFormBlock("form-controller", {
      submitButtonId: "btn-1",
    });

    const buttonBlock: Block = {
      id: "btn-1",
      type: "button",
      props: {
        label: "제출하기",
        formFieldName: "submit-main",
      } as any,
    } as any;

    const updateBlock = vi.fn();

    render(
      <FormControllerPanel
        block={formBlock}
        blocks={[formBlock, buttonBlock]}
        selectedBlockId="form-controller"
        updateBlock={updateBlock}
      />,
    );

    const select = screen.getByLabelText("Submit 버튼") as HTMLSelectElement;

    const submitMainOption = screen.getByText("submit-main (제출하기)");

    expect(submitMainOption).toBeTruthy();
    // 기본 선택 값은 FormBlock.submitButtonId 이어야 한다.
    expect(select.value).toBe("btn-1");
  });
});
