import React, { useCallback, useEffect, useRef, useState } from "react";
import { Command } from "cmdk";
//import { EditLabel } from "./EditLabel";
import {
  createFlow,
  createFolder,
  useFolder,
  useFolders,
  deleteFolder,
  deleteFlow,
  getFullFlowData,
  updateFlowData,
  updateFolder,
} from "../EdgebrixProvider/EdgebrixProvider";
import { Spinner } from "../Sppiner";
import { SmallSpinner } from "../Sppiner";
import { func } from "prop-types";
import Skeleton from "react-loading-skeleton";
import { useCurrentFlow } from "../../hooks/useCurrentFlow";
import { useCurrentFolder } from "../../hooks/useCurrentFolder";
import { Page, usePages } from "../../hooks/usePages";
import { ReactFlowInstance, useReactFlow } from "reactflow";
import Editable from "../FlowBar/EditLabel/Editable";
import Item from "./Item";
import { toPng } from "html-to-image";
import { useWorkingFlow } from "../../hooks/useWorkingFlow";
import { useWorkingFolder } from "../../hooks/useWorkingFolder";
import { api_endpoint, letterCase, truncate, useUniqueId } from "../lib/utils";
import LoadingIcon from "../FlowBar/LoadingIcon";
import { AiOutlineHome, AiOutlineShareAlt } from "react-icons/ai";
import { useToken } from "../../hooks/useToken";
import { useWording } from "../../hooks/useWording";
import "./vercel.scss";

export function FolderManager({
  reactFlowInstance,
  setRename,
}: {
  reactFlowInstance: ReactFlowInstance | null;
  setRename: (rename: boolean) => void;
}) {
  const ref = React.useRef<HTMLDivElement | null>(null);
  const inputRef = React.useRef<HTMLInputElement | null>(null);

  const { token, setToken } = useToken();

  const { flow: flow_wording, folder: folder_wording } = useWording();

  const {
    flow: _flow,
    currentFlowId: flowId,
    setCurrentFlowId: setFlowId,
    setFlow,
  } = useCurrentFlow();
  const {
    folder: _folder,
    currentFolderId: folderId,
    setCurrentFolderId: setFolderId,
    setFolder,
  } = useCurrentFolder();

  //setFlowId(_flow_id);
  //  setFolderId(_folder_id);

  const { workingFlowId, setWorkingFlowId } = useWorkingFlow();
  const { workingFolderId, setWorkingFolderId } = useWorkingFolder();

  const { pages, addPage, setPages } = usePages();

  const [inputValue, setInputValue] = React.useState("");

  const [isInEditMode, setIsInEditMode] = React.useState(false);

  const activePage = pages[pages.length - 1];
  const isHome = activePage.name === "/";

  const popPage = React.useCallback(() => {
    const x = Array<Page>(...pages);
    x.splice(-1, 1);
    setPages(x);
  }, [pages]);

  function bounce() {
    if (ref.current) {
      ref.current.style.transform = "scale(0.96)";
      setTimeout(() => {
        if (ref.current) {
          ref.current.style.transform = "";
        }
      }, 100);

      setInputValue("");
    }
  }

  function handleInoutFoucse() {
    if (inputRef.current) {
      inputRef.current.focus();
    }
  }

  return (
    <div className="vercel">
      <Command
        ref={ref}
        onKeyDown={(e: React.KeyboardEvent) => {
          if (isInEditMode) {
            return;
          }
          if (e.key === "Enter") {
            bounce();
          }

          if (isHome || inputValue.length) {
            return;
          }

          if (e.key === "Backspace") {
            e.preventDefault();
            popPage();
            bounce();
          }
        }}
      >
        <div>
          {pages &&
            pages.map((p) => (
              <>
                {p.type !== "home" && (
                  <>
                    <div key={useUniqueId()} cmdk-vercel-badge="">
                      {truncate(p.name, 15)}
                    </div>
                  </>
                )}
                {p.type === "home" && (
                  <>
                    <div key={useUniqueId()} cmdk-vercel-badge="">
                      {/* <AiOutlineHome height={8} /> */}
                      Home
                    </div>
                  </>
                )}
              </>
            ))}
        </div>

        <Command.Input
          ref={inputRef}
          autoFocus
          placeholder={`Search for ${
            isHome
              ? `${folder_wording.toLowerCase()}s`
              : `${flow_wording.toLowerCase()}s`
          }...`}
          onValueChange={(value) => {
            setInputValue(value);
          }}
        />

        <Command.List>
          {/* <Command.Empty>No results found.</Command.Empty> */}
          {activePage.type === "home" && (
            <RootFolders
              folder_wording={folder_wording}
              token={token}
              showFlowsForFolder={(folder_name: string, folder_id: string) => {
                setInputValue("");
                setPages([...pages, { name: folder_name, type: "folder" }]);
                //setFolderId(folder_id);
                setWorkingFolderId(folder_id);
              }}
            />
          )}

          {activePage.type === "folder" && (
            <ShowFlows
              flow_wording={flow_wording}
              folder_wording={folder_wording}
              focusOnInput={handleInoutFoucse}
              setIsInEditMode={setIsInEditMode}
              popPage={popPage}
              token={token}
              folder_id={workingFolderId}
              folder_name={activePage.name}
              setFlows={(flow_name: string, flow_id: string) => {
                setInputValue("");
                setPages([...pages, { name: flow_name, type: "flow" }]);
                //setFlowId(flow_id);
                setWorkingFlowId(flow_id);
              }}
            />
          )}

          {activePage.type === "flow" && (
            <ShowFlow
              focusOnInput={handleInoutFoucse}
              setIsInEditMode={setIsInEditMode}
              token={token}
              popPage={popPage}
              reactFlowInstance={reactFlowInstance}
              flow_id={workingFlowId}
              flow_name={activePage.name}
              folder_id={workingFolderId}
              setFlowId={setWorkingFlowId}
              setFolderId={setWorkingFolderId}
              // setFlowId={setFlowId}
              //setFolderId={setFolderId}
              setRename={setRename}
            />
          )}
        </Command.List>
      </Command>
    </div>
  );
}

