import type { CSSProperties } from "react";
import type { TextBlockProps } from "@/features/editor/state/editorStore";

export type TextAlign = "left" | "center" | "right" | null | undefined;

export type TextFontSizeScale = "xs" | "sm" | "base" | "lg" | "xl" | "2xl" | "3xl";
export type TextLineHeightScale = "tight" | "snug" | "normal" | "relaxed" | "loose";
export type TextFontWeightScale = "normal" | "medium" | "semibold" | "bold";
export type TextColorPalette =
  | "default"
  | "muted"
  | "strong"
  | "accent"
  | "danger"
  | "success"
  | "warning"
  | "info"
  | "neutral";

export interface TextStyleInput {
  text?: string;
  align?: TextAlign;
  size?: "sm" | "base" | "lg" | null | undefined;
  fontSizeMode?: "scale" | "custom" | null | undefined;
  fontSizeScale?: TextFontSizeScale | null | undefined;
  fontSizeCustom?: string | null | undefined;
  lineHeightMode?: "scale" | "custom" | null | undefined;
  lineHeightScale?: TextLineHeightScale | null | undefined;
  lineHeightCustom?: string | null | undefined;
  fontWeightMode?: "scale" | "custom" | null | undefined;
  fontWeightScale?: TextFontWeightScale | null | undefined;
  fontWeightCustom?: string | number | null | undefined;
  colorMode?: "palette" | "custom" | null | undefined;
  colorPalette?: TextColorPalette | null | undefined;
  colorCustom?: string | null | undefined;
  backgroundColorCustom?: string | null | undefined;
  maxWidthMode?: "scale" | "custom" | null | undefined;
  maxWidthScale?: "none" | "prose" | "narrow" | null | undefined;
  underline?: boolean | null | undefined;
  strike?: boolean | null | undefined;
  italic?: boolean | null | undefined;
}

export interface TextPbTokens {
  alignClass: string;
  sizeClass: string;
  leadingClass: string;
  weightClass: string;
  colorClass: string;
  maxWidthClass: string;
  extraClasses: string[];
  inlineStyles: string[];
}

export function computeTextPbTokens(input: TextStyleInput): TextPbTokens {
  const align = input.align === "center" ? "center" : input.align === "right" ? "right" : "left";
  const alignClass =
    align === "center" ? "pb-text-center" : align === "right" ? "pb-text-right" : "pb-text-left";

  const fontSizeMode = input.fontSizeMode ?? "scale";
  const fallbackScale: TextFontSizeScale = input.size === "sm" ? "sm" : input.size === "lg" ? "lg" : "base";
  const fontSizeScale: TextFontSizeScale = (input.fontSizeScale as TextFontSizeScale | null) ?? fallbackScale;

  const fontSizeMap: Record<TextFontSizeScale, string> = {
    xs: "pb-text-xs",
    sm: "pb-text-sm",
    base: "pb-text-base",
    lg: "pb-text-lg",
    xl: "pb-text-xl",
    "2xl": "pb-text-2xl",
    "3xl": "pb-text-3xl",
  };

  const sizeClass =
    fontSizeMode === "scale" && fontSizeScale && fontSizeMap[fontSizeScale]
      ? fontSizeMap[fontSizeScale]
      : "";

  const lineHeightMode = input.lineHeightMode ?? "scale";
  const lineHeightScale: TextLineHeightScale = (input.lineHeightScale as TextLineHeightScale | null) ?? "normal";
  const leadingMap: Record<TextLineHeightScale, string> = {
    tight: "pb-leading-tight",
    snug: "pb-leading-snug",
    normal: "pb-leading-normal",
    relaxed: "pb-leading-relaxed",
    loose: "pb-leading-loose",
  };

  const leadingClass =
    lineHeightMode === "scale" && lineHeightScale && leadingMap[lineHeightScale]
      ? leadingMap[lineHeightScale]
      : "";

  const fontWeightMode = input.fontWeightMode ?? "scale";
  const fontWeightScale: TextFontWeightScale =
    (input.fontWeightScale as TextFontWeightScale | null) ?? "normal";
  const weightMap: Record<TextFontWeightScale, string> = {
    normal: "pb-font-normal",
    medium: "pb-font-medium",
    semibold: "pb-font-semibold",
    bold: "pb-font-bold",
  };

  const weightClass =
    fontWeightMode === "scale" && fontWeightScale && weightMap[fontWeightScale]
      ? weightMap[fontWeightScale]
      : "";

  let colorClass = "pb-text-color-strong";
  const inlineStyles: string[] = [];

  if (input.colorMode === "palette") {
    const palette: TextColorPalette = (input.colorPalette as TextColorPalette | null) ?? "default";
    const paletteMap: Record<TextColorPalette, string> = {
      default: "pb-text-color-default",
      muted: "pb-text-color-muted",
      strong: "pb-text-color-strong",
      accent: "pb-text-color-accent",
      danger: "pb-text-color-danger",
      success: "pb-text-color-success",
      warning: "pb-text-color-warning",
      info: "pb-text-color-info",
      neutral: "pb-text-color-neutral",
    };
    colorClass = paletteMap[palette] ?? colorClass;
  } else if (input.colorMode === "custom" && input.colorCustom && input.colorCustom.trim() !== "") {
    inlineStyles.push(`color:${input.colorCustom.trim()}`);
  }

  if (input.backgroundColorCustom && input.backgroundColorCustom.trim() !== "") {
    inlineStyles.push(`background-color:${input.backgroundColorCustom.trim()}`);
  }

  let maxWidthClass = "";
  const maxWidthMode = input.maxWidthMode ?? "scale";
  const maxWidthScale = input.maxWidthScale ?? "none";
  if (maxWidthMode === "scale") {
    if (maxWidthScale === "prose") {
      maxWidthClass = "pb-text-maxw-prose";
    } else if (maxWidthScale === "narrow") {
      maxWidthClass = "pb-text-maxw-narrow";
    }
  }

  const extraClasses: string[] = ["pb-whitespace-pre-wrap"];
  if (input.underline) extraClasses.push("pb-underline");
  if (input.strike) extraClasses.push("pb-line-through");
  if (input.italic) extraClasses.push("pb-italic");

  return {
    alignClass,
    sizeClass,
    leadingClass,
    weightClass,
    colorClass,
    maxWidthClass,
    extraClasses,
    inlineStyles,
  };
}

