"use client";

import {
  type ReactNode,
  useCallback,
  useEffect,
  useRef,
  useState,
} from "react";

type QuestionProgressTrackerProps = {
  children: ReactNode;
  total: number;
};

function isQuestionAnswered(question: Element) {
  const explicitAnsweredState = question.getAttribute("data-question-answered");

  if (explicitAnsweredState === "true") {
    return true;
  }

  if (explicitAnsweredState === "false") {
    return false;
  }

  const inputs = Array.from(
    question.querySelectorAll<
      HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement
    >("input, select, textarea"),
  );

  return inputs.some((input) => {
    if (input instanceof HTMLInputElement) {
      if (input.type === "checkbox" || input.type === "radio") {
        return input.checked;
      }

      if (input.type === "file") {
        return input.files !== null && input.files.length > 0;
      }
    }

    return input.value.trim().length > 0;
  });
}

export function QuestionProgressTracker({
  children,
  total: initialTotal,
}: QuestionProgressTrackerProps) {
  const containerRef = useRef<HTMLDivElement>(null);
  const [answered, setAnswered] = useState(0);
  const [total, setTotal] = useState(initialTotal);
  const safeTotal = Math.max(total, 0);
  const progress = safeTotal > 0 ? (answered / safeTotal) * 100 : 0;

  const updateProgress = useCallback(() => {
    const container = containerRef.current;

    if (!container) {
      return;
    }

    const requiredQuestions = Array.from(
      container.querySelectorAll("[data-question-required='true']"),
    ).filter((el) => el.getAttribute("data-question-disabled") !== "true");

    const nextTotal = requiredQuestions.length;
    const nextAnswered = requiredQuestions.filter(isQuestionAnswered).length;

    setTotal(nextTotal);
    setAnswered(nextAnswered);
  }, []);

  useEffect(() => {
    const container = containerRef.current;

    if (!container) {
      return;
    }

    const observer = new MutationObserver(updateProgress);

    observer.observe(container, {
      attributeFilter: ["data-question-answered"],
      attributes: true,
      subtree: true,
    });

    updateProgress();

    return () => observer.disconnect();
  }, [updateProgress]);

  return (
    <div
      ref={containerRef}
      className="flex flex-col"
      onChange={updateProgress}
      onInput={updateProgress}
    >
      <div className="mb-5 h-[68px]" aria-hidden="true" />
      <div className="fixed top-[100px] left-1/2 z-20 w-full max-w-[375px] -translate-x-1/2 px-[17px]">
        <div
          aria-label={`Answered questions: ${answered} of ${safeTotal}`}
          aria-valuemax={safeTotal}
          aria-valuemin={0}
          aria-valuenow={answered}
          role="progressbar"
          className="w-full rounded-none bg-[#F7F1F0] px-[9px] pt-[25px] pb-[16px]"
        >
          <div className="mb-[7px] flex items-center justify-between text-xs leading-none font-normal text-[#747474]">
            <span>fields to complete</span>
            <span>
              {answered} /{safeTotal}
            </span>
          </div>
          <div className="relative h-[6px] rounded-full bg-[#D8D8D8]">
            <div
              className={[
                "absolute top-1/2 h-[10px] -translate-y-1/2 rounded-full bg-[#F2465F] transition-[width] duration-200",
                answered > 0 ? "min-w-[37px]" : "",
              ]
                .filter(Boolean)
                .join(" ")}
              style={{ width: `${progress}%` }}
            />
          </div>
        </div>
      </div>

      {children}
    </div>
  );
}

export default QuestionProgressTracker;
