"use client";

import React from "react";
import { ComponentRendererProps } from "@/types/component";
import { filterDOMProps } from "@/lib/utils/domPropsFilter";
import { ButtonConfig, ButtonVariant } from "./types";

/**
 * Button — 통합 단일 버튼 컴포넌트
 *
 * 흡수 대상:
 *   - v2-button-primary (base)
 *   - button-primary (legacy)
 *   - related-data-buttons (legacy, 버튼 그룹은 여러 button 배치로 대체)
 *
 * 변형:
 *   - variant: primary / secondary / default / destructive / outline / ghost
 *   - actionType: 12종 + custom
 *   - size: sm / md / lg
 */

export interface ButtonComponentProps extends ComponentRendererProps {
  config?: ButtonConfig;
}

// variant 별 기본 스타일 (config override 가능)
const VARIANT_PRESETS: Record<
  ButtonVariant,
  { background: string; color: string; border: string }
> = {
  primary: {
    background: "hsl(var(--primary))",
    color: "hsl(var(--card))",
    border: "1px solid hsl(var(--primary))",
  },
  secondary: {
    background: "hsl(var(--muted-foreground))",
    color: "hsl(var(--card))",
    border: "1px solid hsl(var(--muted-foreground))",
  },
  default: {
    background: "hsl(var(--border))",
    color: "hsl(var(--foreground))",
    border: "1px solid hsl(var(--border))",
  },
  destructive: {
    background: "hsl(var(--destructive))",
    color: "hsl(var(--card))",
    border: "1px solid hsl(var(--destructive))",
  },
  outline: {
    background: "transparent",
    color: "hsl(var(--foreground))",
    border: "1px solid hsl(var(--border))",
  },
  ghost: {
    background: "transparent",
    color: "hsl(var(--foreground))",
    border: "1px solid transparent",
  },
};

const SIZE_PRESETS: Record<
  NonNullable<ButtonConfig["size"]>,
  { padding: string; fontSize: string; height: string }
> = {
  sm: { padding: "4px 10px", fontSize: "11px", height: "26px" },
  md: { padding: "6px 14px", fontSize: "13px", height: "32px" },
  lg: { padding: "8px 18px", fontSize: "15px", height: "40px" },
};

