import { describe, it, expect } from "vitest";
import { expectNoPxInStyleObject, expectNoPxInStyleParts } from "./styleInvariants";
import {
  computeTextPbTokens,
  computeTextEditorTokens,
  computeTextPublicTokens,
} from "@/features/editor/utils/textHelpers";
import type { TextBlockProps } from "@/features/editor/state/editorStore";

const baseProps = {
  text: "텍스트",
  align: "left" as const,
  size: "base" as const,
};

describe("textHelpers.computeTextPbTokens", () => {
  it("기본 텍스트는 pb-text-left / pb-text-base / pb-leading-normal / pb-font-normal / pb-text-color-strong / pb-whitespace-pre-wrap 를 포함해야 한다", () => {
    const tokens = computeTextPbTokens(baseProps);

    expect(tokens.alignClass).toBe("pb-text-left");
    expect(tokens.sizeClass).toBe("pb-text-base");
    expect(tokens.leadingClass).toBe("pb-leading-normal");
    expect(tokens.weightClass).toBe("pb-font-normal");
    expect(tokens.colorClass).toBe("pb-text-color-strong");
    expect(tokens.extraClasses).toContain("pb-whitespace-pre-wrap");
  });

  it("스케일 모드 텍스트는 폰트/라인하이트/굵기 스케일 토큰을 올바르게 매핑해야 한다", () => {
    const tokens = computeTextPbTokens({
      ...baseProps,
      align: "center",
      fontSizeMode: "scale",
      fontSizeScale: "lg",
      lineHeightMode: "scale",
      lineHeightScale: "relaxed",
      fontWeightMode: "scale",
      fontWeightScale: "semibold",
      colorMode: "palette",
      colorPalette: "strong",
      underline: true,
      italic: true,
    });

    expect(tokens.alignClass).toBe("pb-text-center");
    expect(tokens.sizeClass).toBe("pb-text-lg");
    expect(tokens.leadingClass).toBe("pb-leading-relaxed");
    expect(tokens.weightClass).toBe("pb-font-semibold");
    expect(tokens.colorClass).toBe("pb-text-color-strong");
    expect(tokens.extraClasses).toContain("pb-underline");
    expect(tokens.extraClasses).toContain("pb-italic");
  });

  it("커스텀 색상과 배경색은 inlineStyles 에 color/background-color 로 포함되어야 한다", () => {
    const tokens = computeTextPbTokens({
      ...baseProps,
      colorMode: "custom",
      colorCustom: "#ff0000",
      backgroundColorCustom: "#123456",
    });

    expect(tokens.inlineStyles).toContain("color:#ff0000");
    expect(tokens.inlineStyles).toContain("background-color:#123456");
  });

  it("maxWidthScale 가 prose/narrow 인 경우 pb-text-maxw-* 클래스를 포함해야 한다", () => {
    const prose = computeTextPbTokens({ ...baseProps, maxWidthMode: "scale", maxWidthScale: "prose" });
    const narrow = computeTextPbTokens({ ...baseProps, maxWidthMode: "scale", maxWidthScale: "narrow" });

    expect(prose.maxWidthClass).toBe("pb-text-maxw-prose");
    expect(narrow.maxWidthClass).toBe("pb-text-maxw-narrow");
  });

  it("텍스트 Pb inlineStyles 에는 px 단위 값이 포함되지 않아야 한다", () => {
    const tokens = computeTextPbTokens({
      ...baseProps,
      colorMode: "custom",
      colorCustom: "#ff0000",
      backgroundColorCustom: "#123456",
    });

    expectNoPxInStyleParts(tokens.inlineStyles);
  });
});