export interface TextEditorTokens {
  alignClass: string;
  sizeClass: string;
  leadingClass: string;
  weightClass: string;
  colorClass: string;
  maxWidthClass: string;
  decorationClass: string;
  styleOverrides: CSSProperties;
}

export function computeTextEditorTokens(props: TextBlockProps): TextEditorTokens {
  let alignClass = "";
  let sizeClass = "";
  let leadingClass = "";
  let weightClass = "";
  let colorClass = "";
  let maxWidthClass = "";
  let decorationClass = "";
  const styleOverrides: CSSProperties = {};

  // 정렬: pb-text-*
  alignClass =
    props.align === "center"
      ? "pb-text-center"
      : props.align === "right"
        ? "pb-text-right"
        : "pb-text-left";

  // 폰트 크기: scale/custom + 기존 size 값 fallback
  const fontSizeMode = props.fontSizeMode ?? "scale";
  const fallbackScale = props.size === "sm" ? "sm" : props.size === "lg" ? "lg" : "base";
  const fontSizeScale = props.fontSizeScale ?? fallbackScale;

  // 스케일/커스텀 모드와 무관하게 pb-text-* 스케일 클래스는 항상 유지한다.
  sizeClass = `pb-text-${fontSizeScale}`;

  // custom 모드에서는 inline 스타일로 실제 폰트 크기를 덮어쓴다.
  if (fontSizeMode === "custom" && props.fontSizeCustom && props.fontSizeCustom.trim() !== "") {
    styleOverrides.fontSize = props.fontSizeCustom;
  }

  // 줄 간격: scale/custom
  const lineHeightMode = props.lineHeightMode ?? "scale";
  const lineHeightScale = props.lineHeightScale ?? "normal";
  if (lineHeightMode === "scale") {
    leadingClass = `pb-leading-${lineHeightScale}`;
  } else if (lineHeightMode === "custom" && props.lineHeightCustom && props.lineHeightCustom.trim() !== "") {
    styleOverrides.lineHeight = props.lineHeightCustom;
  }

  // 굵기: scale/custom
  const fontWeightMode = props.fontWeightMode ?? "scale";
  const fontWeightScale = props.fontWeightScale ?? "normal";
  if (fontWeightMode === "scale") {
    weightClass = `pb-font-${fontWeightScale}`;
  } else if (fontWeightMode === "custom" && props.fontWeightCustom && String(props.fontWeightCustom).trim() !== "") {
    styleOverrides.fontWeight = props.fontWeightCustom as CSSProperties["fontWeight"];
  }

  // 색상: colorCustom이 있으면 항상 우선 사용, 없으면 팔레트
  const colorPalette = props.colorPalette ?? "default";
  if (props.colorCustom && props.colorCustom.trim() !== "") {
    styleOverrides.color = props.colorCustom.trim();
  } else {
    colorClass = `pb-text-color-${colorPalette}`;
  }

  // 블록 배경색: backgroundColorCustom 이 설정된 경우 편집기 텍스트 컨테이너 배경에도 반영한다.
  if (props.backgroundColorCustom && props.backgroundColorCustom.trim() !== "") {
    styleOverrides.backgroundColor = props.backgroundColorCustom.trim();
  }

  // 최대 너비: 커스텀 값이 있으면 우선 사용, 없으면 scale 프리셋
  const maxWidthScale = props.maxWidthScale ?? "none";
  if (props.maxWidthCustom && props.maxWidthCustom.trim() !== "") {
    styleOverrides.maxWidth = props.maxWidthCustom.trim();
  } else if (maxWidthScale === "prose") {
    maxWidthClass = "pb-text-maxw-prose";
  } else if (maxWidthScale === "narrow") {
    maxWidthClass = "pb-text-maxw-narrow";
  }

  // 글자 간격: 커스텀 값이 있으면 em 단위 그대로 사용
  if (props.letterSpacingCustom && props.letterSpacingCustom.trim() !== "") {
    styleOverrides.letterSpacing = props.letterSpacingCustom.trim();
  }

  // 텍스트 장식: 밑줄/가운데줄/이탤릭
  if (props.underline) {
    decorationClass += " pb-underline";
  }
  if (props.strike) {
    decorationClass += " pb-line-through";
  }
  if (props.italic) {
    decorationClass += " pb-italic";
  }

  return {
    alignClass,
    sizeClass,
    leadingClass,
    weightClass,
    colorClass,
    maxWidthClass,
    decorationClass,
    styleOverrides,
  };
}

