import "@assets/style/global.css";
import TaleButton from "@components/TaleButton";
import { TaleText } from "@components/TaleText";
import {Suspense, useCallback, useEffect, useRef, useState} from "react";
import { lazily } from "react-lazily";
import { TaleLoadingFallback } from "@components/TaleLoadingFallback";
import { useParams } from "react-router-dom";
import { RiCheckboxMultipleLine } from "react-icons/ri";
import { BsStars } from "react-icons/bs";
import { DragDropContext, Droppable, Draggable } from "@hello-pangea/dnd";
import { surveysService } from "@/api/surveys";
import { questionService } from "@/api/question";
import { API_UI, formatQuestionApiToUi, formatQuestionUiToApi } from "@/utils/questionFormatApiToUi";
import {getBatchImportedFlag, setBatchImportedFlag} from "@/utils/batchImportStorage";
import { useTranslation } from "@/hooks/useTranslation";

const { ImportQuestions } = lazily(() =>
  import("@pages/survey/new/scratch/Step2/ImportQuestions")
);
const { EditSingleQuestion } = lazily(() =>
  import("@pages/survey/new/scratch/Step2/EditSingleQuestion")
);
const { QuestionAssistantPanel } = lazily(() =>
  import("@pages/survey/new/scratch/Step2/QuestionAssistantPanel")
);
/** Wide enough to keep the question assistant beside the questions instead of over them. */
const wideQuery = "(min-width: 1280px)";

const { TaleAreYouSure } = lazily(() => import("@components/TaleAreYouSure"));
const { TaleModal } = lazily(() => import("@components/TaleModal"));

