/* ============================================================================
 * 서명전에 — TDS TextArea 컴포넌트 (Task #169)
 *
 *  · TextField 의 textarea 변형. label / placeholder / help / hasError / disabled
 *    구조는 TextField 와 동일. prefix / suffix / right 슬롯은 제외.
 *  · variant 는 box (기본) / line / big / hero 가 모두 지원되지만, 디자인 권장은 box.
 *
 *  · height 모드:
 *      height    숫자(px) 또는 string — 고정 높이. 그 이상은 textarea 내부 스크롤.
 *      minHeight 숫자(px) — 자동 확장 모드. scrollHeight 에 맞춰 height 가 늘어남.
 *      둘 다 생략 시 — CSS 기본 min-height 84px 만 적용 (보통 5줄 정도).
 *      두 값이 모두 주어지면 minHeight 가 우선 (자동 확장).
 *
 *  · ref API: TextField 와 동일 (focus / blur / clear / el)
 *
 *  · maxLength 가 있으면 우측 하단에 카운터 (현재/최대) 표시.
 *
 *  · Babel Standalone 환경 호환: __ta 접두사 alias.
 * ========================================================================== */

const __taUseState           = (typeof React !== "undefined" && React.useState) || function (v) { return [v, function () {}]; };
const __taUseRef             = (typeof React !== "undefined" && React.useRef) || function () { return { current: null }; };
const __taUseEffect          = (typeof React !== "undefined" && React.useEffect) || function () {};
const __taUseLayoutEffect    = (typeof React !== "undefined" && React.useLayoutEffect) || function () {};
const __taUseImperativeHandle= (typeof React !== "undefined" && React.useImperativeHandle) || function () {};
const __taForwardRef         = (typeof React !== "undefined" && React.forwardRef) || function (fn) { return fn; };

function __taJoin() {
  let out = "";
  for (let i = 0; i < arguments.length; i++) {
    const v = arguments[i];
    if (!v) continue;
    out = out ? out + " " + v : v;
  }
  return out;
}

function __taEnum(value, allowed, fallback, propPath) {
  if (allowed.indexOf(value) !== -1) return value;
  if (value !== undefined && window.console && console.warn) {
    console.warn("[TextArea] " + propPath + " 값이 잘못됨: " + JSON.stringify(value) + ". 허용: " + allowed.join(", ") + ". 기본 " + fallback + " 사용.");
  }
  return fallback;
}

