"use client";

import {
  forwardRef,
  useCallback,
  useEffect,
  useId,
  useImperativeHandle,
  useRef,
} from "react";
import type { FormEvent } from "react";

export type ActiveAnswerInput = 0 | 1;

export interface AnswerFormHandle {
  focusInput: () => void;
}

interface AnswerFormProps {
  answerA: string;
  answerB: string;
  activeInput: ActiveAnswerInput;
  disabled: boolean;
  error: string;
  focusOnMount?: boolean;
  onAnswerAChange: (value: string) => void;
  onAnswerBChange: (value: string) => void;
  onActiveInputChange: (input: ActiveAnswerInput) => void;
  onInputBlur?: () => void;
  onInputFocus?: () => void;
  onSubmit: (event: FormEvent<HTMLFormElement>) => void;
}

const AnswerForm = forwardRef<AnswerFormHandle, AnswerFormProps>(function AnswerForm(
  {
    answerA,
    answerB,
    activeInput,
    disabled,
    error,
    focusOnMount = false,
    onAnswerAChange,
    onAnswerBChange,
    onActiveInputChange,
    onInputBlur,
    onInputFocus,
    onSubmit,
  },
  ref,
) {
  const inputId = useId();
  const formRef = useRef<HTMLFormElement>(null);
  const inputRef = useRef<HTMLInputElement>(null);

  const activeAnswer = activeInput === 0 ? answerA : answerB;
  const activeLabel = activeInput === 0 ? "첫째 항" : "둘째 항";
  const activeEnterKeyHint = activeInput === 0 ? "next" : "done";
  const activeAnswerChange =
    activeInput === 0 ? onAnswerAChange : onAnswerBChange;

  const focusInput = useCallback(() => {
    inputRef.current?.focus({ preventScroll: true });
    onInputFocus?.();
  }, [onInputFocus]);

  useImperativeHandle(ref, () => ({ focusInput }), [focusInput]);

  useEffect(() => {
    if (!disabled && focusOnMount) {
      window.requestAnimationFrame(() => {
        focusInput();
      });
    }
  }, [disabled, focusInput, focusOnMount]);

  function setAnswer(input: ActiveAnswerInput, value: string) {
    if (input === 0) {
      onAnswerAChange(value);
    } else {
      onAnswerBChange(value);
    }
  }

  function toggleMinus() {
    activeAnswerChange(
      activeAnswer.startsWith("-") ? activeAnswer.slice(1) : `-${activeAnswer}`,
    );
    focusInput();
  }

  function moveToInput(input: ActiveAnswerInput, reset = false) {
    onActiveInputChange(input);
    if (reset) {
      setAnswer(input, "");
    }
    focusInput();
  }

  function handleEnter() {
    if (activeInput === 0) {
      moveToInput(1);
      return;
    }

    formRef.current?.requestSubmit();
  }

  const answerButtons = [
    {
      index: 0 as const,
      label: "첫째 항",
      value: answerA,
    },
    {
      index: 1 as const,
      label: "둘째 항",
      value: answerB,
    },
  ];

  return (
    <form
      ref={formRef}
      onSubmit={onSubmit}
      className="rounded-md bg-white p-6 shadow-sm ring-1 ring-slate-200 sm:p-8"
    >
      <div className="flex flex-col gap-4">
        <div>
          <label
            htmlFor={inputId}
            className="mb-2 block text-sm font-semibold text-slate-700"
          >
            {activeLabel}
          </label>
          <div className="flex h-12 w-full min-w-0 overflow-hidden rounded-md border border-slate-300 bg-white focus-within:border-emerald-600 focus-within:ring-2 focus-within:ring-emerald-200 sm:border-0 sm:focus-within:ring-0">
            <button
              type="button"
              disabled={disabled}
              onPointerDown={(event) => event.preventDefault()}
              onClick={toggleMinus}
              aria-label={`${activeLabel} 음수 기호 입력`}
              className="inline-flex h-full w-12 shrink-0 items-center justify-center border-r border-slate-300 px-2 text-sm font-semibold text-slate-800 transition hover:bg-slate-100 focus:outline-none disabled:cursor-not-allowed disabled:bg-slate-100 disabled:text-slate-400 sm:hidden"
            >
              -/+
            </button>
            <input
              id={inputId}
              ref={inputRef}
              type="text"
              value={activeAnswer}
              onFocus={() => {
                onInputFocus?.();
              }}
              onBlur={() => {
                onInputBlur?.();
              }}
              onChange={(event) => activeAnswerChange(event.target.value)}
              onKeyDown={(event) => {
                if (event.key === "Enter") {
                  event.preventDefault();
                  handleEnter();
                }
              }}
              disabled={disabled}
              autoComplete="off"
              enterKeyHint={activeEnterKeyHint}
              inputMode="numeric"
              pattern="-?[0-9]*"
              className="h-full min-w-0 flex-1 px-3 text-lg font-semibold text-slate-950 outline-none disabled:bg-slate-100 sm:rounded-md sm:border sm:border-slate-300 sm:px-4 sm:transition sm:focus:border-emerald-600 sm:focus:ring-2 sm:focus:ring-emerald-200"
            />
            <button
              type="button"
              disabled={disabled}
              onPointerDown={(event) => event.preventDefault()}
              onClick={handleEnter}
              aria-label={
                activeInput === 0
                  ? "첫째 항 입력 완료 후 둘째 항으로 이동"
                  : "둘째 항 입력 완료 후 제출"
              }
              className="inline-flex h-full w-12 shrink-0 items-center justify-center border-l border-slate-300 px-2 text-xl font-semibold text-slate-800 transition hover:bg-slate-100 focus:outline-none disabled:cursor-not-allowed disabled:bg-slate-100 disabled:text-slate-400 sm:hidden"
            >
              ↵
            </button>
          </div>
        </div>

        <div
          className="inline-flex w-fit max-w-full gap-1 rounded-md border border-slate-300 bg-white p-1 shadow-sm"
          role="group"
          aria-label="입력 항 선택"
        >
          {answerButtons.map((button) => {
            const selected = activeInput === button.index;

            return (
              <button
                key={button.index}
                type="button"
                disabled={disabled}
                onPointerDown={(event) => event.preventDefault()}
                onClick={() => moveToInput(button.index, true)}
                aria-pressed={selected}
                aria-label={`${button.label} 다시 입력`}
                className={`inline-flex h-10 min-w-20 items-center justify-center rounded px-3 text-base font-semibold transition focus:outline-none focus:ring-2 focus:ring-emerald-500 focus:ring-offset-2 disabled:cursor-not-allowed ${
                  selected
                    ? "bg-emerald-700 text-white"
                    : "text-slate-700 hover:bg-slate-100 disabled:bg-slate-100 disabled:text-slate-400"
                }`}
              >
                {button.value || "?"}
              </button>
            );
          })}
        </div>
      </div>

      {error ? (
        <p className="mt-3 text-sm font-semibold text-red-700">{error}</p>
      ) : null}
    </form>
  );
});

export default AnswerForm;
