import { IAPITag } from "@/pages/profile_tasks.dto";
import apiClient from "@/services/api";
import { cn } from "@/utils/class-merge";
import { BookOpenIcon, CheckIcon, DocumentDuplicateIcon, PlusCircleIcon } from "@heroicons/react/24/outline";
import { XMarkIcon } from "@heroicons/react/24/solid";
import { FunctionComponent } from "preact";
import { Dispatch, StateUpdater, useEffect, useRef, useState } from "preact/hooks";
import Button from "./ui/Button";
import Dialog from "./ui/Dialog";
import ModalWindow, { ModalWindowProps } from "./ui/Modal";

export interface ITags {
  first: number;
  second: number;
  overdue: boolean;
}

interface ModalTagsProps extends ModalWindowProps {
  isOpen?: boolean;
  setIsOpen?: Dispatch<StateUpdater<boolean>>;
  onClose?: () => void;
  value?: ITags;
  onChange?: Dispatch<StateUpdater<ITags>>;
  tagsList?: {
    first: IAPITag[];
    second: IAPITag[];
  };
  refreshTags: () => void;
}

const ModalTags: FunctionComponent<ModalTagsProps> = ({
  isOpen,
  setIsOpen,
  onClose,
  onChange,
  value,
  tagsList,
  refreshTags,
  ...rest
}) => {
  const [showFirstTags, setShowFirstTags] = useState(false);
  const [showSecondTags, setShowSecondTags] = useState(false);
  const [showAddFirstTag, setShowAddFirstTag] = useState(false);
  const [showAddSecondTag, setShowAddSecondTag] = useState(false);
  const [showErrorDialog, setShowErrorDialog] = useState(false);
  const [errorMessage, setErrorMessage] = useState<string[]>([]);
  const addFirstTagRef = useRef<HTMLInputElement>(null);
  const addSecondTagRef = useRef<HTMLInputElement>(null);
  useEffect(() => {
    if (showFirstTags && showSecondTags) setShowFirstTags(false);
  }, [showSecondTags]);
  useEffect(() => {
    if (showFirstTags && showSecondTags) setShowSecondTags(false);
  }, [showFirstTags]);

  const handleCreateTag = async () => {
    if (!addFirstTagRef.current?.value && !addSecondTagRef.current?.value) return;

    const data: { subject_name?: string; taskType_name?: string } = {};
    if (addFirstTagRef.current && addFirstTagRef.current.value) data.subject_name = addFirstTagRef.current.value;
    if (addSecondTagRef.current && addSecondTagRef.current.value) data.taskType_name = addSecondTagRef.current.value;
    const response = await apiClient<{ success: boolean; subject?: IAPITag; taskType?: IAPITag }>(
      "/api/tags/create_tags/",
      { method: "POST", body: JSON.stringify(data) }
    );
    if (response.success) {
      refreshTags();
      if (showAddFirstTag) {
        const new_subject_id = response.subject!.id;
        onChange!((prev) => ({ ...prev, first: new_subject_id }));
        setShowAddFirstTag(false);
      }
      if (showAddSecondTag) {
        const new_taskType_id = response.taskType!.id;
        onChange!((prev) => ({ ...prev, second: new_taskType_id }));
        setShowAddSecondTag(false);
      }
    }
    if (addFirstTagRef.current) addFirstTagRef.current.value = "";
    if (addSecondTagRef.current) addSecondTagRef.current.value = "";
  };

  const handleDeleteTag = async (id: number) => {
    const data: { subject_id?: number; taskType_id?: number } = {};
    if (showFirstTags) data.subject_id = id;
    if (showSecondTags) data.taskType_id = id;
    const response = await apiClient<{ error?: string }>(`/api/tags/delete_tag/`, {
      method: "DELETE",
      body: JSON.stringify(data),
    });
    if (!response.error) {
      refreshTags();
    } else {
      setShowErrorDialog(true);
      const match = response.error?.match(/\[(.+)\]/);
      if (match) setErrorMessage(match[1].split(", ").map((s) => s.trim().replace(/'/g, "")));
    }
  };

  return (
    <>
      <Dialog
        isOpen={showErrorDialog}
        setIsOpen={setShowErrorDialog}
        title="Ошибка!"
        confirmation={false}
        cancelText="Ок"
      >
        <div class="flex flex-col items-start gap-1">
          <p class="mb-6 text-sm sm:text-[1rem]">
            Данный тег есть в других задачах. Поменяйте теги в них и повторите операцию.
          </p>
          <p class="text-sm sm:text-[1rem]">Задачи с этим тегом:</p>
          <ul class="ms-6 list-disc">
            {errorMessage.map((s, i) => (
              <li key={i}>{s}</li>
            ))}
          </ul>
        </div>
      </Dialog>
      <ModalWindow
        isOpen={isOpen}
        {...rest}
        setIsOpen={setIsOpen}
        onClose={() => {
          onClose!();
          setShowFirstTags(false);
          setShowSecondTags(false);
          setShowAddFirstTag(false);
          setShowAddSecondTag(false);
        }}
        className="relative h-[14rem] justify-between py-4 md:h-[14rem] md:w-[25rem]"
        zIndex={70}
      >
        <p class="text-2xl font-semibold">Теги</p>
        <div class="flex w-[85%] flex-col gap-2 md:w-full">
          <Button
            className="flex w-full flex-row items-center justify-center gap-1 text-[1rem]!"
            onClick={() => {
              setShowFirstTags(!showFirstTags);
              setShowSecondTags(false);
              setShowAddFirstTag(false);
              setShowAddSecondTag(false);
            }}
          >
            <BookOpenIcon class="size-6" />
            {tagsList?.first?.find((tag) => tag.id === value?.first)?.name || "Предмет"}
          </Button>
          <Button
            className="flex w-full flex-row items-center justify-center gap-1 text-[1rem]! break-words"
            onClick={() => {
              setShowSecondTags(!showSecondTags);
              setShowFirstTags(false);
              setShowAddFirstTag(false);
              setShowAddSecondTag(false);
            }}
          >
            <DocumentDuplicateIcon class="size-6" />
            {tagsList?.second?.find((tag) => tag.id === value?.second)?.name || "Тема"}
          </Button>
          {showFirstTags && (
            <div class="absolute top-full left-0 mt-3 ml-2 flex h-fit w-[18rem] flex-col items-center gap-3 md:top-0 md:left-full md:mt-0 md:ml-5">
              <div class="flex h-fit max-h-[15rem] w-full flex-col gap-3 overflow-y-auto rounded-[4rem] bg-white px-8 py-4 text-xs">
                {tagsList?.first.map((tag) => (
                  <div
                    class="flex cursor-pointer flex-row items-center gap-2"
                    onClick={() =>
                      onChange?.((prev) => {
                        return { ...prev, first: tag.id };
                      })
                    }
                  >
                    <div
                      class={cn(
                        "pointer-events-none flex aspect-square size-4 flex-col items-center justify-center rounded-full border-1 border-black text-white select-none",
                        {
                          "bg-black": value?.first === tag.id,
                        }
                      )}
                    >
                      ✓
                    </div>
                    <p class="flex-1">{tag.name}</p>
                    <XMarkIcon
                      class="size-4 cursor-pointer"
                      onClick={(e) => {
                        e.stopPropagation();
                        handleDeleteTag(tag.id);
                      }}
                    />
                  </div>
                ))}
                <button
                  class="mt-2 flex w-full cursor-pointer flex-row items-center gap-2"
                  onClick={() => {
                    setShowAddFirstTag(!showAddFirstTag);
                    setTimeout(() => addFirstTagRef.current?.focus(), 100);
                  }}
                >
                  <PlusCircleIcon class="size-5" />
                  <span>Добавить</span>
                </button>
              </div>
              {showAddFirstTag && (
                <div class="flex w-full flex-row items-center rounded-[4rem] bg-white px-8 py-4 text-xs">
                  <input placeholder="Введите текст" class="flex-1 outline-0" ref={addFirstTagRef} />
                  <CheckIcon class="size-6 cursor-pointer" onClick={handleCreateTag} />
                </div>
              )}
            </div>
          )}
          {showSecondTags && (
            <div class="absolute top-full left-0 mt-3 ml-2 flex h-fit w-[18rem] flex-col items-center gap-3 md:top-0 md:left-full md:mt-0 md:ml-5">
              <div class="flex h-fit max-h-[15rem] w-full flex-col gap-3 overflow-y-auto rounded-[4rem] bg-white px-8 py-4 text-xs">
                {tagsList?.second.map((tag) => (
                  <div
                    class="flex cursor-pointer flex-row gap-2"
                    onClick={() =>
                      onChange?.((prev) => {
                        return { ...prev, second: tag.id };
                      })
                    }
                  >
                    <div
                      class={cn(
                        "pointer-events-none flex aspect-square size-4 flex-col items-center justify-center rounded-full border-1 border-black text-white select-none",
                        {
                          "bg-black": value?.second === tag.id,
                        }
                      )}
                    >
                      ✓
                    </div>
                    <p class="flex-1">{tag.name}</p>
                    <XMarkIcon
                      class="size-4 cursor-pointer"
                      onClick={(e) => {
                        e.stopPropagation();
                        handleDeleteTag(tag.id);
                      }}
                    />
                  </div>
                ))}
                <button
                  class="mt-2 flex w-full cursor-pointer flex-row items-center gap-2"
                  onClick={() => {
                    setShowAddSecondTag(!showAddSecondTag);
                    setTimeout(() => addSecondTagRef.current?.focus(), 100);
                  }}
                >
                  <PlusCircleIcon class="size-5" />
                  <span>Добавить</span>
                </button>
              </div>
              {showAddSecondTag && (
                <div class="flex w-full flex-row items-center rounded-[4rem] bg-white px-8 py-4 text-xs">
                  <input placeholder="Введите текст" class="flex-1 outline-0" ref={addSecondTagRef} />
                  <CheckIcon class="size-6 cursor-pointer" onClick={handleCreateTag} />
                </div>
              )}
            </div>
          )}
        </div>
      </ModalWindow>
    </>
  );
};

ModalTags.displayName = "AHModalTags";

export default ModalTags;
