"use client";

import {
  Children,
  Fragment,
  cloneElement,
  isValidElement,
  type ReactElement,
  type ReactNode,
} from "react";
import { cx } from "../../utils";

export type FoxButtonGroupOrientation = "horizontal" | "vertical";
export type FoxButtonGroupAlign = "start" | "center" | "end";
export type FoxButtonGroupSize = "lg" | "md" | "sm" | "xsm";

export interface FoxButtonGroupProps {
  orientation?: FoxButtonGroupOrientation;
  /** 주축 정렬. 세로에서는 그룹 높이가 정해져 있을 때만 눈에 띈다. */
  align?: FoxButtonGroupAlign;
  /** 자식 버튼의 `size`를 전부 이 값으로 덮어쓴다. 자식이 따로 준 값은 무시된다. */
  size: FoxButtonGroupSize;
  wrap?: boolean;
  /** 배치 조정용. */
  className?: string;
  children?: ReactNode;
}

const ORIENTATION_CLASS: Record<FoxButtonGroupOrientation, string> = {
  horizontal: "fox-button-group--horizontal",
  vertical: "fox-button-group--vertical",
};

const ALIGN_CLASS: Record<FoxButtonGroupAlign, string> = {
  start: "fox-button-group--start",
  center: "fox-button-group--center",
  end: "fox-button-group--end",
};

type Overrides = { size: FoxButtonGroupSize; fullWidth?: true };

/**
 * 자식 버튼에 그룹 값을 강제로 덮어쓴다.
 *
 * - 호스트 요소(`div` 등)는 건드리지 않는다 — DOM에 없는 속성이 넘어가면 React가 경고한다.
 * - `Children.map`은 프래그먼트 안으로 들어가지 않아 직접 내려간다. 그러지 않으면
 *   `<>…</>`로 감싼 버튼들이 덮어쓰기를 피해 가고 Fragment에 `size`가 붙어 경고가 난다.
 */
function overrideChildren(children: ReactNode, overrides: Overrides): ReactNode {
  return Children.map(children, (child) => {
    if (!isValidElement(child)) {
      return child;
    }

    if (child.type === Fragment) {
      const fragment = child as ReactElement<{ children?: ReactNode }>;
      return overrideChildren(fragment.props.children, overrides);
    }

    if (typeof child.type === "string") {
      return child;
    }

    return cloneElement(child as ReactElement<Record<string, unknown>>, overrides);
  });
}

/**
 * @fox 버튼 묶음. 간격·방향·정렬만 책임지고 상태를 갖지 않는다.
 *
 * 크기는 **그룹이 단일 진실 공급원**이다 — 자식이 저마다 다른 `size`를 줘도 그룹 값으로
 * 통일된다. 세로일 때는 자식이 항상 폭을 채운다.
 *
 * ⚠️ 스타일은 이 파일이 import하지 않는다 — 호스트 앱이 `@use "@fox/styles/components"`
 * (또는 개별 파티셜)로 한 번 불러와야 한다.
 */
export function FoxButtonGroup({
  orientation = "horizontal",
  align = "start",
  size,
  wrap = false,
  className,
  children,
}: FoxButtonGroupProps) {
  const overrides: Overrides =
    orientation === "vertical" ? { size, fullWidth: true } : { size };

  return (
    <div
      className={cx(
        "fox-button-group",
        ORIENTATION_CLASS[orientation],
        ALIGN_CLASS[align],
        wrap && "fox-button-group--wrap",
        className
      )}
    >
      {overrideChildren(children, overrides)}
    </div>
  );
}