//To show all relevant actino to the selected flow
function ShowFlow({
  focusOnInput,
  setIsInEditMode,
  token,
  reactFlowInstance,
  popPage,
  flow_id,
  flow_name,
  folder_id,
  setFlowId,
  setFolderId,
  setRename,
}: {
  focusOnInput: () => void;
  setIsInEditMode: (isInEditMode: boolean) => void;
  popPage: () => void;
  token: string;
  reactFlowInstance: ReactFlowInstance | null;
  flow_id: string;
  flow_name: string;
  folder_id: string;
  setFlowId: (flow_id: string) => void;
  setFolderId: (folder_id: string) => void;
  setRename: (rename: boolean) => void;
}) {
  const [deleteFlowInProgress, setDeleteFlowInProgress] = useState(false);
  const [isloadToCanvas, setIsLoadToCanvas] = useState(false);

  // const flow = getFullFlowData(folder_id, flow_id);

  const { setCurrentFlowId } = useCurrentFlow();
  const { setCurrentFolderId } = useCurrentFolder();

  const loadToCanvas = async () => {
    setIsLoadToCanvas(true);
    const rw = await getFullFlowData(folder_id, flow_id, token);

    if (reactFlowInstance) {
      reactFlowInstance.setNodes(rw?.data?.nodes || []);
      reactFlowInstance.setEdges(rw?.data?.edges || []);
    } else {
    }
    setFlowId(flow_id);
    setFolderId(folder_id);
    setCurrentFlowId(flow_id);
    setCurrentFolderId(folder_id);
    setIsLoadToCanvas(false);
  };

  const delete_flow = async () => {
    setDeleteFlowInProgress(true);
    await deleteFlow(folder_id, flow_id, token);
    setDeleteFlowInProgress(false);
    popPage();
  };

  const handleEditDone = async (value: string) => {
    focusOnInput();
    if (value !== flow_name) {
      await updateFlowData(folder_id, flow_id, { name: value }, {}, token);
      setRename(true);
    }
  };

  function downloadImage(dataUrl: any) {
    const a = document.createElement("a");

    a.setAttribute("download", "reactflow.png");
    a.setAttribute("href", dataUrl);
    a.click();
  }

  const saveAsImage = async () => {
    const input = document.querySelector(".react-flow");
    const el1: HTMLElement = input as HTMLElement; // 👈️ type assertion

    toPng(el1, {
      filter: (node) => {
        // we don't want to add the minimap and the controls to the image
        if (
          node?.classList?.contains("edgebrix") ||
          node?.classList?.contains("react-flow__minimap") ||
          node?.classList?.contains("react-flow__controls")
        ) {
          return false;
        }
        return true;
      },
    }).then(downloadImage);
  };

  return (
    <div>
      {/* <div>
        <div className="flex items-center justify-between">
          <div className="flex items-center">
            <img
              className="pl-8 pr-8 pb-8 pt-6"
              src="https://res.cloudinary.com/dhwxfvlrn/image/upload/v1670577383/photo-1670516537787-22e2d8de641f_gpjhvx.jpg"
              alt={flow_name}
            ></img>
          </div>
        </div>
      </div> */}

      <Item
        key={useUniqueId()}
        onSelect={async () => {
          await loadToCanvas();
        }}
      >
        <LoadToCanvasIcon inProgress={isloadToCanvas} />
        Load to canvas...
      </Item>
      <Editable
        callback={(value) => {
          setIsInEditMode(false);
          handleEditDone(value);
        }}
        setIsInEditMode={setIsInEditMode}
        text={flow_name}
        placeholder="Write a flow name"
        type="input"
        props={undefined}
      ></Editable>

      <Item
        key={useUniqueId()}
        onSelect={async () => {
          await delete_flow();
        }}
      >
        <DeleteIcon inProgress={deleteFlowInProgress} />
        <p>Delete</p>
        <p style={{ fontWeight: "bold" }}>{`${truncate(flow_name, 20)}...`}</p>
      </Item>

      {/* <Item
        onSelect={async () => {
          await saveAsImage();
        }}
      >
        <DeleteIcon inProgress={deleteFlowInProgress} />
        Save Image...
      </Item> */}
    </div>
  );
}
//Show all the flows in the selected folder
function ShowFlows({
  focusOnInput,
  setIsInEditMode,
  popPage,
  token,
  folder_id,
  folder_name,
  setFlows,
  flow_wording,
  folder_wording,
}: {
  focusOnInput: () => void;
  setIsInEditMode: (isInEditMode: boolean) => void;
  popPage: Function;
  token: string;
  folder_id: string;
  folder_name: string;
  setFlows: Function;
  flow_wording: string;
  folder_wording: string;
}) {
  const { isValidating, folderMutate, folder, folderError, isFolderLoading } =
    useFolder(folder_id);
  const [inProgress, setInProgress] = useState(false);
  const [deleteInProgress, setDeleteInProgress] = useState(false);
  const [shareInProgress, setShareInProgress] = useState(false);

  const createNewFlow = async () => {
    setInProgress(true);
    await createFlow(folder_id, token);
    folderMutate();
    setInProgress(false);
  };

  const deleteSelectedFolder = async () => {
    setDeleteInProgress(true);
    await deleteFolder(folder_id, token);
    popPage();
    //mutate();
    setDeleteInProgress(false);
  };

  const shareFolder = async () => {
    setShareInProgress(true);
    const tt = await fetch(`${api_endpoint}/folders/${folder_id}/share`, {
      method: "PUT",
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${token}`,
      },
      body: JSON.stringify({
        shared_with: ["*"],
      }),
    });

    const data = await tt.json();

    setShareInProgress(false);
  };

  const handleEditDone = async (value: string) => {
    focusOnInput();
    if (value !== folder_name) {
      await updateFolder(token, folder_id, { name: value });
      folderMutate();
    }
  };

  return (
    <>
      {isFolderLoading && (!folder || folder.flows > 0) && (
        <Command.Loading>
          <Spinner />
        </Command.Loading>
      )}

      {!isFolderLoading &&
        folder &&
        folder.flows &&
        folder.flows.length === 0 && (
          <>
            <p cmdk-empty="">{`No ${flow_wording.toLowerCase()}s found.`}</p>
          </>
        )}
      {folder &&
        folder.flows &&
        folder.flows.map((f: any) => {
          return (
            <Item
              key={useUniqueId()}
              onSelect={() => {
                setFlows(f.name, f.id);
              }}
            >
              <FlowIcon />
              {truncate(f.name, 40)}
              <p style={{ width: "0px", visibility: "hidden" }}>{f.id}</p>
            </Item>
          );
        })}
      <div className="p-2"></div>
      {folder && (
        <>
          <Command.Separator />
          <Item
            key={useUniqueId()}
            onSelect={() => {
              createNewFlow();
            }}
          >
            <PlusIcon inProgress={inProgress} />
            {`Create New ${letterCase(flow_wording)}...`}
          </Item>
          <Editable
            callback={(value) => {
              setIsInEditMode(false);
              handleEditDone(value);
            }}
            setIsInEditMode={setIsInEditMode}
            text={folder_name}
            placeholder={`${letterCase(flow_wording)} name`}
            type="input"
            props={undefined}
          ></Editable>

          <Item
            key={useUniqueId()}
            onSelect={() => {
              shareFolder();
            }}
          >
            <LoadingIcon inProgress={shareInProgress}>
              <AiOutlineShareAlt />
            </LoadingIcon>
            {`Share ${folder_name}...`}
          </Item>

          <Item
            key={useUniqueId()}
            disabled={folder?.flows?.length > 0 ? true : false}
            onSelect={() => {
              deleteSelectedFolder();
            }}
          >
            <DeleteIcon inProgress={deleteInProgress} />
            <p>Delete</p>
            <p style={{ fontWeight: "bold" }}>{`${folder_name}...`}</p>
          </Item>
        </>
      )}
    </>
  );
}

//To show all the folders in the root
function RootFolders({
  token,
  showFlowsForFolder,
  folder_wording,
}: {
  token: string;
  showFlowsForFolder: Function;
  folder_wording: string;
}) {
  const { mutate, folders, foldersError, isFoldersLoading } = useFolders();

  useEffect(() => {
    mutate();
  }, []);

  const [inProgress, setInProgress] = useState(false);

  const createNewFolder = async () => {
    setInProgress(true);
    await createFolder(token);
    mutate();
    setInProgress(false);
  };

  return (
    <>
      {isFoldersLoading && (!folders || folders.length > 0) && (
        <Command.Loading>
          <Spinner />
        </Command.Loading>
      )}

      {folders && folders.length === 0 && !isFoldersLoading && (
        <>
          <p cmdk-empty="">{`No ${folder_wording}s found.`}</p>
        </>
      )}

      {folders &&
        ["private", "shared", "public"].map((type) => {
          return (
            <>
              {folders.filter((f: any) => f.type === type).length > 0 && (
                <>
                  <Command.Group
                    key={useUniqueId()}
                    heading={`${
                      type.charAt(0).toUpperCase() + type.slice(1)
                    } ${folder_wording.toLowerCase()}s`}
                  >
                    {folders &&
                      folders
                        ?.filter((f: any) => f.type === type)
                        .map((f: any) => {
                          return (
                            <Item
                              key={useUniqueId()}
                              onSelect={() => {
                                showFlowsForFolder(f.name, f.id);
                              }}
                            >
                              <FolderIcon />
                              {truncate(f.name, 40)}
                              <p style={{ width: "0px", visibility: "hidden" }}>
                                {f.id}
                              </p>
                            </Item>
                          );
                        })}
                  </Command.Group>
                </>
              )}
            </>
          );
        })}

      <div className="p-2"></div>
      <Command.Separator />
      <Item
        key={useUniqueId()}
        onSelect={() => {
          createNewFolder();
        }}
      >
        <PlusIcon inProgress={inProgress} />
        {`Create New ${letterCase(folder_wording)}...`}
      </Item>
    </>
  );
}

function FlowIcon() {
  return (
    <svg
      xmlns="http://www.w3.org/2000/svg"
      fill="none"
      viewBox="0 0 24 24"
      strokeWidth={1.5}
      stroke="currentColor"
      className="w-6 h-6"
    >
      <path
        strokeLinecap="round"
        strokeLinejoin="round"
        d="M2.25 7.125C2.25 6.504 2.754 6 3.375 6h6c.621 0 1.125.504 1.125 1.125v3.75c0 .621-.504 1.125-1.125 1.125h-6a1.125 1.125 0 01-1.125-1.125v-3.75zM14.25 8.625c0-.621.504-1.125 1.125-1.125h5.25c.621 0 1.125.504 1.125 1.125v8.25c0 .621-.504 1.125-1.125 1.125h-5.25a1.125 1.125 0 01-1.125-1.125v-8.25zM3.75 16.125c0-.621.504-1.125 1.125-1.125h5.25c.621 0 1.125.504 1.125 1.125v2.25c0 .621-.504 1.125-1.125 1.125h-5.25a1.125 1.125 0 01-1.125-1.125v-2.25z"
      />
    </svg>
  );
}

function LoadToCanvasIcon({ inProgress }: { inProgress?: boolean }) {
  return (
    <>
      {inProgress ? (
        <>
          <SmallSpinner />
        </>
      ) : (
        <>
          <svg
            xmlns="http://www.w3.org/2000/svg"
            fill="none"
            viewBox="0 0 24 24"
            strokeWidth={1.5}
            stroke="currentColor"
            className="w-6 h-6"
          >
            <path
              strokeLinecap="round"
              strokeLinejoin="round"
              d="M9 8.25H7.5a2.25 2.25 0 00-2.25 2.25v9a2.25 2.25 0 002.25 2.25h9a2.25 2.25 0 002.25-2.25v-9a2.25 2.25 0 00-2.25-2.25H15M9 12l3 3m0 0l3-3m-3 3V2.25"
            />
          </svg>
        </>
      )}
    </>
  );
}
function DeleteIcon({ inProgress }: { inProgress?: boolean }) {
  return (
    <>
      {inProgress ? (
        <>
          <SmallSpinner />
        </>
      ) : (
        <>
          <svg
            xmlns="http://www.w3.org/2000/svg"
            fill="none"
            viewBox="0 0 24 24"
            strokeWidth={1.5}
            stroke="currentColor"
            className="w-6 h-6"
          >
            <path
              strokeLinecap="round"
              strokeLinejoin="round"
              d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0"
            />
          </svg>
        </>
      )}
    </>
  );
}

function PlusIcon({ inProgress }: { inProgress?: boolean }) {
  return (
    <>
      {inProgress ? (
        <>
          <SmallSpinner />
        </>
      ) : (
        <>
          <svg
            fill="none"
            height="24"
            shapeRendering="geometricPrecision"
            stroke="currentColor"
            strokeLinecap="round"
            strokeLinejoin="round"
            strokeWidth="1.5"
            viewBox="0 0 24 24"
            width="24"
          >
            <path d="M12 5v14"></path>
            <path d="M5 12h14"></path>
          </svg>
        </>
      )}
    </>
  );
}

function FolderIcon() {
  return (
    <svg
      xmlns="http://www.w3.org/2000/svg"
      fill="none"
      viewBox="0 0 24 24"
      strokeWidth={1.5}
      stroke="currentColor"
      className="w-6 h-6"
    >
      <path
        strokeLinecap="round"
        strokeLinejoin="round"
        d="M2.25 12.75V12A2.25 2.25 0 014.5 9.75h15A2.25 2.25 0 0121.75 12v.75m-8.69-6.44l-2.12-2.12a1.5 1.5 0 00-1.061-.44H4.5A2.25 2.25 0 002.25 6v12a2.25 2.25 0 002.25 2.25h15A2.25 2.25 0 0021.75 18V9a2.25 2.25 0 00-2.25-2.25h-5.379a1.5 1.5 0 01-1.06-.44z"
      />
    </svg>
  );
}