const TextArea = __taForwardRef(function TextArea(props, ref) {
  const {
    label,
    placeholder = "",
    help,
    variant: variantProp,
    labelOption: labelOptionProp,
    hasError = false,
    handleError,
    disabled = false,
    required = false,

    height,
    minHeight,
    maxLength,
    showCounter,

    value,
    defaultValue,
    onChange,
    onFocus,
    onBlur,

    paddingTop,
    paddingBottom,

    className = "",
    style,
    id,
    name,
    autoFocus,
    autoComplete,
    inputMode,
    "aria-label": ariaLabel,

    ...rest
  } = props;

  const variant = __taEnum(variantProp, ["box", "line", "big", "hero"], "box", "variant");
  const labelOption = __taEnum(labelOptionProp, ["appear", "sustain"], "sustain", "labelOption");

  // ----- controlled / uncontrolled -----
  const isControlled = value !== undefined;
  const [internalValue, setInternalValue] = __taUseState(typeof defaultValue === "string" ? defaultValue : "");
  const currentValue = isControlled ? (value == null ? "" : String(value)) : internalValue;

  // ----- 포커스 -----
  const [focused, setFocused] = __taUseState(false);

  // ----- ref -----
  const textareaRef = __taUseRef(null);

  __taUseImperativeHandle(ref, function () {
    return {
      focus: function () { if (textareaRef.current && textareaRef.current.focus) textareaRef.current.focus(); },
      blur:  function () { if (textareaRef.current && textareaRef.current.blur)  textareaRef.current.blur(); },
      clear: function () {
        if (!isControlled) setInternalValue("");
        if (typeof onChange === "function") {
          onChange({
            target: { value: "", name: name },
            currentTarget: textareaRef.current,
            type: "change",
          });
        }
      },
      el: function () { return textareaRef.current; },
    };
  }, [isControlled]);

  // ----- 자동 확장 (minHeight 모드) -----
  // height 가 명시되어 있지 않고 minHeight 가 있으면 scrollHeight 동기화.
  const isAuto = (height == null) && (minHeight != null);

  function syncAutoHeight() {
    if (!isAuto) return;
    const el = textareaRef.current;
    if (!el) return;
    // 한 번 줄였다 다시 측정 — 줄어든 경우도 잡힘
    el.style.height = "auto";
    const sh = el.scrollHeight;
    const mh = typeof minHeight === "number" ? minHeight : parseInt(minHeight, 10) || 0;
    el.style.height = Math.max(sh, mh) + "px";
  }

  __taUseLayoutEffect(function () {
    syncAutoHeight();
  }, [currentValue, isAuto, minHeight]);

  // ----- 핸들러 -----
  const handleChange = function (e) {
    if (!isControlled) setInternalValue(e.target.value);
    if (typeof onChange === "function") onChange(e);
  };
  const handleFocus = function (e) {
    setFocused(true);
    if (typeof onFocus === "function") onFocus(e);
  };
  const handleBlur = function (e) {
    setFocused(false);
    if (typeof onBlur === "function") onBlur(e);
  };

  // ----- label 표시 -----
  const hasValueOrFocus = focused || (currentValue && currentValue.length > 0);
  const labelShown = labelOption === "sustain" || (labelOption === "appear" && hasValueOrFocus);

  // ----- 클래스 -----
  const rootCls = __taJoin(
    "tds-tf",
    "tds-tf--textarea",
    "tds-tf--" + variant,
    "tds-tf--" + labelOption,
    labelShown ? "tds-tf--shown" : "",
    focused ? "tds-tf--focused" : "",
    hasError ? "tds-tf--error" : "",
    disabled ? "tds-tf--disabled" : "",
    className
  );

  // ----- 외곽 style -----
  const finalStyle = Object.assign({}, style || {});
  if (paddingTop != null) finalStyle.paddingTop = typeof paddingTop === "number" ? paddingTop + "px" : paddingTop;
  if (paddingBottom != null) finalStyle.paddingBottom = typeof paddingBottom === "number" ? paddingBottom + "px" : paddingBottom;

  // ----- textarea style -----
  const textareaStyle = {};
  if (height != null) {
    textareaStyle.height = typeof height === "number" ? height + "px" : height;
    textareaStyle.minHeight = textareaStyle.height;
    textareaStyle.maxHeight = textareaStyle.height;
    textareaStyle.overflowY = "auto";
  } else if (minHeight != null) {
    textareaStyle.minHeight = typeof minHeight === "number" ? minHeight + "px" : minHeight;
    textareaStyle.overflowY = "hidden"; // 자동 확장 중엔 스크롤 안 보이게
  }

  // ----- 카운터 표시 여부 -----
  const counterVisible = (showCounter !== false) && (typeof maxLength === "number" && maxLength > 0);

  return (
    <div id={id} className={rootCls} style={finalStyle}>
      {label != null && label !== "" ? (
        <label className="tds-tf__label" htmlFor={id ? id + "__textarea" : undefined}>
          {label}
          {required ? <span className="tds-tf__label-required" aria-hidden="true">*</span> : null}
        </label>
      ) : null}

      <div className="tds-tf__body">
        <textarea
          ref={textareaRef}
          id={id ? id + "__textarea" : undefined}
          name={name}
          className="tds-tf__textarea"
          value={currentValue}
          onChange={handleChange}
          onFocus={handleFocus}
          onBlur={handleBlur}
          placeholder={placeholder}
          disabled={disabled}
          autoFocus={autoFocus}
          autoComplete={autoComplete}
          inputMode={inputMode}
          maxLength={maxLength}
          aria-label={ariaLabel || label || undefined}
          aria-invalid={hasError ? "true" : undefined}
          aria-describedby={(handleError || help) && id ? id + "__help" : undefined}
          required={required}
          style={textareaStyle}
          {...rest}
        />
      </div>

      {((hasError && handleError) || help || counterVisible) ? (
        <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
          {((hasError && handleError) || help) ? (
            <p
              id={id ? id + "__help" : undefined}
              className="tds-tf__help"
              role={hasError ? "alert" : undefined}
              style={{ flex: "1 1 auto", margin: 0 }}
            >
              {hasError && handleError ? handleError : help}
            </p>
          ) : null}
          {counterVisible ? (
            <span className="tds-tf__counter" aria-live="polite">
              {currentValue.length}/{maxLength}
            </span>
          ) : null}
        </div>
      ) : null}
    </div>
  );
});

// ----- window 등록 -----
window.TextArea = TextArea;
Object.assign(window, { TextArea });