export const CreateSurveyStep2 = ({
  questions = [],
  setQuestions,
  importQuestions,
  draftQuestions,
  surveyId,
  surveyLanguage,
  surveyTitle,
  surveyCategory,
  enableAiAssistant = false,
}) => {
  const { t } = useTranslation();
  const params = useParams();
  const [state, setstate] = useState({
    deleteQuestion: {
      show: false,
      index: null,
    },
  });
    const selfDuplicate = useCallback(
        async (index) => {
            const question = questions[index];
            const questionOrder = questions.length + 1;
            const API_ITEM = formatQuestionUiToApi({ ...question, questionOrder });
            delete API_ITEM.id; // must be a fresh create — sending the source id causes
            // the backend to upsert/overwrite the original instead
            // of inserting a new row
            const createdQuestion = await surveysService.addQuestionToSurvey(
                params.surveyId,
                API_ITEM
            );
            const duplicatedQuestion = formatQuestionApiToUi(createdQuestion);
            const clone = [
                ...questions.slice(0, index),
                duplicatedQuestion,
                ...questions.slice(index),
            ];
            setQuestions(clone);
        },
        [params.surveyId, questions, setQuestions]
    );

  const selfDelete = useCallback(async (index) => {
    setstate((prev) => ({
      ...prev,
      deleteQuestion: {
        ...prev.deleteQuestion,
        index,
        show: true,
      },
    }));
  }, []);
    const addQuestion = useCallback(async () => {
        const questionOrder = questions.length + 1;
        const newQuestion = await surveysService.addQuestionToSurvey(
            params.surveyId,
            { questionOrder }
        );
        setQuestions([
            ...questions,
            {
                ...newQuestion,
                responseType: "TEXT",
                questionOrder,
            },
        ]);
    }, [params.surveyId, questions, setQuestions]);

    // Beside the questions where there is room, as a sheet over them where there is not. The sheet is a
    // portal, so CSS alone cannot keep it off wide screens - hence the media query.
    const [isWide, setIsWide] = useState(() => window.matchMedia(wideQuery).matches);
    useEffect(() => {
        const media = window.matchMedia(wideQuery);
        const onChange = (e) => setIsWide(e.matches);
        media.addEventListener("change", onChange);
        return () => media.removeEventListener("change", onChange);
    }, []);
    // Open by default only where it does not cover the questions.
    const [assistantOpen, setAssistantOpen] = useState(
        () => enableAiAssistant && window.matchMedia(wideQuery).matches
    );

    // Questions proposed by the assistant, as the person left them, appended after the existing ones.
    const addAssistantQuestions = useCallback(
        async (suggestions) => {
            const startOrder = questions.length + 1;
            const created = await surveysService.addBatchQuestionsToSurvey(
                surveyId,
                suggestions.map((s, i) => {
                    const options = (s.options ?? []).map((o) => o.trim()).filter(Boolean);
                    const isChoice = ["RADIO", "CHECKBOX"].includes(s.questionType);
                    return {
                        text: s.text.trim(),
                        description: s.description || "",
                        // A choice left without two answers cannot be answered; free text can.
                        questionType: isChoice && options.length < 2 ? "COMMENT" : s.questionType,
                        options: isChoice && options.length >= 2 ? options : [],
                        mandatory: !!s.mandatory,
                        otherOption: false,
                        questionOrder: startOrder + i,
                    };
                })
            );
            if (!Array.isArray(created)) throw new Error("Questions were not created");
            setQuestions([
                ...questions,
                ...created.map((e, i) => ({
                    ...formatQuestionApiToUi({ ...e, assets: e.assets ?? [] }),
                    responseType: "TEXT",
                    questionOrder: startOrder + i,
                })),
            ]);
        },
        [questions, setQuestions, surveyId]
    );

    const onDragEnd = useCallback(
        async (result) => {
            if (!result.destination) return;
            const { source, destination } = result;
            if (source.index === destination.index) return;

            const reordered = Array.from(questions);
            const [moved] = reordered.splice(source.index, 1);
            reordered.splice(destination.index, 0, moved);

            // Reassign questionOrder based on new positions
            const updated = reordered.map((q, i) => ({ ...q, questionOrder: i + 1 }));
            setQuestions(updated);

            // Persist new order for each question
            await Promise.all(
                updated.map((q) =>
                    questionService.updateQuestion(
                        formatQuestionUiToApi({ ...q, questionOrder: q.questionOrder })
                    )
                )
            );
        },
        [questions, setQuestions]
    );

  const setQuestion = useCallback(
    (idx, newValue) => {
      let questionsClone = [...questions];
      questionsClone[idx] = {
        ...questionsClone[idx],
        ...newValue,
      };
      setQuestions(questionsClone);
    },
    [questions, setQuestions]
  );

    const questionsRef = useRef(questions);
    useEffect(() => {
        questionsRef.current = questions;
    }, [questions]);

    useEffect(() => {
        return () => {
            const emptyQuestions = questionsRef.current.filter(
                (q) => !q.question_text && !q.format
            );
            emptyQuestions.forEach((q) => {
                questionService.deleteQuestion(q.id).catch(() => undefined);
            });
        };
    }, []);

  const [allowImport, setallowImport] = useState(importQuestions);
  const [alreadyImported, setalreadyImported] = useState(() =>
      getBatchImportedFlag(surveyId)
  );

  return (
    <>
      <Suspense fallback={null}>
        {state.deleteQuestion.show ? (
          <TaleModal className="flex items-center justify-center">
            <TaleAreYouSure
              onCancel={() =>
                setstate((prev) => ({
                  ...prev,
                  deleteQuestion: {
                    show: false,
                    index: null,
                  },
                }))
              }
              onConfirm={async () => {
                await questionService.deleteQuestion(
                  questions[state.deleteQuestion.index].id
                );
                setQuestions(
                  questions.filter((_, i) => i !== state.deleteQuestion.index)
                );
                setstate((prev) => ({
                  ...prev,
                  deleteQuestion: {
                    show: false,
                    index: null,
                  },
                }));
              }}
              text={
                <>
                  {t("surveyBuilder.step2.deleteQuestionWarning")}
                  <br />
                  <b>{t("surveyBuilder.step2.deleteQuestionIrreversible")}</b>
                </>
              }
              title={t("surveyBuilder.step2.deleteQuestionTitle")}
            />
          </TaleModal>
        ) : null}
      </Suspense>
      <div className="flex gap-6 items-start">
      <div className="flex flex-col gap-4 relative flex-1 min-w-0">
        {enableAiAssistant && !assistantOpen && (
          <TaleButton
            role="normal"
            variant="outlined"
            onClick={() => setAssistantOpen(true)}
            className="!w-fit !px-4 self-end rounded-xl"
          >
            <div className="flex items-center gap-2">
              <BsStars className="size-5" />
              <span className="text-sm">{t("surveyBuilder.questionAssistant.open")}</span>
            </div>
          </TaleButton>
        )}
        {!allowImport || alreadyImported ? null : (
          <TaleModal className="flex items-center justify-center p-4">
            <div className="w-[99%] h-[99%] flex items-center justify-center bg-white rounded-2xl shadow-2xl">
              <Suspense fallback={<TaleLoadingFallback className="!py-20" />}>
                <ImportQuestions
                  cancel={() => setallowImport(false)}
                  importQuestions={async (importedList) => {
                      const startOrder = questions.length + 1;
                      const questionsApi = importedList.map((e, i) => ({
                          ...(e.choices?.length ? { options: e.choices, questionType: "RADIO" } : {}),
                          text: e.question,
                          mandatory: false,
                          questionOrder: startOrder + i,
                      }));
                      const newQuestions = await surveysService.addBatchQuestionsToSurvey(
                          surveyId,
                          questionsApi
                      );
                      setQuestions([
                          ...questions,
                          ...newQuestions.map((e, i) => ({
                              id: e.id,
                              possible_responses: e.options,
                              question_text: e.text,
                              mandatory: e.mandatory,
                              responseType: "TEXT",
                              format: API_UI[e.questionType],
                              questionOrder: startOrder + i,
                          })),
                      ]);
                      setallowImport(false);
                      setalreadyImported(true);
                      setBatchImportedFlag(surveyId);
                  }}
                />
              </Suspense>
            </div>
          </TaleModal>
        )}
        {!questions.length ? (
          <div className="w-full h-full flex flex-col items-center justify-center gap-2 py-40">
            <img src="/assets/empty-box.svg" alt={t("surveyBuilder.step2.noQuestionsAlt")} />
            <span className="text-base font-medium text-[#999999]">
              {t("surveyBuilder.step2.noQuestionsRegistered")}{" "}
              <TaleText
                className="font-semibold cursor-pointer"
                onClick={addQuestion}
              >
                {t("surveyBuilder.step2.addNewQuestion")}
              </TaleText>
                {alreadyImported ? null : (
                    <>
                        {" "}{t("surveyBuilder.step2.or")}{" "}
                        <TaleText
                            className="font-semibold cursor-pointer"
                            onClick={() => setallowImport(true)}
                        >
                            {t("surveyBuilder.step2.batchImportMany")}
                        </TaleText>
                    </>
                )}
            </span>
          </div>
        ) : (
            <>
                <DragDropContext onDragEnd={onDragEnd}>
                    <Droppable droppableId="questions-list">
                        {(provided) => (
                            <div
                                ref={provided.innerRef}
                                {...provided.droppableProps}
                                className="flex flex-col gap-4"
                            >
                                {questions.map((e, i) => (
                                    <Draggable key={e.id} draggableId={String(e.id)} index={i}>
                                        {(dragProvided) => (
                                            <div
                                                ref={dragProvided.innerRef}
                                                {...dragProvided.draggableProps}
                                                {...dragProvided.dragHandleProps}
                                            >
                                                <Suspense fallback={<TaleLoadingFallback className="py-20" />}>
                                                    <EditSingleQuestion
                                                        question={e}
                                                        selfDuplicate={() => selfDuplicate(i)}
                                                        selfDelete={() => selfDelete(i)}
                                                        setQuestion={(v) => setQuestion(i, v)}
                                                        questions={questions}
                                                        draftStatus={draftQuestions[e.id]}
                                                        surveyLanguage={surveyLanguage}
                                    />
                                                </Suspense>
                                            </div>
                                        )}
                                    </Draggable>
                                ))}
                                {provided.placeholder}
                            </div>
                        )}
                    </Droppable>
                </DragDropContext>
                <div className="flex gap-1 items-center !sticky bottom-5">
                    <TaleButton
                        onClick={addQuestion}
                        role="normal"
                        className="!font-semibold !px-4 w-fit rounded-xl shadow-lg"
                    >
                        <div className="flex items-center justify-center gap-3">
                            <img src="/assets/add-square.svg" alt={t("surveyBuilder.step2.addQuestionAlt")} className="!size-6" />
                            <span className="text-sm text-nowrap">{t("surveyBuilder.step2.newQuestion")}</span>
                        </div>
                    </TaleButton>
                    {alreadyImported ? null : (
                        <TaleButton
                            role="normal"
                            onClick={() => setallowImport(true)}
                            className="!font-semibold w-fit !px-4 rounded-xl shadow-lg"
                        >
                            <div className="flex items-center justify-center gap-3">
                                <RiCheckboxMultipleLine className="!size-6" />
                                <span className="text-sm text-nowrap">{t("surveyBuilder.step2.batchImport")}</span>
                            </div>
                        </TaleButton>
                    )}
                </div>
            </>
        )}
      </div>
      {enableAiAssistant && assistantOpen && isWide && (
        <aside
          className="w-[340px] 2xl:w-[400px] shrink-0 sticky"
          // Clear the layout's sticky header (it publishes its height as --header-h) at the top, and
          // the round assistance button fixed in the bottom-right corner (56px, 20px from the edge)
          // at the bottom - it used to sit on top of the Send button.
          style={{
            top: "calc(var(--header-h, 80px) + 1rem)",
            height: "calc(100vh - var(--header-h, 80px) - 7rem)",
          }}
        >
          <Suspense fallback={<TaleLoadingFallback className="py-20" />}>
            <QuestionAssistantPanel
              surveyId={surveyId}
              surveyTitle={surveyTitle}
              surveyCategory={surveyCategory}
              surveyLanguage={surveyLanguage}
              questions={questions}
              onAddQuestions={addAssistantQuestions}
              onClose={() => setAssistantOpen(false)}
            />
          </Suspense>
        </aside>
      )}
      </div>
      {/* Narrow screens: the same conversation as a sheet over the questions, closed by default. */}
      {enableAiAssistant && assistantOpen && !isWide && (
        <Suspense fallback={null}>
          <TaleModal className="flex items-end sm:items-center justify-center p-2">
            <div className="w-full max-w-lg h-[85vh]">
              <Suspense fallback={<TaleLoadingFallback className="py-20" />}>
                <QuestionAssistantPanel
                  surveyId={surveyId}
                  surveyTitle={surveyTitle}
                  surveyCategory={surveyCategory}
                  surveyLanguage={surveyLanguage}
                  questions={questions}
                  onAddQuestions={addAssistantQuestions}
                  onClose={() => setAssistantOpen(false)}
                />
              </Suspense>
            </div>
          </TaleModal>
        </Suspense>
      )}
    </>
  );
};
