"use client";

import React, { useCallback, useMemo, useState } from "react";
import Link from "next/link";

import styles from "@/components/administrator/JoinBridge/joinbridge.module.css";

import { useSettingManagement } from "@/hooks/useSettingManagement";
import { normalizeURL } from "@/app/library/library";

import Input from "@/components/administrator/form/Input/input";
import Button from "@/components/ui/Button/button";
import Table from "../Table/table";
import Loader from "@/components/web/Loader/loader";
import Switch from "@/components/ui/Switch/switch";

import { TbArrowFork, TbBrandSpeedtest } from "react-icons/tb";
import { MdDeleteForever } from "react-icons/md";
import { PiWarningDuotone } from "react-icons/pi";

/**
 *
 * @type {React.FC<{
 *    bridgeSettings: any;
 *    status: boolean;
 *    ID: string;
 * }>}
 *
 * @returns {JSX.Element}
 */
const JoinBridge = (props) => {
  const [endpoint, setEndpoint] = useState({
    name: "",
    url: "",
    status: false,
  });
  const [isLoading, setIsLoading] = useState({
    addData: false,
    action: false,
    auth: false,
  });
  const [isauthorized, setIsAuthorized] = useState(false);
  const [data, setData] = useState(props?.bridgeSettings?.endpoints || []);
  const { testBridgeUrl, updateEndpoints, getAuthorization } =
    useSettingManagement();

  // action
  const testUrl = useCallback(
    (url, api_key) => {
      if (isLoading.action) return;

      let newData;
      setIsLoading((prev) => ({ ...prev, action: true }));
      testBridgeUrl(
        { url, api_key },
        async (result) => {
          setData((prev) => {
            newData = prev.map((item) =>
              item.url === url ? { ...item, status: true } : item
            );
            return newData;
          });
          await updateEndpoints(newData);
        },
        async () => {
          setData((prev) => {
            newData = prev.map((item) =>
              item.url === url ? { ...item, status: false } : item
            );

            return newData;
          });
          await updateEndpoints(newData);
        },
        async () => {
          setIsLoading((prev) => ({ ...prev, action: false }));
        }
      );
    },
    [testBridgeUrl, updateEndpoints, isLoading]
  );
  const deleteUrl = useCallback(
    (url) => {
      if (isLoading.action) return;
      setIsLoading((prev) => ({ ...prev, action: true }));

      const newData = data.filter((item) => item.url !== url);

      updateEndpoints(
        newData,
        () => {
          setData(newData);
        },
        null,
        () => {
          setIsLoading((prev) => ({ ...prev, action: false }));
        }
      );
    },
    [data, isLoading, updateEndpoints]
  );
  const updateStatus = useCallback(
    (url, status) => {
      if (isLoading.action) return;
      setIsLoading((prev) => ({ ...prev, action: true }));

      const newData = data.map((item) =>
        item.url === url ? { ...item, status: status } : item
      );

      updateEndpoints(
        newData,
        () => {
          setData(newData);
        },
        null,
        () => {
          setIsLoading((prev) => ({ ...prev, action: false }));
        }
      );
    },
    [data, isLoading, updateEndpoints]
  );
  const authorization = useCallback(async () => {
    if (isLoading.auth) return;
    setIsLoading((prev) => ({ ...prev, auth: true }));
    await getAuthorization(
      {
        url: endpoint.url,
        ID: props.ID,
      },
      (data) => {
        setEndpoint((prev) => ({ ...prev, ...data, status: true }));
        setIsAuthorized(true);
      },
      null,
      () => {
        setIsLoading((prev) => ({ ...prev, auth: false }));
      }
    );
  }, [props, endpoint, isLoading, getAuthorization]);

  const displayData = useMemo(
    () =>
      data.map((item) => ({
        ...item,
        status: (
          <Switch
            value={item.status}
            disabled={isLoading.action}
            onChange={(value) => {
              updateStatus(item.url, value);
            }}
          />
        ),
        action: (
          <span className={styles.actions}>
            <MdDeleteForever
              title="Delete Endpoint"
              style={{ opacity: isLoading.action ? "0.5" : "1" }}
              size={20}
              className={`${styles.action_icon} ${styles.danger}`}
              onClick={() => deleteUrl(item.url)}
            />
            <TbBrandSpeedtest
              title="Test Endpoint"
              size={20}
              style={{ opacity: isLoading.action ? "0.5" : "1" }}
              className={`${styles.action_icon} ${styles.success}`}
              onClick={() => testUrl(item.url, item.API_KEY)}
            />
          </span>
        ),
      })),
    [data, isLoading, testUrl, deleteUrl, updateStatus]
  );
  const isValid = useMemo(() => {
    return (
      (data.some((item) => item.url !== endpoint.url) || data.length === 0) &&
      Object.values(endpoint).every((item) => item)
    );
  }, [endpoint, data]);

  return (
    <div className={styles.container}>
      <div className={styles.header}>
        <div className={styles.header_title}>
          <h3>
            <TbArrowFork /> Join Bridge
          </h3>
          <p>
            {props.status ? (
              "You can manage content across the company and define API endpoints for data exchange"
            ) : (
              <span className={styles.warning}>
                <PiWarningDuotone /> Generate CMS ID first on{" "}
                <Link href={"/dashboard/settings/general"}>
                  General Settings
                </Link>
              </span>
            )}
          </p>
        </div>
      </div>
      <div
        className={styles.content}
        style={props.status ? {} : { opacity: "0.5", pointerEvents: "none" }}>
        <div className={styles.input_container}>
          <div className={styles.input_content}>
            <Input
              className={styles.input}
              label="Name (alias)"
              value={endpoint?.name}
              onChange={(e) =>
                setEndpoint({ ...endpoint, name: e.target.value })
              }
            />
            <Input
              className={styles.input}
              label="URL"
              value={endpoint?.url}
              onChange={(e) => {
                setEndpoint({
                  ...endpoint,
                  url: e.target.value,
                  API_KEY: "",
                  status: false,
                });
                setIsAuthorized(false);
              }}
              error={{
                status: endpoint.url && !isauthorized,
                message: "This url is not Authorized. Please authorize first.",
              }}
              continouslyFrom={
                endpoint.url.startsWith("http") ? "" : "https://"
              }
            />
            <div className={styles.action_horizontal}>
              <Button
                className={styles.button}
                disabled={
                  !endpoint.url ||
                  data.some((item) =>
                    new RegExp(normalizeURL(endpoint.url)).test(
                      normalizeURL(item.url)
                    )
                  ) ||
                  isauthorized
                }
                onClick={() => authorization()}>
                {isLoading.auth && <Loader color="#fff" />}
                Authorization
              </Button>
              <Button
                className={styles.button}
                disabled={!isValid || isLoading.addData}
                onClick={() => {
                  const sentData = [...data, endpoint];

                  setIsLoading({ ...isLoading, addData: true });
                  updateEndpoints(
                    sentData,
                    (data) => {
                      setData(data.endpoints);
                      setEndpoint({
                        name: "",
                        url: "",
                        status: false,
                        API_KEY: "",
                      });
                    },
                    null,
                    () => {
                      setIsLoading({ ...isLoading, addData: false });
                    }
                  );
                }}>
                {isLoading.addData && <Loader color="#fff" />}
                Add Endpoint
              </Button>
            </div>
          </div>
        </div>
        <span className={styles.separator}></span>
        <Table
          role={{
            name: "Name",
            url: "URL",
            status: "Status",
            action: "Action",
          }}
          style={{
            action: {
              minWidth: "30px !important",
              maxWidth: "30px !important",
            },
          }}
          data={displayData}
          showEmptyStatus={false}
        />
      </div>
    </div>
  );
};

export default JoinBridge;
