"use client";

import type { ChangeEvent, ComponentPropsWithRef, ReactNode } from "react";
import { cx } from "../../utils";

export type FoxToggleSwitchSize = "lg" | "md";

/**
 * 네이티브 `<input type="checkbox">`가 받는 것을 그대로 넘겨받는다 — name·value·checked·
 * defaultChecked·disabled·required·form 등. 의미가 겹치는 것만 걷어내고 아래에서 다시 정의한다.
 * `role`도 걷어낸다 — 스위치로 읽히는 것이 이 컴포넌트의 정체라 호출부가 바꿀 값이 아니다.
 */
type NativeCheckboxProps = Omit<
  ComponentPropsWithRef<"input">,
  "type" | "role" | "size" | "className" | "children" | "hidden" | "onChange"
>;

export interface FoxToggleSwitchProps extends NativeCheckboxProps {
  size?: FoxToggleSwitchSize;
  /**
   * 스위치 옆 글자. 넘기지 않으면 영역을 렌더링하지 않는다.
   *
   * ⚠️ 생략하면 스위치를 읽어 줄 이름이 없어진다 — 그때는 `aria-label`을 함께 넘긴다
   * (네이티브 속성이라 그대로 전달된다).
   */
  label?: ReactNode;
  /**
   * 켜지거나 꺼질 때 부른다. 켜짐 여부가 첫 인자다 — 네이티브 `onChange`를 `Omit`으로
   * 걷어내고 그 자리를 대신한다(`FoxCheckbox`와 같은 방식).
   */
  onChange?: (checked: boolean, event: ChangeEvent<HTMLInputElement>) => void;
  /** 참이면 렌더하지 않는다(DOM에 남지 않는다). */
  hidden?: boolean;
  /** 배치 조정용. */
  className?: string;
}

const SIZE_CLASS: Record<FoxToggleSwitchSize, string> = {
  lg: "fox-toggle-switch--lg",
  md: "fox-toggle-switch--md",
};

/**
 * @fox 토글 스위치. 켜짐 여부는 네이티브 `<input type="checkbox">`가 소유한다.
 *
 * 체크박스와 마크업은 같지만 `role="switch"`를 얹어 "선택됨"이 아니라 "켜짐/꺼짐"으로 읽히게
 * 한다. 폼에도 체크박스처럼 참여한다 — 켜져 있으면 `value`가 함께 전송된다.
 *
 * 루트가 `<label>`이라 글자를 눌러도 바뀐다. 동그라미는 꺼짐이면 왼쪽, 켜짐이면 오른쪽이고
 * X·체크 표시를 둘 다 그려 두고 CSS가 골라 보여 준다 — 켜졌을 때만 넣으면 비제어 입력에서
 * React가 상태를 몰라 어긋난다.
 *
 * ⚠️ 스타일은 이 파일이 import하지 않는다 — 호스트 앱이 `@use "@fox/styles/components"`
 * (또는 개별 파티셜)로 한 번 불러와야 한다.
 */
export function FoxToggleSwitch({
  size = "lg",
  label,
  onChange,
  hidden = false,
  className,
  ...rest
}: FoxToggleSwitchProps) {
  if (hidden) {
    return null;
  }

  // 끌 때도 change가 뛴다. 그래서 켜짐 여부를 그대로 넘긴다.
  const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
    onChange?.(event.target.checked, event);
  };

  return (
    <label className={cx("fox-toggle-switch", SIZE_CLASS[size], className)}>
      {/* 형제 선택자(`~`)가 뒤따르는 트랙과 글자에 닿아야 하므로 맨 앞에 둔다. */}
      <input
        {...rest}
        type="checkbox"
        role="switch"
        className="fox-toggle-switch__input"
        onChange={handleChange}
      />
      <span className="fox-toggle-switch__track">
        <span className="fox-toggle-switch__thumb">
          <XMark />
          <CheckMark />
        </span>
      </span>
      {label === undefined ? null : (
        <span className="fox-toggle-switch__label">{label}</span>
      )}
    </label>
  );
}

// 시안 아이콘 둘. `fill`을 시안의 색 리터럴(#6D7882·#256EF4·#CDD1D5) 대신 `currentColor`로
// 두면 트랙 규칙이 정한 색을 그대로 물려받는다 — 시안에서 표시 색은 언제나 트랙 배경과 같은
// 값이라, 상태가 셋(꺼짐·켜짐·비활성)이어도 SVG는 한 벌로 끝난다.
// `width`·`height`를 쓰지 않는다 — 크기는 CSS가 정한다.

// 꺼짐 표시.
function XMark() {
  return (
    <i
      className="fox-toggle-switch__mark-off fox-ico fox-ico--bold fox-ico-X"
      aria-hidden="true"
    />
  );
}

// 켜짐 표시.
function CheckMark() {
  return (
    <i
      className="fox-toggle-switch__mark-on fox-ico fox-ico--bold fox-ico-Check"
      aria-hidden="true"
    />
  );
}