export const ButtonComponent: React.FC<ButtonComponentProps> = ({
  component,
  isDesignMode = false,
  isSelected = false,
  onClick,
  onDragStart,
  onDragEnd,
  config,
  className,
  style,
  ...props
}) => {
  // ─── 4경로 머지 (Phase A-2 에서 확립된 표준 패턴) ────────────────────────
  // ★ 주의: props.size 는 component 의 visual size {width, height} 객체이므로
  //   ButtonConfig.size (sm/md/lg 문자열) 와 충돌. fromProps 에 size 는 넣지
  //   않고, 문자열 여부 체크 후 사용.
  const fromProps: Partial<ButtonConfig> = {};
  const p = props as any;
  if (p.text !== undefined) fromProps.text = p.text;
  if (typeof p.variant === "string") fromProps.variant = p.variant;
  if (typeof p.actionType === "string") fromProps.actionType = p.actionType;
  if (p.confirm !== undefined) fromProps.confirm = p.confirm;
  if (typeof p.disabled === "boolean") fromProps.disabled = p.disabled;
  if (typeof p.icon === "string") fromProps.icon = p.icon;
  if (typeof p.iconPosition === "string") fromProps.iconPosition = p.iconPosition;
  if (typeof p.backgroundColor === "string")
    fromProps.backgroundColor = p.backgroundColor;
  if (typeof p.textColor === "string") fromProps.textColor = p.textColor;
  if (typeof p.borderRadius === "string") fromProps.borderRadius = p.borderRadius;

  // 2) 4경로 머지 (마지막이 최우선)
  const componentConfig = {
    ...config,
    ...((component as any).config ?? {}),
    ...((component as any).componentConfig ?? {}),
    ...fromProps,
  } as ButtonConfig;

  // ★ text/icon 은 문자열이어야 함. object 가 들어오면 React child 에러 → 방어
  const rawText = componentConfig.text;
  const text: string =
    typeof rawText === "string" || typeof rawText === "number"
      ? String(rawText)
      : "버튼";
  const variant: ButtonVariant = componentConfig.variant ?? "primary";
  // ★ componentConfig.size 는 가끔 {width, height} 객체가 섞여 올 수 있어 방어
  const sizeKey: NonNullable<ButtonConfig["size"]> =
    typeof componentConfig.size === "string" &&
    ["sm", "md", "lg"].includes(componentConfig.size)
      ? (componentConfig.size as NonNullable<ButtonConfig["size"]>)
      : "md";
  const disabled = componentConfig.disabled ?? false;
  const rawIcon = componentConfig.icon;
  const icon: string | null = typeof rawIcon === "string" ? rawIcon : null;
  const iconPosition = componentConfig.iconPosition ?? "left";

  const variantStyle = VARIANT_PRESETS[variant] ?? VARIANT_PRESETS.primary;
  const sizeStyle = SIZE_PRESETS[sizeKey] ?? SIZE_PRESETS.md;

  // 디자인 모드에서는 wrapper 박스 크기(리사이즈한 값)를 그대로 채워야
  // 디자이너 캔버스에서 박스 크기 = 시각 크기가 된다.
  //
  // 런타임에서는 두 경로가 있다:
  //   (A) component.size.{width,height} 가 유효한 px 로 넘어온 경우 (line 엔진)
  //       → design px (예: 120x40) 를 root 에 직접 적용. 버튼이 wrapper cell
  //         전체로 stretch 되지 않고 디자이너가 준 크기 그대로 렌더.
  //   (B) 그 외 (기존 band 경로 등)
  //       → content size (sizePreset 기반). 기존 회귀 방지용 기본 동작.
  const fillWrapper = isDesignMode === true;
  const rawSize = (component as any)?.size;
  const sizeW =
    typeof rawSize?.width === "number" && rawSize.width > 0 ? rawSize.width : 0;
  const sizeH =
    typeof rawSize?.height === "number" && rawSize.height > 0 ? rawSize.height : 0;
  const useDesignPx = !fillWrapper && sizeW > 0 && sizeH > 0;

  const buttonStyle: React.CSSProperties = {
    display: "inline-flex",
    alignItems: "center",
    justifyContent: "center",
    gap: "6px",
    padding: sizeStyle.padding,
    fontSize: sizeStyle.fontSize,
    minHeight: sizeStyle.height,
    fontWeight: 600,
    border: variantStyle.border,
    borderRadius: componentConfig.borderRadius ?? "6px",
    background: componentConfig.backgroundColor ?? variantStyle.background,
    color: componentConfig.textColor ?? variantStyle.color,
    cursor: disabled ? "not-allowed" : "pointer",
    opacity: disabled ? 0.5 : 1,
    transition: "opacity 0.1s, transform 0.05s",
    userSelect: "none",
    whiteSpace: "nowrap",
    ...(fillWrapper ? { width: "100%", height: "100%" } : {}),
    ...(component as any).style,
    ...style,
    // design px 는 외부 style 보다 뒤에 spread 해서 최종 승자가 되게 한다
    ...(useDesignPx
      ? {
          width: `${sizeW}px`,
          height: `${sizeH}px`,
          minHeight: `${sizeH}px`,
          flex: "0 0 auto",
        }
      : {}),
  };

  if (isDesignMode && isSelected) {
    buttonStyle.outline = "2px solid hsl(var(--primary))";
    buttonStyle.outlineOffset = "2px";
  }

  // 템플릿 컨텍스트가 내려주는 액션 콜백 — actionType 에 따라 해당 콜백 호출
  const p2 = props as any;
  const ctxOnAdd: (() => void) | undefined =
    typeof p2.onAdd === "function" ? p2.onAdd : undefined;
  const ctxOnEdit: (() => void) | undefined =
    typeof p2.onEdit === "function" ? p2.onEdit : undefined;
  const ctxOnDelete: (() => void) | undefined =
    typeof p2.onDelete === "function" ? p2.onDelete : undefined;
  const ctxOnFormSubmit: (() => void) | undefined =
    typeof p2.onFormSubmit === "function" ? p2.onFormSubmit : undefined;
  const ctxOnFormCancel: (() => void) | undefined =
    typeof p2.onFormCancel === "function" ? p2.onFormCancel : undefined;

  const handleClick = (e: React.MouseEvent) => {
    e.stopPropagation();
    if (disabled) return;
    if (isDesignMode) {
      onClick?.();
      return;
    }
    if (componentConfig.confirm && !window.confirm(componentConfig.confirm)) {
      return;
    }

    // actionType 기반 분기 — 매칭되는 게 있으면 그걸 호출하고,
    // 아니면 기존 onClick 폴백 (빌더/커스텀 경로)
    const at = componentConfig.actionType;
    switch (at) {
      case "add":
        if (ctxOnAdd) return ctxOnAdd();
        break;
      case "edit":
        if (ctxOnEdit) return ctxOnEdit();
        break;
      case "delete":
        if (ctxOnDelete) return ctxOnDelete();
        break;
      case "save":
      case "submit":
        if (ctxOnFormSubmit) return ctxOnFormSubmit();
        break;
      case "cancel":
      case "close":
        if (ctxOnFormCancel) return ctxOnFormCancel();
        break;
      // search / reset / navigate / popup / approval / custom 은 다음 단계
      default:
        break;
    }
    onClick?.();
  };

  /* eslint-disable @typescript-eslint/no-unused-vars */
  const {
    selectedScreen: _1,
    onZoneComponentDrop: _2,
    onZoneClick: _3,
    componentConfig: _4,
    component: _5,
    isSelected: _6,
    onClick: _7,
    onDragStart: _8,
    onDragEnd: _9,
    size: _10,
    position: _11,
    style: _12,
    screenId: _13,
    tableName: _14,
    onRefresh: _15,
    onClose: _16,
    web_type: _17,
    autoGeneration: _18,
    isInteractive: _19,
    formData: _20,
    onFormDataChange: _21,
    menuId: _22,
    menuObjid: _23,
    onSave: _24,
    userId: _25,
    userName: _26,
    companyCode: _27,
    isInModal: _28,
    readonly: _29,
    originalData: _30,
    _originalData: _31,
    _initialData: _32,
    _groupedData: _33,
    allComponents: _34,
    onUpdateLayout: _35,
    selectedRows: _36,
    selectedRowsData: _37,
    onSelectedRowsChange: _38,
    sortBy: _39,
    sortOrder: _40,
    tableDisplayData: _41,
    flowSelectedData: _42,
    flowSelectedStepId: _43,
    onFlowSelectedDataChange: _44,
    onConfigChange: _45,
    refreshKey: _46,
    flowRefreshKey: _47,
    onFlowRefresh: _48,
    isPreview: _49,
    groupedData: _50,
    // ★ ButtonConfig 필드 — DOM 에 spread 되면 React warning. 제외.
    text: _51,
    variant: _52,
    actionType: _53,
    confirm: _54,
    disabled: _55,
    icon: _56,
    iconPosition: _57,
    backgroundColor: _58,
    textColor: _59,
    borderRadius: _60,
    action: _61,
    displayMode: _62,
    iconTextPosition: _63,
    iconGap: _64,
    // 템플릿 컨텍스트 액션 콜백 — DOM 에 흘리지 않음
    onAdd: _65,
    onEdit: _66,
    onDelete: _67,
    onFormSubmit: _68,
    onFormCancel: _69,
    onSearch: _70,
    searchParams: _71,
    selectedRow: _72,
    view: _73,
    ...domProps
  } = props as any;
  /* eslint-enable @typescript-eslint/no-unused-vars */

  return (
    <button
      type="button"
      style={buttonStyle}
      className={className}
      onClick={handleClick}
      onDragStart={onDragStart}
      onDragEnd={onDragEnd}
      disabled={disabled}
      {...filterDOMProps(domProps)}
    >
      {icon && iconPosition === "left" && (
        <span aria-hidden>{/* TODO: lucide icon lookup (Phase F) */}{icon}</span>
      )}
      <span>{text}</span>
      {icon && iconPosition === "right" && (
        <span aria-hidden>{/* TODO: lucide icon lookup (Phase F) */}{icon}</span>
      )}
    </button>
  );
};

export const ButtonWrapper: React.FC<ButtonComponentProps> = (props) => {
  return <ButtonComponent {...props} />;
};
