import React, { useState, useEffect, useCallback, useRef } from "react";
import { useParams } from "react-router";
import { defaultEndpoints } from "@/utils/templates/api/default";
import { buildTreeQLEndpoints } from "@/utils/templates/api/treeQL";
import {
  GlobalContext,
  Views,
  setGLobalProperty,
  setLoading,
} from "@/context/Global";
import { MkdButton } from "@/components/MkdButton";
import { RouteList } from ".";
import { Skeleton } from "@/components/Skeleton";
import { AuthContext } from "@/context/Auth";
import { RouteEditor } from "./RouteEditor";
import { LazyLoad } from "@/components/LazyLoad";
import {
  getProject,
  getRoles,
  getSchema,
  getWireframe,
  saveApiAction,
  WireFrameBuilderContext,
} from "@/components/WireframeBuilder/reducers";
import { getDefaultRouteConfig } from "@/utils/options/DataTypes";
import { InteractiveButton } from "@/components/InteractiveButton";
import {
  GitIcon,
  LoadCheckIcon,
  PostmanIcon,
  ThreeDotsHorizontal,
} from "@/assets/svgs";
import { BasicRouteEditor } from "./BasicRouteEditor";
import RouteLogic from "./RouteEditor/RouteLogic/RouteLogic";
import { DropdownOption, DropdownOptions } from "@/components/DropdownOptions";
import { makeLambdaEndpoints } from "@/utils/helpers/endpoints/makeLambda";
import { makePostmanCollection } from "@/utils/helpers/endpoints/makePostman";
import { ModalPrompt } from "@/components/Modal";

