"use client";

import { useMemo, useEffect, useRef } from "react";
import { useForm, Controller } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/yup";
import * as yup from "yup";
import {
  Accordion,
  AccordionContent,
  AccordionItem,
  AccordionTrigger,
} from "@/components/ui/accordion";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { Input } from "@/components/ui/input";
import {
  Select,
  SelectTrigger,
  SelectValue,
  SelectContent,
  SelectItem,
} from "@/components/ui/select";
import { Checkbox } from "@/components/ui/checkbox";
import { useTranslations } from "next-intl";
import { useEventDetails } from "@/hooks/useEventDetails";
import { useBooking } from "@/context/BookingContext";
import { QuestionType } from "@/types/questions";
import type { Question } from "@/types/event";
import type { QuestionAnswer } from "@/types/booking";

interface QuestionsRelatedEventProps {
  onFormValidChange?: (isValid: boolean) => void;
}

export default function QuestionsRelatedEvent({
  onFormValidChange,
}: QuestionsRelatedEventProps) {
  const t = useTranslations("QuestionsPage");
  const tCommon = useTranslations("Common");
  const { data: eventData, isLoading, isError } = useEventDetails();
  const { setQuestions } = useBooking();

  const questions = useMemo(
    () => eventData?.data?.event?.questions || [],
    [eventData?.data?.event?.questions]
  );

  // Create dynamic yup schema based on questions
  const validationSchema = useMemo(() => {
    if (questions.length === 0) {
      return yup.object().shape({});
    }

    const schemaObject: Record<string, yup.AnySchema> = {};

    questions.forEach((question) => {
      const fieldName = `question_${question.id}`;

      switch (question.type) {
        case QuestionType.OPEN_ENDED:
          schemaObject[fieldName] = yup
            .string()
            .required(t("fieldRequired"))
            .min(1, t("fieldRequired"));
          break;

        case QuestionType.YES_NO:
          schemaObject[fieldName] = yup
            .string()
            .required(t("fieldRequired"))
            .oneOf(question.answer, t("invalidSelection"));
          break;

        case QuestionType.MULTIPLE_CHOICE:
          schemaObject[fieldName] = yup
            .array()
            .of(yup.string())
            .min(1, t("selectAtLeastOne"))
            .required(t("fieldRequired"));
          break;

        case QuestionType.SINGLE_CHOICE:
          schemaObject[fieldName] = yup
            .string()
            .required(t("fieldRequired"))
            .oneOf(question.answer, t("invalidSelection"));
          break;
      }
    });

    return yup.object().shape(schemaObject) as yup.ObjectSchema<
      Record<string, string | string[]>
    >;
  }, [questions, t]);

  type FormValues = Record<string, string | string[]>;

  const defaultValues = useMemo<FormValues>(() => {
    const defaults: FormValues = {};
    questions.forEach((question) => {
      const fieldName = `question_${question.id}`;
      if (question.type === QuestionType.MULTIPLE_CHOICE) {
        defaults[fieldName] = [];
      } else {
        defaults[fieldName] = "";
      }
    });
    return defaults;
  }, [questions]);

  const {
    control,
    watch,
    reset,
    formState: { isValid, errors },
  } = useForm<FormValues>({
    resolver: yupResolver(validationSchema),
    mode: "onChange",
    defaultValues,
  });

  // Watch all form values to trigger validation
  const formValues = watch();

  // Reset form when questions change
  useEffect(() => {
    reset(defaultValues);
  }, [defaultValues, reset]);

  // Watch form validity and notify parent
  useEffect(() => {
    onFormValidChange?.(isValid);
  }, [isValid, onFormValidChange]);

  // Use ref to track previous questionAnswers to avoid infinite loop
  const prevQuestionAnswersRef = useRef<string>("");

  // Convert form values to booking format and save to context
  useEffect(() => {
    const questionAnswers: QuestionAnswer[] = questions
      .map((question) => {
        const fieldName = `question_${question.id}`;
        const formValue = formValues[fieldName];

        if (!formValue) return null;

        // Convert form value to answer array
        let answers: string[] = [];
        if (Array.isArray(formValue)) {
          answers = formValue;
        } else if (typeof formValue === "string" && formValue.trim() !== "") {
          answers = [formValue];
        }

        if (answers.length === 0) return null;

        return {
          question_id: question.id,
          answer: answers,
        };
      })
      .filter((qa): qa is QuestionAnswer => qa !== null);

    // Only update context if questionAnswers actually changed
    const currentAnswersString = JSON.stringify(questionAnswers);
    if (prevQuestionAnswersRef.current !== currentAnswersString) {
      prevQuestionAnswersRef.current = currentAnswersString;
      setQuestions(questionAnswers);
    }
  }, [formValues, questions, setQuestions]);

  const renderQuestion = (question: Question) => {
    const questionId = `question-${question.id}`;
    const fieldName = `question_${question.id}`;
    const error = errors[fieldName];

    switch (question.type) {
      case QuestionType.OPEN_ENDED:
        return (
          <div key={question.id} className="flex flex-col gap-1">
            <Label htmlFor={questionId}>
              {question.questions}
              <span className="text-red-500 ml-px">*</span>
            </Label>
            <Controller
              name={fieldName}
              control={control}
              render={({ field }) => (
                <>
                  <Textarea
                    id={questionId}
                    placeholder={t("yourAnswerHere")}
                    {...field}
                  />
                  {error && (
                    <p className="text-sm text-red-500">{error.message}</p>
                  )}
                </>
              )}
            />
          </div>
        );

      case QuestionType.YES_NO:
        return (
          <div key={question.id} className="flex flex-col gap-1">
            <Label>
              {question.questions}
              <span className="text-red-500 ml-px">*</span>
            </Label>
            <Controller
              name={fieldName}
              control={control}
              render={({ field }) => (
                <>
                  <div className="flex gap-10">
                    {question.answer.map((option, index) => (
                      <div key={index} className="flex items-center gap-2">
                        <Input
                          type="radio"
                          id={`${questionId}-${index}`}
                          name={questionId}
                          value={option}
                          checked={field.value === option}
                          onChange={() => field.onChange(option)}
                          className="size-4 focus:ring-0 accent-vendor-secondary cursor-pointer"
                        />
                        <Label
                          htmlFor={`${questionId}-${index}`}
                          className="cursor-pointer"
                        >
                          {option}
                        </Label>
                      </div>
                    ))}
                  </div>
                  {error && (
                    <p className="text-sm text-red-500">{error.message}</p>
                  )}
                </>
              )}
            />
          </div>
        );

      case QuestionType.MULTIPLE_CHOICE:
        return (
          <div key={question.id} className="flex flex-col gap-1">
            <Label>
              {question.questions}
              <span className="text-red-500 ml-px">*</span>
            </Label>
            <Controller
              name={fieldName}
              control={control}
              render={({ field }) => {
                const selectedAnswers = Array.isArray(field.value)
                  ? field.value
                  : [];

                return (
                  <>
                    <div className="flex flex-col gap-3">
                      {question.answer.map((option, index) => {
                        const optionId = `${questionId}-${index}`;
                        const isChecked = selectedAnswers.includes(option);

                        return (
                          <div key={index} className="flex items-center gap-2">
                            <Checkbox
                              id={optionId}
                              checked={isChecked}
                              onCheckedChange={(checked) => {
                                let newAnswers: string[];
                                if (checked) {
                                  newAnswers = [...selectedAnswers, option];
                                } else {
                                  newAnswers = selectedAnswers.filter(
                                    (ans) => ans !== option
                                  );
                                }
                                field.onChange(newAnswers);
                              }}
                            />
                            <Label
                              htmlFor={optionId}
                              className="cursor-pointer"
                            >
                              {option}
                            </Label>
                          </div>
                        );
                      })}
                    </div>
                    {error && (
                      <p className="text-sm text-red-500">{error.message}</p>
                    )}
                  </>
                );
              }}
            />
          </div>
        );

      case QuestionType.SINGLE_CHOICE:
        return (
          <div key={question.id} className="flex flex-col gap-1">
            <Label htmlFor={questionId}>
              {question.questions}
              <span className="text-red-500 ml-px">*</span>
            </Label>
            <Controller
              name={fieldName}
              control={control}
              render={({ field }) => (
                <>
                  <Select
                    value={typeof field.value === "string" ? field.value : ""}
                    onValueChange={field.onChange}
                  >
                    <SelectTrigger id={questionId}>
                      <SelectValue placeholder={t("selectOption")} />
                    </SelectTrigger>
                    <SelectContent>
                      {question.answer.map((option, index) => (
                        <SelectItem key={index} value={option}>
                          {option}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                  {error && (
                    <p className="text-sm text-red-500">{error.message}</p>
                  )}
                </>
              )}
            />
          </div>
        );

      default:
        return null;
    }
  };

  if (isLoading) {
    return (
      <Accordion type="single" collapsible defaultValue="item-1">
        <AccordionItem value="item-1">
          <AccordionTrigger className="text-[16px] font-bold">
            {t("questionsRelatedEvent")}
          </AccordionTrigger>
          <AccordionContent className="pt-5 flex flex-col gap-5">
            <p className="text-center py-5">{tCommon("loadingQuestions")}</p>
          </AccordionContent>
        </AccordionItem>
      </Accordion>
    );
  }

  if (isError || questions.length === 0) {
    return (
      <Accordion type="single" collapsible defaultValue="item-1">
        <AccordionItem value="item-1">
          <AccordionTrigger className="text-[16px] font-bold">
            {t("questionsRelatedEvent")}
          </AccordionTrigger>
          <AccordionContent className="pt-5 flex flex-col gap-5">
            <p className="text-center py-5">
              {questions.length === 0
                ? tCommon("noQuestionsAvailable")
                : tCommon("errorLoadingQuestions")}
            </p>
          </AccordionContent>
        </AccordionItem>
      </Accordion>
    );
  }

  return (
    <Accordion type="single" collapsible defaultValue="item-1">
      <AccordionItem value="item-1">
        <AccordionTrigger className="text-[16px] font-bold">
          {t("questionsRelatedEvent")}
        </AccordionTrigger>
        <AccordionContent className="pt-5 flex flex-col gap-5">
          {questions.map((question) => renderQuestion(question))}
        </AccordionContent>
      </AccordionItem>
    </Accordion>
  );
}