export interface TextPublicTokens {
  alignClass: string;
  sizeClass: string;
  styleOverrides: CSSProperties;
}

const pxToEm = (px: number, base = 16) => `${px / base}em`;

const convertPxStringToEm = (value?: string | null) => {
  if (!value) return null;
  const match = value.trim().match(/-?\d+(?:\.\d+)?/);
  if (!match) return null;
  const px = parseFloat(match[0]);
  if (!Number.isFinite(px)) return null;
  return pxToEm(px);
};

export function computeTextPublicTokens(props: TextBlockProps): TextPublicTokens {
  const alignClass =
    props.align === "center"
      ? "text-center"
      : props.align === "right"
        ? "text-right"
        : "text-left";

  const fontSizeMode = props.fontSizeMode ?? "scale";
  const fallbackScale = props.size === "sm" ? "sm" : props.size === "lg" ? "lg" : "base";
  const fontSizeScale = props.fontSizeScale ?? fallbackScale;

  const fontSizeScaleToClass: Record<string, string> = {
    xs: "text-xs",
    sm: "text-sm",
    base: "text-base",
    lg: "text-lg",
    xl: "text-xl",
    "2xl": "text-2xl",
    "3xl": "text-3xl",
  };

  let sizeClass = "";
  const styleOverrides: CSSProperties = {};

  if (fontSizeMode === "scale" && fontSizeScale && fontSizeScaleToClass[fontSizeScale]) {
    sizeClass = fontSizeScaleToClass[fontSizeScale];
  } else if (
    fontSizeMode === "custom" &&
    props.fontSizeCustom &&
    props.fontSizeCustom.trim() !== ""
  ) {
    const fontSizeValue = props.fontSizeCustom.trim();
    if (fontSizeValue.endsWith("px")) {
      const fontSizeEm = convertPxStringToEm(fontSizeValue);
      if (fontSizeEm) {
        styleOverrides.fontSize = fontSizeEm;
      }
    } else {
      styleOverrides.fontSize = fontSizeValue;
    }
  }

  if (props.colorCustom && props.colorCustom.trim() !== "") {
    styleOverrides.color = props.colorCustom.trim();
  }

  if (props.backgroundColorCustom && props.backgroundColorCustom.trim() !== "") {
    styleOverrides.backgroundColor = props.backgroundColorCustom.trim();
  }

  if (props.lineHeightCustom && props.lineHeightCustom.trim() !== "") {
    const lineHeightValue = props.lineHeightCustom.trim();
    if (lineHeightValue.endsWith("px")) {
      const lineHeightEm = convertPxStringToEm(lineHeightValue);
      if (lineHeightEm) {
        styleOverrides.lineHeight = lineHeightEm;
      }
    } else {
      styleOverrides.lineHeight = lineHeightValue;
    }
  }

  if (props.letterSpacingCustom && props.letterSpacingCustom.trim() !== "") {
    const letterSpacingValue = props.letterSpacingCustom.trim();
    if (letterSpacingValue.endsWith("px")) {
      const letterSpacingEm = convertPxStringToEm(letterSpacingValue);
      if (letterSpacingEm) {
        styleOverrides.letterSpacing = letterSpacingEm;
      }
    } else {
      styleOverrides.letterSpacing = letterSpacingValue;
    }
  }

  return {
    alignClass,
    sizeClass,
    styleOverrides,
  };
}
