import { QuestionTypes } from "@/api/types";
import {
  useAnswerMutation,
  useCompleteTestMutation,
  useUserTest,
} from "@/api/userTests";
import Question from "@/components/question";
import {
  AlertDialog,
  AlertDialogBackdrop,
  AlertDialogBody,
  AlertDialogContent,
  AlertDialogFooter,
  AlertDialogHeader,
} from "@/components/ui/alert-dialog";
import Answer from "@/components/ui/answer";
import { Button, ButtonText } from "@/components/ui/button";
import Content from "@/components/ui/content";
import CustomButton from "@/components/ui/custom-button";
import { Divider } from "@/components/ui/divider";
import Panel from "@/components/ui/panel";
import { Textarea, TextareaInput } from "@/components/ui/textarea";
import { ThemedText } from "@/components/ui/themed-text";
import getErrorAxiosMessage from "@/utils/get-error-axios-message";
import getUserTestTitle from "@/utils/get-user-test-title";
import { router, Stack, useLocalSearchParams } from "expo-router";
import { useEffect, useState } from "react";
import { ScrollView, StyleSheet, View } from "react-native";
import { useToast } from "react-native-toast-notifications";

const DoingUserTestScreen = () => {
  const { id: idParam } = useLocalSearchParams<{ id: string }>();
  const [answer, setAnswer] = useState<(string | number)[]>([]);
  const [page, setPage] = useState(0);
  const [openCompleteDialog, setOpenCompleteDialog] = useState(false);
  const id = +idParam;
  const { data: userTest, refetch: refetchUserTest } = useUserTest(id);
  const { mutateAsync: mutateAsyncAnswer, isPending: answerPending } =
    useAnswerMutation();
  const { mutate: mutateCompleteTest, isPending: completePending } = useCompleteTestMutation();
  const toast = useToast();
  useEffect(() => {
    if (!userTest) return;

    setAnswer(userTest.answers[page].answer || []);
  }, [userTest, page]);

  if (!userTest)
    return (
      <>
        <Stack.Screen options={{ title: `Test #${id}` }} />
        <Content>
          <Question />
        </Content>
      </>
    );

  const currentAnswer = userTest.answers[page];
  const currentQuestion = currentAnswer.question;
  const pages = Array.from({ length: userTest.answers.length }).map(
    (_, i) => i
  );
  const countAnsweredQuestion = userTest.answers.filter(
    (answer) => answer.answer
  ).length;
  const isAllAnswered = countAnsweredQuestion === userTest.answers.length;
  const isLastPage = page === pages.length - 1;
  const userTextAnswer = answer ? (answer[0] as string) : "";
  const alertDialogMessage = isAllAnswered
    ? "Finish the test to see your results."
    : "Warning: You haven't answered all questions. Are you sure you want to finish?";

  const handleSetAnswer = (value: number | string) => {
    if (currentQuestion.type === QuestionTypes.Text) {
      setAnswer([value]);
    }
    if (currentQuestion.type === QuestionTypes.Single) {
      setAnswer([value as number]);
    }
    if (currentQuestion.type === QuestionTypes.Multiple) {
      if ((answer as number[]).includes(value as number)) {
        setAnswer((prev) => prev.filter((v) => v !== value));
      } else {
        setAnswer((prev) => {
          const set = new Set(prev as number[]);
          set.add(value as number);
          return Array.from(set);
        });
      }
    }
  };
  const handleSaveAnswer = async () => {
    let ans = answer;

    if (currentQuestion.type === QuestionTypes.Text && answer) {
      ans = [(answer[0] as string).trim()];
    }

    try {
      await mutateAsyncAnswer(
        {
          answerId: currentAnswer.id,
          answer: ans,
        },
        {
          onSuccess: () => {
            toast.show("Your answer was saved", { type: "success" });
            if(!isLastPage)
              goPage(page + 1);
          },
          onError: (error) => {
            toast.show(getErrorAxiosMessage(error), { type: "danger" });
          },
        }
      );
    } catch {}
    await refetchUserTest();
  };
  const handleCompleteTest = () => {
    mutateCompleteTest({
      testId: userTest.id
    }, {
      onSuccess: () => {
        router.replace(`/user-tests/${userTest.id}`);
      },
      onError: (error) => {
        toast.show(getErrorAxiosMessage(error), { type: "danger" });
      }
    })
  };
  const goPage = (page: number) => {
    setAnswer([]);
    setPage(page);
  };

  return (
    <>
      <Stack.Screen options={{ title: getUserTestTitle(userTest) }} />
      <View style={styles.container}>
        <Content style={styles.content}>
          <View style={styles.top}>
            <ScrollView horizontal contentContainerStyle={styles.topScrollView}>
              {pages.map((p) => (
                <Button
                  key={p}
                  variant={p === page ? "solid" : "outline"}
                  action={
                    p === page || userTest.answers[p].answer
                      ? "primary"
                      : "secondary"
                  }
                  onPress={() => goPage(p)}
                >
                  <ButtonText>{p + 1}</ButtonText>
                </Button>
              ))}
              <Button
                variant="outline"
                action="negative"
                onPress={() => setOpenCompleteDialog(true)}
              >
                <ButtonText>Complete test</ButtonText>
              </Button>
            </ScrollView>
          </View>

          <Question question={currentQuestion} />

          <Divider className="mt-5 mb-5" />

          <View className="gap-4 mb-4">
            {currentQuestion.variants.map((variant) => (
              <Answer
                key={variant.id}
                answer={variant}
                isTextType={false}
                userAnswers={answer}
                onPress={() => handleSetAnswer(variant.id)}
                displayUserAnswer={true}
              />
            ))}
            {currentQuestion.type === QuestionTypes.Text && (
              <Panel>
                <ThemedText className="mb-1 text-sm" type="defaultSemiBold">
                  Your answer:
                </ThemedText>
                <Textarea>
                  <TextareaInput
                    onChangeText={(text) => handleSetAnswer(text)}
                    value={userTextAnswer}
                  />
                </Textarea>
              </Panel>
            )}
          </View>

          <CustomButton isLoading={answerPending} onPress={handleSaveAnswer}>
            <ButtonText>Save answer</ButtonText>
          </CustomButton>

          <Divider className="mt-2 mb-3" />

          {(isAllAnswered || isLastPage) && (
            <Button
              variant={isAllAnswered ? "outline" : "solid"}
              action="negative"
              onPress={() => setOpenCompleteDialog(true)}
            >
              <ButtonText>Complete test</ButtonText>
            </Button>
          )}
        </Content>
      </View>

      <AlertDialog
        isOpen={openCompleteDialog}
        onClose={() => setOpenCompleteDialog(false)}
      >
        <AlertDialogBackdrop />
        <AlertDialogContent>
          <AlertDialogHeader className="mb-2">
            <ThemedText type="defaultSemiBold">Complete test</ThemedText>
          </AlertDialogHeader>
          <AlertDialogBody className="mb-3">
            <ThemedText>{alertDialogMessage}</ThemedText>
          </AlertDialogBody>
          <AlertDialogFooter>
            <Button
              variant="outline"
              action="secondary"
              onPress={() => setOpenCompleteDialog(false)}
              size="sm"
            >
              <ButtonText>Cancel</ButtonText>
            </Button>
            <CustomButton
              variant={isAllAnswered ? "outline" : "solid"}
              action="negative"
              size="sm"
              isLoading={completePending}
              onPress={handleCompleteTest}
            >
              <ButtonText>Complete</ButtonText>
            </CustomButton>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    width: "100%"
  },
  top: {
    width: "100%",
    marginBottom: 15,
  },
  topScrollView: {
    flexDirection: "row",
    alignItems: "flex-start",
    gap: 10,
  },
  content: {
    flex: 1,
    width: "100%",
  },
});

export default DoingUserTestScreen;
