"use client";

import React, {
  memo,
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
} from "react";
import styles from "@/components/administrator/PostEditor/posteditor.module.css";

import { useDispatch } from "react-redux";
import {
  capitalizeEachWord,
  filterEmptyValue,
  objectFilterKey,
  objecthasKey,
  slugify,
  spliceObject,
  toRelativeDay,
  unmergingCategory,
} from "@/app/library/library";
import { AnimatePresence, motion } from "framer-motion";

// components
import Button from "@/components/ui/Button/button";
import Input from "@/components/administrator/form/Input/input";
import Content from "./FeatureForms/content.form";
import SEO from "./FeatureForms/seo.form";
import Meta from "./FeatureForms/meta.form";

// icons
import usePostManagement from "@/hooks/usePostManagement";
import { addModal } from "@/utils/store/features/ui/modal.slice";
import PostHeartBeat from "@/providers/post.heartbeat";
import PostSwitched from "@/components/administrator/modals/PostSwitched/post.switched";
import { usePathname, useSearchParams } from "next/navigation";
import JadwalPelatihan from "./FeatureForms/jadwal.pelatihan";
import InputMultiple from "../form/InputMultiple/input.multiple";
import Dropdown from "../form/Dropdown/dropdown";

/**
 * Post Editor Component
 * @type {React.FC & {
 *    tab: number;
 *    tags: any[];
 *    categories: any[];
 *    currentSatus: string;
 *    data: any;
 *    post_lock: any;
 *    post_publish: any;
 *    additional_data: any;
 *    uid: any;
 * }>}
 */
