import { useEffect, useRef, useState } from "react";
import styles from "../../styles/exos/ModalCard.module.scss";
import { isBrowser, isEmpty, parseClassName } from "../../utils/utils.js";
import ExoPrinterForm from "./ExoPrinterForm.jsx";
import Tag from "../Tag.jsx";
import { HiOutlineTrash } from "react-icons/hi";
import { TiEdit } from "react-icons/ti";
import { AiOutlineClose } from "react-icons/ai";
import { notificationService } from "../../services/notification.service.js";
import { AlertType, useAlert } from "../../context/alert.context.js";
import { ExoEditForm } from "./ExoEditForm.jsx";
import {
  delExo,
  delTag,
  favExo,
  getExos,
  getModelFile,
  setTags,
} from "../../requests/requests.exos.js";
import { useMutation, useQuery, useQueryClient } from "react-query";
import { TagCreatable } from "./TagCreate.jsx";
import Link from "next/link";
import { HiOutlineDuplicate } from "react-icons/hi";
import { useSessionContext } from "../../context/session.context.js";
export default function ModalCard({ step, onClose, onDelete, tags, queryKey }) {
  
  const [tagMode, setTagMode] = useState(false);

  const alert = useAlert();
  const [edit, setEdit] = useState(false);
  const queryClient = useQueryClient();

  const {
    isLoading: isUpdating,
    isFetching,
    data: step_data,
  } = useQuery(
    ["exo-data", step.id_code],
    async () => await getExos(step.id_code),
    { initialData: step, refetchOnWindowFocus: !edit }
  );
  const [selected, setSelected] = useState([]);
  const [tagOptions, setTagOptions] = useState(
    tags.map((tag) => {
      return {
        ...tag,
        isDisabled: step_data.tags.map((t) => t.id_code).includes(tag.id_code),
      };
    })
  );
    const {authData} = useSessionContext()
  useEffect(() => {
    setTagOptions(
      tags.map((tag) => {
        return {
          ...tag,
          isDisabled: step_data.tags
            .map((t) => t.id_code)
            .includes(tag.id_code),
        };
      })
    );
    return () => {
      setTagOptions([]);
    };
  }, [step_data.tags, tags]);

  const { mutate: setTagMutate } = useMutation(
    async () => await setTags({ step: step.id_code, tags: [...selected] }),
    {
      onSuccess: (data) => {
        //queryClient.invalidateQueries(step.id_code);
        queryClient.setQueryData(['exo-data', step.id_code],(old) => {
          return {...old, tags: data.data.tags}
        })
        queryClient.setQueryData(queryKey, (old) => {
          console.log('TEST OLD', old)
          return {
            ...old,
            results: [
              ...old.results.map((r) => {
                if (r.id_code === data.data.id_code) {
                  return { ...r, tags: data.data.tags };
                }
                return r;
              }),
            ],
          };
        });
        queryClient.invalidateQueries("tags");
        queryClient.invalidateQueries(queryKey[0], { inactive: true });

        setSelected([]);
        notificationService.success("Tags", `Tags de ${step.name} modifiés !`, {
          autoClose: true,
        });
        setTagMode(false);
      },
      onError: (e) => {
        console.log('error', e)
        notificationService.error(
          "Erreur",
          `Les tags de ${step.name} n'ont pu être modifiés !`
        );
      },
    }
  );

  const { mutate: delTagMutate } = useMutation(
    async (tag) => {
      return await delTag({ tag: tag, step: step.id_code });
    },
    {
      onSuccess: (data) => {
        var tagsSelected = queryKey[2].tags || null;
        if (tagsSelected && tagsSelected.includes(data.data.tagId)) {
          queryClient.invalidateQueries(queryKey);
        }
        queryClient.setQueryData(["exo-data", step.id_code], (old) => {
          return { ...old, tags: data.data.tags };
        });
        queryClient.setQueryData(queryKey, (old) => {
          
          return {
            ...old,
            results: [
              ...old.results.map((r) => {
                if (r.id_code === data.data.id_code) {
                  return { ...r, tags: data.data.tags };
                }
                return r;
              }),
            ],
          };
        });
        queryClient.invalidateQueries(queryKey[0], { inactive: true });

        queryClient.invalidateQueries("tags");
        notificationService.success(
          "Tags",
          `Tag ${data.data.name} retiré à ${step.name} !`,
          {
            autoClose: true,
          }
        );
        setTagMode(false);
      },
      onError: () => {
        notificationService.error(
          "Erreur",
          `Le tag n'a pu être retiré de ${step.name} !`
        );
      },
    }
  );

  
  const [full, setFull] = useState({ state: false, fade: false });
  const fadeFull = (state) => {
    setFull({ state: !state, fade: state });
    setTimeout(() => {
      setFull({ state: state, fade: false });
    }, 300);
  };

  return (
    <div
      className={styles["ex_card--full"]}
      onKeyDown={(e) => {
        if (e.code == "Escape") {
          onClose();
        }
      }}
      //id={"card-" + step_data.id_code}
    >
      <div
        className={parseClassName([
          styles["ex_card--body"],
          edit ? "marginb-p0" : undefined,
          full.fade ? styles["ex_card-fade"] : undefined,
          full.fade || full.state ? styles["ex_card--big"] : undefined,
          full.state ? "vh-100" : undefined,
          edit ? styles["edit-card"] : undefined,
        ])}
      >
        {isFetching && (
          <div className={styles["updating"]}>
            <span className="loader"></span>
          </div>
        )}

        {!(isFetching || isUpdating) && (
          <>
            {!edit && full.state == false && (
              <div className={styles["ex_card--title"]}>
                {step_data.name}
                {step_data.original != null && (
                  <Link href={`/exercices/${step_data.original}`}>
                    <a title="Voir l'exercice original">Exercice original</a>
                  </Link>
                )}
                {!step_data.isUser && (
                  <p className={styles.author}>{step_data.author.username}</p>
                )}
              </div>
            )}

            {!edit && full.state == false && (
              <ExoPrinterForm step={step_data} />
            )}

            {edit && (
              <ExoEditForm
                step={step_data}
                cancel={() => {
                  setEdit(false);
                }}
                setFull={fadeFull}
                full={full.state}
              />
            )}
          </>
        )}
      </div>
      {!(isFetching || isUpdating) && full.state == false && !isEmpty(authData)&& (
        <div
          className={parseClassName([
            styles["ex_card--footer"],
            tagMode == true
              ? styles["tag_card"]
              : styles["ex_card--footer-not-tag"],
          ])}
        >
          {tagMode == false && !edit && full.state == false && (
            <>
              <div className={styles["tag--container"]}>
                {step_data.tags.map((t, i) => {
                  return <Tag key={i} tag={t} onDelete={delTagMutate} />;
                })}
              </div>
              <div
                onClick={() => {
                  setTagMode(true);
                }}
                className={styles["ex_card--add-tag"]}
              >
                {" "}
                <hr /> <p> +</p>
              </div>
            </>
          )}
          {tagMode && !edit && full.state == false && (
            <>
              <TagCreatable
                options={tagOptions}
                selectOption={setSelected}
                select={selected}
                onCreate={setTagOptions}
              />
              <div className="margint-p3 flex-column">
                <button onClick={setTagMutate} className="exo-btn">
                  Valider
                </button>
                <button
                  onClick={() => {
                    setTagMode(false);
                    setSelected([]);
                  }}
                  className="cancel-btn"
                >
                  Annuler
                </button>
              </div>
            </>
          )}
        </div>
      )}
      {!edit && !(isFetching || isUpdating) && full.state == false && (
        <div className={styles["icon-container"]}>
          {/* <Delete className={styles['icon']}/> */}

          <AiOutlineClose
            className={parseClassName([styles["icon"]])}
            onClick={onClose}
          />
          {isBrowser &&
            localStorage.getItem("token") != null &&
            !step_data.isUser && (
              <HiOutlineDuplicate
                onClick={() => {
                  favExo(step.id_code).then((res) => {
                    setRegistered(res.isRegistered);
                  });
                }}
              />
            )}
          {step_data.isUser == true && (
            <div>
              <HiOutlineTrash
                className={parseClassName([styles["icon"], styles["delete"]])}
                onClick={() => {
                  alert.alert({
                    title: "Êtes-vous sûr ?",
                    active: true,
                    message: `Vous allez supprimer l'exercice ${step_data.name} ! Cette action est irréversible !`,
                    type: AlertType.Warning,
                    validate: () => {
                      delExo(step.id_code).then(() => {
                        notificationService.success(
                          "Suppression",
                          `Exercice ${step_data.name} supprimé !`,
                          { autoClose: true, keepAfterRouteChange: true }
                        );
                        onDelete(step.id_code);
                        onClose();
                      });
                    },
                  });
                }}
              />
              <TiEdit
                className={parseClassName([styles["icon"], styles["edit"]])}
                onClick={() => {
                  setEdit(true);
                }}
              />
            </div>
          )}
        </div>
      )}
    </div>
  );
}
