"use client";

import React, {
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
} from "react";
import { useDispatch, useSelector } from "react-redux";

import styles from "@/components/administrator/UsersLogin/userlogin.module.css";

import { setNotification } from "@/utils/store/features/ui/notification.slice";
import { useSearch } from "@/hooks/useSearch";
import { isEmptyObject, spliceObject } from "@/app/library/library";

import Table from "../Table/table";

import { FiSearch } from "react-icons/fi";
import { IoCloseOutline } from "react-icons/io5";
import useUserToken from "@/hooks/useUserToken";
import { selectUser } from "@/utils/store/features/ui/userdata.slice";
import { searchToken } from "@/services/users";
/**
 * @type {React.FC <{
 *     initialData: any[];
 *     limit: number;
 *     sort: object;
 * }>}
 * @returns
 */
const UsersLoginData = (props) => {
  const dispatch = useDispatch();
  const searchref = useRef(null);

  const [users, setUsers] = useState(props.initialData);
  const [isLoading, setIsLoading] = useState(false);
  const user = useSelector(selectUser);

  const usersData = useMemo(
    () =>
      users?.map((userData) => {
        const {
          selected: { user },
          spliced: optional,
        } = spliceObject(userData, ["user"]);
        const location = spliceObject(
          optional,
          ["village", "municipality", "city", "region"],
          false
        ).selected;
        const point = spliceObject(
          optional,
          ["latitude", "longitude", "ip", "org"],
          false
        ).selected;

        return {
          ...user,
          uid: optional.uid, // for key
          optional,
          location,
          point,
          location: "Location", // location action button
          revoke: userData.revoke ? "Grant" : "Revoke", // revoke action button
        };
      }),
    [users]
  );

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

  const setData = useCallback((data) => {
    setUsers(data);
  }, []);

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

  return (
    <div className={styles.post_container}>
      <div className={styles.post_header}>
        <div className={styles.header_wrapper}>
          <h1>Active Users</h1>
          <div className={styles.post_action}></div>
        </div>
        <div className={styles.header_wrapper}>
          <form
            className={styles.search_container}
            onSubmit={handleSubmit}>
            <FiSearch />
            <input
              type="text"
              ref={searchref}
              placeholder="Search User"
              onInput={handleInput}
              onFocus={() => {
                if (!isSearch) setInitialData(users);

                setSearchFn(searchToken);
                setSetDataFn(setUsers);
              }}
            />
            {isSearch && (
              <IoCloseOutline
                onClick={() => {
                  searchref.current.value = "";
                  cancel();
                }}
                style={{ cursor: "pointer" }}
              />
            )}
          </form>
        </div>
      </div>
      <Table
        data={usersData}
        role={{
          name: "Name",
          username: "Username",
          role: "Role",
          "optional.display_name": "Address",
          "point.ip": "IP",
          "point.org": "Provider",
          location: "Location",
          revoke: "Revoke",
        }}
        style={{
          name: { minWidth: "300px", fontWeight: "600" },
          display_name: { minWidth: "300px" },
          role: { minWidth: "200px", textAlign: "center" },
          ip: { minWidth: "200px", textAlign: "center" },
          org: { minWidth: "200px", textAlign: "center" },
          location: { textDecoration: "underline", textAlign: "center" },
          revoke: { textDecoration: "underline", textAlign: "center" },
        }}
        itemClick={{
          location: (realdata, data, event) => {
            const point = isEmptyObject(realdata?.point)
              ? null
              : realdata.point;

            if (!point) {
              dispatch(
                setNotification({
                  status: true,
                  message:
                    "Location not found, user's browser does not support geolocation or not allowed.",
                  type: "error",
                  timeout: 3000,
                })
              );
              return;
            }

            const { latitude, longitude } = point;
            const query = `${latitude},${longitude}`;

            window.open(
              // `https://www.openstreetmap.org/?mlat=${latitude}&mlon=${longitude}#map=16/${latitude}/${longitude}`,
              `https://www.google.com/maps?q=${query}`,
              "_blank",
              "noopener,noreferrer"
            );
          },
          revoke: async (realdata, data, event) => {
            const id = realdata.optional._id;
            console.log({ realdata });
            const action = {
              Revoke: async () =>
                await revokeToken(id, (result) => {
                  setUsers((prev) =>
                    prev.map((user) =>
                      user._id === id ? { ...user, revoke: !user.revoke } : user
                    )
                  );
                }),
              Grant: async () =>
                await grantToken(id, (result) => {
                  setUsers((prev) =>
                    prev.map((user) =>
                      user._id === id ? { ...user, revoke: !user.revoke } : user
                    )
                  );
                }),
            };

            return await action[realdata.revoke]();
          },
        }}
      />
    </div>
  );
};

export default UsersLoginData;