const PostEditorComponent = (props) => {
  const dispatch = useDispatch();
  const savebuttonref = useRef(null);

  const pathname = usePathname();
  const searchParams = useSearchParams();

  const [constData, setConstData] = useState(
    objectFilterKey(props.data, "imagedata")
  );
  const [data, setData] = useState(props.data);
  const [media, setMedia] = useState({});
  const [selectedTab, setSelectedTab] = useState(props.tab);
  const [isLoading, setIsLoading] = useState({
    on: "",
    status: false,
  });
  const [term, setTerm] = useState({
    categories: props.categories,
    tags: props.tags,
  });
  const [hoverTab, setHoverTab] = useState(props.tab);

  const isChange = useMemo(
    () => JSON.stringify(constData) !== JSON.stringify(data),
    [constData, data]
  );

  const { save, publish, unpublish, revert, deleteconfirm } =
    usePostManagement();

  const filterMediaData = (data) => {
    const hasMediaData = objecthasKey(data, "imagedata");
    if (hasMediaData) {
      const imagedata = {
        thumbnail: data?.media?.imagedata,
        "meta-image": data?.metadata?.imagedata,
      };

      const removedImageData = objectFilterKey(data, "imagedata");
      setData(removedImageData);

      // setMedia(filterEmptyValue(imagedata));
      setMedia(filterEmptyValue(imagedata));
      return removedImageData;
    }

    return data;
  };

  const filterData = useCallback((result) => {
    let newData = filterMediaData(result);
    const unwantedKeys = ["post_publish", "post_lock"];
    const isPostPublish = unwantedKeys.some((key) =>
      objecthasKey(newData, key)
    );

    if (isPostPublish) newData = spliceObject(newData, unwantedKeys).spliced;

    setConstData(newData);
    setData(newData);

    return newData;
  }, []);

  const onSave = useCallback(async () => {
    if (!isChange) return;
    setIsLoading({ on: "Saving", status: true });

    await save(data, (result) => {
      filterData(result);

      setIsLoading({ on: "", status: false });
    });
  }, [data, isChange, save, filterData]);

  const onPublish = useCallback(async () => {
    setIsLoading({ on: "Publishing", status: true });

    await publish(data, (result) => {
      filterData(result);

      setIsLoading({ on: "", status: false });
    });
  }, [data, publish, filterData]);

  const onRevert = useCallback(async () => {
    setIsLoading({ on: "Reverting", status: true });

    await revert(data, (result) => {
      const newData = filterData(result);

      setConstData(newData);
      setIsLoading({ on: "", status: false });
    });
  }, [data, revert, filterData]);

  const onUnpublish = useCallback(async () => {
    setIsLoading({ on: "Unpublishing", status: true });

    await unpublish(data, (result) => {
      filterData(result);

      setIsLoading({ on: "", status: false });
    });
  }, [data, unpublish, filterData]);

  const setTermData = useCallback(
    (data) => {
      if (data && typeof data === "function") {
        const newData = data(term);
        setTerm(newData);
        return;
      }

      setTerm(data);
    },
    [term]
  );

  useEffect(() => {
    const handleKeyDown = (event) => {
      const key = [
        {
          on: event.ctrlKey && event.key === "s",
          action: () => {
            event.preventDefault();
            event.stopPropagation();

            onSave();
          },
        },
        {
          on: event.ctrlKey && event.key === "p",
          action: () => {
            event.preventDefault();
            event.stopPropagation();
            onPublish();
          },
        },
        {
          on: event.ctrlKey && event.key === "u",
          action: () => {
            event.preventDefault();
            event.stopPropagation();
            onUnpublish();
          },
        },
      ];

      return key.find((k) => k.on)?.action();
    };

    // add event keydown
    document.addEventListener("keydown", handleKeyDown);
    return () => document.removeEventListener("keydown", handleKeyDown);
  }, [onPublish, onSave, onUnpublish, data]);

  useEffect(() => {
    filterMediaData(props.data);
  }, [props]);

  useEffect(() => {
    if (props.post_lock === undefined) return;

    if (!props.post_lock?.own) {
      dispatch(
        addModal({
          status: !props.post_lock?.own,
          component: PostSwitched,
          data: props.post_lock || {},
          cannotClose: true,
        })
      );
    }
  }, [props, dispatch]);

  return (
    <PostHeartBeat
      uid={props.uid}
      visibility={props.post_lock?.own}>
      <div className={styles.join_container}>
        <Dropdown
          className={styles.input}
          label="Select Unit"
          data={[
            { name: "Master", API_KEY: "0" },
            ...(props?.additional_data?.joinBridge || []),
          ]}
          display="name"
        />
      </div>
      <h1 className={styles.post_title}>
        {data?.title || props.data?.title || "Untitled"}{" "}
      </h1>
      <div className={styles.container}>
        <div className={styles.editor_header}>
          <div className={styles.editor_status}>
            <p>
              Status :{" "}
              <span>
                {capitalizeEachWord(constData.status)}
                {(() => {
                  if (isChange) return " (Changed)";
                  if (constData.status === "published" && !constData.sync)
                    return " (Updated but Not Published)";
                })()}
              </span>
              {!constData.sync && constData.status === "published" && (
                <span>
                  {" "}
                  —{" "}
                  <span
                    className={styles.action}
                    onClick={() => onRevert()}>
                    Revert to Publish
                  </span>
                </span>
              )}
            </p>
            <p>
              Last Updated :{" "}
              <span>{toRelativeDay(constData.modifiedAt) || ""}</span>
            </p>
            <p>
              Created at :{" "}
              <span>{toRelativeDay(constData.createdAt) || ""}</span>
            </p>
            {constData.status === "published" && (
              <p>
                Action:{" "}
                <span
                  className={styles.action}
                  onClick={() => {
                    window.open(
                      `${window.location.origin}/post/${props?.post_publish.slug}`,
                      "_blank",
                      "noopener,noreferrer"
                    );
                  }}>
                  Preview
                </span>
              </p>
            )}
            {isLoading.status && (
              <p>
                <span>{isLoading.on}</span>
              </p>
            )}
          </div>
        </div>
        <div className={styles.editor_content}>
          <div className={`${styles.editor_body}`}>
            <div className={styles.editor_post}>
              <Input
                label="Title"
                className={styles.input}
                value={data.title || ""}
                labelclassname={styles.label}
                onChange={(e) =>
                  setData((prev) => ({
                    ...prev,
                    title: e.target.value,
                    slug: slugify(e.target.value),
                    metadata: {
                      ...(prev?.metadata || {}),
                      title: e.target.value,
                    },
                  }))
                }
              />
              <Input
                label="Subtitle"
                className={styles.input}
                value={data.subtitle || ""}
                labelclassname={styles.label}
                onChange={(e) =>
                  setData((prev) => ({ ...prev, subtitle: e.target.value }))
                }
              />
            </div>
            <div className={styles.editor_tab_container}>
              <div className={styles.editor_tab}>
                {["Content", "Meta", "SEO", "Jadwal Pelatihan"].map(
                  (item, index) => (
                    <motion.div
                      key={index}
                      onHoverStart={() => setHoverTab(index)}
                      onHoverEnd={() => setHoverTab(selectedTab)}
                      onClick={() => {
                        setSelectedTab(index);

                        const params = new URLSearchParams(searchParams);
                        params.set("tab", index);

                        window.history.replaceState(
                          null,
                          "",
                          `${pathname}?${params.toString()}`
                        );
                      }}
                      className={styles.tab}>
                      {item}
                      {index === hoverTab ? (
                        <motion.div
                          className={styles.underline}
                          layoutId="underline"
                          id="underline"
                        />
                      ) : null}
                    </motion.div>
                  )
                )}
              </div>
              <div className={styles.editor_content}>
                <AnimatePresence mode="wait">
                  <motion.div
                    key={selectedTab}
                    initial={{ y: 10, opacity: 0 }}
                    animate={{ y: 0, opacity: 1 }}
                    exit={{ y: -10, opacity: 0 }}
                    transition={{ duration: 0.2 }}
                    className={styles.editor_menu_content}>
                    {(() => {
                      const menu = [Content, Meta, SEO, JadwalPelatihan];
                      const Component = menu[selectedTab];
                      return (
                        <Component
                          data={data}
                          setData={setData}
                          additional_data={props.additional_data}
                          other={{
                            categories: unmergingCategory(term.categories),
                            tags: term.tags,
                          }}
                          setTerm={setTermData}
                          media={media}
                          setMedia={setMedia}
                          save={() => savebuttonref.current.click()}
                        />
                      );
                    })()}
                  </motion.div>
                </AnimatePresence>
              </div>
            </div>
          </div>
          <div className={`${styles.editor_body} ${styles.aside}`}>
            <Button
              ref={savebuttonref}
              title="Save (Ctrl + S)"
              className={`${styles.button} ${styles.reverse}`}
              disabled={!isChange || isLoading.status}
              onClick={() => onSave()}>
              Save
            </Button>
            <Button
              className={`${styles.button}`}
              title="Publish (Ctrl + P)"
              // enable on const data status is published and not sync
              disabled={
                (constData.status === "published" && constData.sync) ||
                isLoading.status
              }
              onClick={() => onPublish()}>
              Publish Changes
            </Button>
            <Button
              className={`${styles.button} ${styles.danger}`}
              title="Unpublish (Ctrl + U)"
              disabled={constData.status !== "published" || isLoading.status}
              onClick={() => onUnpublish()}>
              Unpublish
            </Button>
            <Button
              className={`${styles.button} ${styles.danger_reverse}`}
              // title="Unpublish (Ctrl + U)"
              disabled={isLoading.status}
              onClick={() => deleteconfirm(data)}>
              Delete Post
            </Button>
          </div>
        </div>
      </div>
    </PostHeartBeat>
  );
};

const PostEditor = memo(PostEditorComponent);
export default PostEditor;
