"use client";

import React, {
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
} from "react";

import styles from "@/components/administrator/PostData/postsdata.module.css";

import Pagination from "@/components/ui/Pagination/pagination";
import Loader from "@/components/web/Loader/loader";
import Table from "@/components/administrator/Table/table";
import NewPost from "@/components/administrator/NewPost/new.post";

import { FiSearch } from "react-icons/fi";
import { IoCloseOutline } from "react-icons/io5";
import { useSearch } from "@/hooks/useSearch";
import usePostManagement from "@/hooks/usePostManagement";
import { spliceObject, toRelativeDay } from "@/app/library/library";
import { useSelector } from "react-redux";
import { selectPostLock } from "@/utils/store/features/data/post.lock";
import { selectUser } from "@/utils/store/features/ui/userdata.slice";
import { postsServices } from "@/app/services/api/posts.services";
import Image from "next/image";

/**
 * @type {React.FC <{
 *     initialData: any[];
 *     limit: number;
 *     lockPostData: any[];
 * }>}
 * @returns
 */
const PostsData = (props) => {
  const searchref = useRef(null);

  const [posts, setPosts] = useState(props.initialData.data);
  const [selected, setSelected] = useState([]);
  const [isLoading, setIsLoading] = useState(false);

  const postLock = useSelector(selectPostLock);
  const user = useSelector(selectUser);

  const { deleteconfirmMultiple, multipleUpdatePost, handleClickToEdit } =
    usePostManagement();

  const postData = useMemo(() => {
    const formatLockData = (item) => {
      const isMe = item.user._id === user._id;
      return {
        ...item,
        status: isMe
          ? "You are Currently Editing"
          : `${item.user.name} is Currently Editing`,
      };
    };
    const _postLock = Array.isArray(postLock)
      ? postLock.map(formatLockData)
      : props.lockPostData?.map(formatLockData);

    return posts.map((post) => {
      const onEditing = _postLock.find((item) => item.post_id === post._id);
      const isEditing = !!onEditing;

      return {
        ...post,
        title: (
          <div className={styles.title_post}>
            <Image
              src={
                (post.media.imagedata.url ||
                  // "http://localhost:3000/api/media/not-found.jpg") +
                  "http://localhost:3000/media/not-found.jpg") + "?w=70&h=70"
              }
              alt={post.title || "no title"}
              width={70}
              height={70}
              loading="lazy"
            />
            <div>
              <h4>
                {post.title}
                {isEditing ? <a title={onEditing.status}>🔒</a> : ""}
              </h4>
              <span>{post.subtitle || "-"}</span>
              <span>{post.slug}</span>
            </div>
          </div>
        ),
        edited: isEditing && onEditing.status,
        onEditing,
        isEditing,
        updated:
          post?.sync && post?.status === "published"
            ? "Is Clean"
            : "Not Published",
        modifiedAt: toRelativeDay(post.modifiedAt),
        createdAt: toRelativeDay(post.createdAt),
        categories: post.categories?.map((item) => item.name).join(", ") || "",
        tags: post.tags?.map((item) => item.name).join(", ") || "",
      };
    });
  }, [posts, postLock, user, props.lockPostData]);

  const {
    isLoading: loadSearch,
    isSearch,
    isError,
    handleInput,
    handleSubmit,
    setInitialData,
    setSearchFn,
    setSetDataFn,
    cancel,
  } = useSearch();

  const handleUpdateStatus = useCallback(
    async (status) => {
      await multipleUpdatePost(
        selected.map(
          (item) =>
            // remove unwanted keys
            spliceObject(item, [
              "title",
              "edited",
              "onEditing",
              "isEditing",
              "updated",
              "createdAt",
              "modifiedAt",
              "tags",
            ]).spliced
        ),
        status,
        (result) => {
          setPosts((prev) =>
            prev.map((item) =>
              result.map((post) => post._id).includes(item._id)
                ? result.find((post) => post._id === item._id)
                : item
            )
          );
        }
      );
      setSelected([]);
    },
    [multipleUpdatePost, selected]
  );

  const getSortedData = useCallback(async ({ page, limit }, sort) => {
    const data = await postsServices.getPosts({ page, limit }, sort);
    setPosts(data.data);
  }, []);

  useEffect(() => {
    setIsLoading(loadSearch);
  }, [loadSearch]);

  return (
    <div className={styles.post_container}>
      <div className={styles.post_header}>
        <div className={styles.header_wrapper}>
          <h1>Posts Management</h1>
          <div className={styles.post_action}>
            {selected.length > 0 && (
              <div className={styles.post_status}>
                <p>
                  Selected:{" "}
                  <span>
                    {selected.length} item{selected.length > 1 && "s"}
                  </span>{" "}
                </p>
                {selected.every((item) => item.status === "draft") && (
                  <p>
                    <span
                      className={styles.action}
                      onClick={async () =>
                        await handleUpdateStatus("published")
                      }>
                      Publish
                    </span>{" "}
                  </p>
                )}
                {selected.every((item) => item.status === "published") && (
                  <p>
                    <span
                      className={styles.action}
                      onClick={async () => await handleUpdateStatus("draft")}>
                      Unpublish
                    </span>{" "}
                  </p>
                )}
                <p>
                  <span
                    className={styles.action}
                    onClick={async () => {
                      const ids = selected.map((item) => item._id);
                      await deleteconfirmMultiple(ids, (result) => {
                        const idDeleted = result.map((item) => item._id);

                        setPosts((prev) =>
                          prev.filter((item) => !idDeleted.includes(item._id))
                        );
                        setSelected([]);
                      });
                    }}>
                    Delete
                  </span>{" "}
                </p>
              </div>
            )}
            <NewPost
              className={styles.post_button}
              fontSize={13}
              getPost={(result) => {
                setPosts((prev) => [result, ...prev]);
              }}>
              Add Post
            </NewPost>
          </div>
        </div>
        <div className={styles.header_wrapper}>
          <form
            className={styles.search_container}
            onSubmit={handleSubmit}>
            <FiSearch />
            <input
              type="text"
              ref={searchref}
              placeholder="Search Posts"
              onInput={handleInput}
              onFocus={() => {
                if (!isSearch) setInitialData(posts);

                setSearchFn(async (keyword) => {
                  return await postsServices.searchPosts(keyword);
                });
                setSetDataFn((data) => {
                  setPosts(data);
                });
              }}
            />
            {isSearch && (
              <IoCloseOutline
                onClick={() => {
                  searchref.current.value = "";
                  cancel();
                }}
                style={{ cursor: "pointer" }}
              />
            )}
          </form>
        </div>
      </div>
      {isLoading ? (
        <div className={styles.loader_container}>
          <div className={styles.loader}>
            <Loader
              color="#000"
              width={30}
            />
            <p>Getting data</p>
          </div>
        </div>
      ) : (
        <Table
          data={postData}
          selected={selected}
          limit={props.limit}
          role={{
            title: "Title",
            // edited: "Editing",
            // slug: "Slug",
            // subtitle: "Subtitle",
            categories: "Categories",
            tags: "Tags",
            status: "Status",
            updated: "Updated",
            modifiedAt: "Last Updated",
            createdAt: "Created Date",
          }}
          style={{
            status: {
              fontWeight: "600",
              textTransform: "capitalize",
              textAlign: "center",
            },
            updated: {
              fontWeight: "600",
              textTransform: "capitalize",
              textAlign: "center",
            },
            createdAt: { textAlign: "center" },
            modifiedAt: { textAlign: "center" },
            title: { minWidth: "290px", fontWeight: "600" },
          }}
          sortRole={{
            canSorting: true,
            excludeSorting: [
              "edited",
              "status",
              "updated",
              "categories",
              "tags",
            ],
            sortingFn: getSortedData,
          }}
          onClick={(data) => {
            handleClickToEdit(data, user);
          }}
          onSelected={(data) => {
            setSelected(data);
          }}
          onMouseEnter={(data) => {
            console.log(data);
          }}
        />
      )}
      {!isSearch && (
        <div className={styles.pagination}>
          <Pagination
            totalPage={props.initialData.totalPage}
            currentPage={props.initialData.page}
            getData={postsServices.getPosts}
            getIsLoading={(status) => setIsLoading(status)}
            setData={(data) => setPosts(data.data)}
            limit={props.limit}
          />
        </div>
      )}
    </div>
  );
};

export default PostsData;