function ApiBuilderV2({ wireframe, getWireframeConfig }) {
  const {
    dispatch: globalDispatch,
    state: {
      view,
      endPointsLoading,
      save_api,
      route_logic,
      commitRepo,
      downloadingPostman,
      isRouteSaved,
    },
  } = React.useContext(GlobalContext);

  // console.log("wireframe: ", JSON.parse(wireframe?.api_config))

  const { dispatch: authDispatch } = React.useContext(AuthContext);
  const { dispatch: wireframeDispatch, state: wireframeState } =
    React.useContext(WireFrameBuilderContext);
  const params = useParams();

  const [endpoints, setEndpoints] = useState([]);
  const saveRef = useRef(null);
  const [selectedEndpointIndex, setSelectedEndpointIndex] = useState(null);
  const [openSavePrompt, setOpenSavePrompt] = useState(false);
  const [isUpdated, setIsUpdated] = useState(false);
  const [isLoading, setIsLoading] = useState(false);
  console.log("wireframeState:", wireframeState);
  // endpoints.forEach((item) => item.group === "custom" && console.log("custom", item));
  // endpoints.forEach((item) => item.group === "treeql" && console.log("treeql", item));
  // endpoints.forEach((item) => item.group === "default" && console.log("default", item));

  const downloadPostman = () => {
    setLoading(globalDispatch, true, "downloadingPostman");
    try {
      const postmanCollection = makePostmanCollection(
        endpoints,
        wireframeState?.project
      );

      if (postmanCollection) {
        // Convert the JSON string to a Blob
        const blob = new Blob([postmanCollection], {
          type: "application/json",
        });

        // Create an invisible anchor element
        const anchor = document.createElement("a");
        anchor.style.display = "none";

        // Set the anchor's properties
        anchor.href = window.URL.createObjectURL(blob);
        anchor.download = `${wireframeState?.project?.project_id}_postman_collection.json`;

        // Append the anchor to the document
        document.body.appendChild(anchor);

        // Trigger a click on the anchor to start the download
        anchor.click();

        // Remove the anchor from the document
        document.body.removeChild(anchor);
      }

      setLoading(globalDispatch, false, "downloadingPostman");
    } catch (error) {
      setLoading(globalDispatch, false, "downloadingPostman");
    }
  };

  const threeDotsHorOptionsDropdown = [
    {
      name: `${commitRepo?.loading ? "Commiting" : "Commit To Repo"}`,
      onClick: () =>
        makeLambdaEndpoints(
          endpoints,
          wireframeState?.project,
          globalDispatch,
          authDispatch
        ),
      icon: <GitIcon className="mr-1 h-5 w-5 " />,
    },
    {
      name: "Create Postman doc",
      onClick: () => {
        downloadPostman();
      },
      icon: <PostmanIcon className="mr-1 h-5 w-5 " />,
    },
  ];

  const handleEndpointSave = async (endpointData) => {
    const tempEndpoints = [...endpoints];
    const endpointIndex = tempEndpoints.findIndex(
      (endpoint) => endpoint?.id === endpointData?.id
    );

    if (endpointIndex !== -1) {
      tempEndpoints.splice(endpointIndex, 1, endpointData);
    } else {
      tempEndpoints.unshift(endpointData);
    }

    await saveApiAction(
      wireframeDispatch,
      authDispatch,
      globalDispatch,
      tempEndpoints,
      wireframe
    );

    await getWireframe(wireframeDispatch, authDispatch, Number(params?.id));
    // await getWireframeConfig("api_config");
    setIsUpdated((pre) => !pre);
  };

  const setDefaultEndpoints = useCallback(
    async (schema, currentEndpoints) => {
      // console.log(currentEndpoints)
      setIsLoading(true);
      setGLobalProperty(globalDispatch, true, "endPointsLoading");

      if (!Array.isArray(currentEndpoints)) {
        currentEndpoints = [];
      }

      try {
        let treeQLEndpoints = buildTreeQLEndpoints(schema);
        let filteredEndpoints = currentEndpoints
          .filter((s) => s.type != "default")
          .filter((s) => s.type != "treeql");
        const AllEndpoints = [
          ...filteredEndpoints,
          ...defaultEndpoints,
          ...treeQLEndpoints,
        ];

        setEndpoints(AllEndpoints);
      } catch (error) {
        console.error("Error setting default endpoints:", error);
      } finally {
        setGLobalProperty(globalDispatch, false, "endPointsLoading");
        setIsLoading(false);
      }
    },
    [isUpdated]
  );

  const onEndpointDelete = async (id) => {
    setIsLoading(true);
    setGLobalProperty(globalDispatch, true, "endPointsLoading");
    const tempEndpoints = endpoints.filter((e) => e.id !== id);
    setEndpoints(tempEndpoints);
    setSelectedEndpointIndex(null);

    await saveApiAction(
      wireframeDispatch,
      authDispatch,
      globalDispatch,
      tempEndpoints,
      wireframe
    );

    // await getWireframeConfig("api_config");
    await getWireframe(wireframeDispatch, authDispatch, Number(params?.id));
    setIsUpdated((pre) => !pre);
  };

  const onEndpointSelect = (endpoint) => {
    setSelectedEndpointIndex(endpoint.id);
    setGLobalProperty(globalDispatch, endpoint, "selectedRoute");
  };

  const addNewRoute = () => {
    setGLobalProperty(
      globalDispatch,
      getDefaultRouteConfig(wireframeState?.project?.project_id),
      "selectedRoute"
    );
    setGLobalProperty(globalDispatch, Views.BasicRouteEditor, "view");
  };

  const skipSave = useCallback(() => {
    setOpenSavePrompt(false);
    setGLobalProperty(globalDispatch, true, "isRouteSaved");
    setGLobalProperty(globalDispatch, Views.RouteList, "view");
    setGLobalProperty(globalDispatch, null, "selectedRoute");
  }, []);

  const onBackClick = useCallback(() => {
    if (!isRouteSaved) {
      setOpenSavePrompt(true);
    } else {
      skipSave();
    }
  }, [isRouteSaved]);

  useEffect(() => {
    getWireframe(wireframeDispatch, authDispatch, Number(params?.id));
    // getWireframeConfig("api_config");
  }, []);

  useEffect(() => {
    if (!Object.keys(wireframeState?.project).length) {
      getProject(wireframeDispatch, authDispatch, wireframe?.project_id);
    }

    getRoles(wireframeDispatch, authDispatch, wireframeState?.project);

    if (
      !wireframeState?.schema?.length &&
      Object.keys(wireframeState?.project)
    ) {
      getSchema(wireframeDispatch, authDispatch, wireframe?.project_id);
    }
    if (wireframeState?.schema?.length) {
      setDefaultEndpoints(
        wireframeState?.schema,
        JSON.parse(wireframe?.api_config)
      );
    }
  }, [wireframeState?.schema, isUpdated]);

  const mock_endpoints = endpoints.filter((e) => e.type !== "default");
  return (
    <div className="h-screen min-h-screen w-full  py-2">
      <div className="flex h-fit min-h-fit w-full items-center justify-between px-8 ">
        <div className="flex grow items-center  bg-transparent">
          <div className="items-center  font-['Inter'] text-xl font-bold capitalize leading-7 text-neutral-800">
            API - {wireframe?.name}
          </div>

          {[Views.BasicRouteEditor, Views.AdvancedRouteEditor].includes(
            view
          ) && (
            <div className="flex w-[25rem] items-center bg-white p-2 px-7 font-medium text-[#8D8D8D]">
              <button
                onClick={() =>
                  setGLobalProperty(
                    globalDispatch,
                    Views.BasicRouteEditor,
                    "view"
                  )
                }
                className={`grow cursor-pointer rounded-lg px-3 py-1 transition-all  ${
                  view === Views.BasicRouteEditor
                    ? "bg-[#f4f4f4] text-[#525252]"
                    : ""
                }`}
              >
                Basic
              </button>
              <button
                onClick={() =>
                  setGLobalProperty(
                    globalDispatch,
                    Views.AdvancedRouteEditor,
                    "view"
                  )
                }
                className={`grow cursor-pointer rounded-lg px-3 py-1 transition-all  ${
                  view === Views.AdvancedRouteEditor
                    ? "bg-[#f4f4f4] text-[#525252]"
                    : ""
                }`}
              >
                Advanced
              </button>
            </div>
          )}
        </div>
        <div className="flex gap-3">
          {view === Views.RouteList && (
            <div className="flex w-fit items-center gap-3">
              <div className="flex w-fit items-center  gap-2">
                <LoadCheckIcon
                  icon={
                    commitRepo?.loading || downloadingPostman?.loading
                      ? "loader"
                      : "check"
                  }
                />
                <div
                  className={`text-primaryBlue transition-all ${
                    commitRepo?.loading ? "w-fit" : "w-0 overflow-hidden"
                  }`}
                >
                  Commiting...
                </div>
                <div
                  className={`text-primaryBlue transition-all ${
                    downloadingPostman?.loading
                      ? "w-fit"
                      : "w-0 overflow-hidden"
                  }`}
                >
                  Generating Postman Collection...
                </div>
              </div>
              <MkdButton onClick={addNewRoute}>Add Route</MkdButton>

              <DropdownOptions
                icon={
                  <ThreeDotsHorizontal className="h-5 w-5 text-[#8D8D8D]" />
                }
                iconWrapperClass="rounded-md px-[.6125rem] h-[2.125rem] border border-[#E0E0E0] hover:bg-[#F4F4F4] "
              >
                {threeDotsHorOptionsDropdown.map((item, index) => (
                  <DropdownOption
                    key={index}
                    icon={item.icon}
                    name={item.name}
                    onClick={commitRepo?.loading ? () => {} : item.onClick}
                  />
                ))}
              </DropdownOptions>
            </div>
          )}

          {[Views.BasicRouteEditor, Views.AdvancedRouteEditor].includes(
            view
          ) && (
            <>
              <div className={`flex items-center gap-3`}>
                <span>
                  <LoadCheckIcon
                    icon={save_api?.loading ? "loader" : "check"}
                  />
                </span>
                <span>{save_api?.loading ? "Saving" : ""}</span>
                <InteractiveButton
                  loading={save_api?.loading}
                  disabled={save_api?.loading}
                  onClick={() => saveRef?.current?.click()}
                  type="button"
                  className=" rounded-md bg-primaryBlue px-5 py-2 font-bold text-white "
                >
                  {save_api?.loading ? "Saving" : "Save"} Changes
                </InteractiveButton>
                <MkdButton
                  showPlus={false}
                  onClick={() =>
                    setGLobalProperty(globalDispatch, true, "route_logic")
                  }
                >
                  Preview Mode
                </MkdButton>
                <MkdButton showPlus={false} onClick={() => onBackClick()}>
                  Back to API
                </MkdButton>
              </div>
            </>
          )}
        </div>
      </div>

      {!endPointsLoading && endpoints?.length && view === Views.RouteList ? (
        <LazyLoad count={5}>
          {mock_endpoints.length > 0 ? (
            <RouteList
              endpoints={mock_endpoints}
              onEndpointDelete={onEndpointDelete}
              onEndpointSelect={onEndpointSelect}
              selectedEndpointIndex={selectedEndpointIndex}
            />
          ) : (
            <div className="flex h-[70%] flex-col items-center justify-center text-center text-2xl font-bold text-neutral-800">
              No Routes Found <br />
              <span className="text-sm text-neutral-500">
                Add a new route to get started
              </span>
            </div>
          )}
        </LazyLoad>
      ) : (
        endPointsLoading && <Skeleton />
      )}

      {/* BASIC VIEW */}
      {view === Views.BasicRouteEditor ? (
        <LazyLoad count={5}>
          <BasicRouteEditor
            handleEndpointSave={handleEndpointSave}
            saveRef={saveRef}
          />
        </LazyLoad>
      ) : null}

      {/* ADVANCED VIEW */}
      {view === Views.AdvancedRouteEditor ? (
        <LazyLoad count={5}>
          <RouteEditor
            handleEndpointSave={handleEndpointSave}
            saveRef={saveRef}
          />
        </LazyLoad>
      ) : null}

      <LazyLoad>{route_logic ? <RouteLogic /> : null}</LazyLoad>
      <LazyLoad>
        <ModalPrompt
          open={openSavePrompt}
          closeModalFunction={() => setOpenSavePrompt(false)}
          actionHandler={skipSave}
          title={`Unsaved Changes`}
          message={`You have unsaved changes, do you wish to skip unsaved changes?.`}
          titleClasses={`text-blue-950 text-2xl font-semibold font-['Inter']`}
          messageClasses={`text-slate-500 text-sm font-medium font-['Inter'] leading-tight`}
          acceptText="Skip"
          rejectText="OK"
        />
      </LazyLoad>
    </div>
  );
}

export default ApiBuilderV2;