describe("textHelpers.computeTextEditorTokens", () => {
  const baseBlockProps: TextBlockProps = {
    text: "텍스트",
    align: "left",
    size: "base",
  } as TextBlockProps;

  it("기본 텍스트는 pb-text-left / pb-text-base / pb-leading-normal / pb-font-normal / pb-text-color-default 를 사용해야 한다", () => {
    const tokens = computeTextEditorTokens(baseBlockProps);

    expect(tokens.alignClass).toBe("pb-text-left");
    expect(tokens.sizeClass).toBe("pb-text-base");
    expect(tokens.leadingClass).toBe("pb-leading-normal");
    expect(tokens.weightClass).toBe("pb-font-normal");
    expect(tokens.colorClass).toBe("pb-text-color-default");
    expect(tokens.styleOverrides.color).toBeUndefined();
  });

  it("colorCustom / backgroundColorCustom / maxWidthCustom 이 styleOverrides 에 반영되어야 한다", () => {
    const tokens = computeTextEditorTokens({
      ...baseBlockProps,
      align: "center",
      colorCustom: "#ff0000",
      backgroundColorCustom: "#123456",
      maxWidthCustom: "320px",
    } as TextBlockProps);

    expect(tokens.alignClass).toBe("pb-text-center");
    expect(tokens.styleOverrides.color).toBe("#ff0000");
    expect(tokens.styleOverrides.backgroundColor).toBe("#123456");
    expect(tokens.styleOverrides.maxWidth).toBe("320px");
  });
});

describe("textHelpers.computeTextPublicTokens", () => {
  const baseBlockProps: TextBlockProps = {
    text: "텍스트",
    align: "left",
    size: "base",
  } as TextBlockProps;

  it("기본 텍스트는 text-left / text-base 를 사용하고 색상/배경 styleOverrides 는 없어야 한다", () => {
    const tokens = computeTextPublicTokens(baseBlockProps);

    expect(tokens.alignClass).toBe("text-left");
    expect(tokens.sizeClass).toBe("text-base");
    expect(tokens.styleOverrides.color).toBeUndefined();
    expect(tokens.styleOverrides.backgroundColor).toBeUndefined();
  });

  it("fontSizeMode=custom 인 경우 sizeClass 는 비워지고 styleOverrides.fontSize 에 값이 설정되어야 한다", () => {
    const tokens = computeTextPublicTokens({
      ...baseBlockProps,
      fontSizeMode: "custom",
      fontSizeCustom: "24px",
    } as TextBlockProps);

    expect(tokens.sizeClass).toBe("");
    expect(tokens.styleOverrides.fontSize).toBe("1.5em");
  });

  it("colorCustom / backgroundColorCustom 이 styleOverrides 에 반영되어야 한다", () => {
    const tokens = computeTextPublicTokens({
      ...baseBlockProps,
      colorCustom: "#ff0000",
      backgroundColorCustom: "#123456",
    } as TextBlockProps);

    expect(tokens.styleOverrides.color).toBe("#ff0000");
    expect(tokens.styleOverrides.backgroundColor).toBe("#123456");
  });

  it("lineHeightCustom / letterSpacingCustom \uc774 px \uc778 \uacbd\uc6b0 em \ub2e8\uc704 \uc2a4\ud0c0\uc77c\ub85c \ubcc0\ud658\ub418\uc5b4\uc57c \ud55c\ub2e4", () => {
    const tokens = computeTextPublicTokens({
      ...baseBlockProps,
      lineHeightCustom: "24px",
      letterSpacingCustom: "2px",
    } as TextBlockProps);

    expect(tokens.styleOverrides.lineHeight).toBe("1.5em");
    expect(tokens.styleOverrides.letterSpacing).toBe("0.125em");
  });

  it("퍼블릭 텍스트 styleOverrides 에 px 단위 값이 포함되지 않아야 한다", () => {
    const tokens = computeTextPublicTokens({
      ...baseBlockProps,
      fontSizeMode: "custom",
      fontSizeCustom: "24px",
      lineHeightCustom: "24px",
      letterSpacingCustom: "2px",
      colorCustom: "#ff0000",
      backgroundColorCustom: "#123456",
    } as TextBlockProps);

    expectNoPxInStyleObject(tokens.styleOverrides);
  });
});
