import React, { useCallback, useEffect, useState } from "react";
import { LazyLoad } from "@/components/LazyLoad";
import { GlobalContext, setGLobalProperty, showToast } from "@/context/Global";
import {
  APIRouteConfigTabs,
  DragSegmentsTypes,
  WorkflowTypes,
} from "@/utils/constants";
import { generateUUID } from "@/utils/utils";
import { RouteEditorWorkflow } from "../RouteEditor/RouteEditorWorkflow";
import {
  buildWorkflowCode,
} from "@/utils/options/DataTypes";

const BasicRouteEditor = ({ handleEndpointSave, saveRef }) => {
  const {
    dispatch: globalDispatch,
    state: { selectedRoute, selectedWorkflow, isRouteSaved },
  } = React.useContext(GlobalContext);


  const [ready, setReady] = useState(false);

  const [variables, setVariables] = useState({
    var: [],
    actions: [],
  });

  const [workflows, setWorkflows] = useState([
    {
      id: generateUUID(),
      name: WorkflowTypes.APIRoute,
      configurations: {
        [APIRouteConfigTabs.General]: {
          name: "",
          description: "",
          route: "",
          method: "GET",
          folder: "",
        },
        [APIRouteConfigTabs.Authentication]: {
          protected: false,
          authorizedRoles: [],
        },
        [APIRouteConfigTabs.Api_Input]: { inputs: [] },
      },
    },
    {
      id: generateUUID(),
      name: WorkflowTypes.SuccessResponse,
      status_code: "200 - OK",
      response: [],
      columns: {},
      type: "Responses",
    },
  ]);

  const handleSave = useCallback(() => {
    const result = buildWorkflowCode(selectedRoute);
    console.log("result:", result)
    const endpoint = {
      ...selectedRoute,
      code: result.join("\n"),
    };
    console.log("endpoint:", endpoint)
    handleEndpointSave(endpoint);
  }, [workflows, selectedRoute]);

  const handleColumns = (response) => {
    const columns = {}
    response?.forEach((item) => columns[item.name] = item.dataType)
    return columns;
  }

  console.log("workflows:", workflows)
  console.log("selectedRoute:", selectedRoute)
  console.log("selectedWorkflow:", selectedWorkflow)

  // Update Workflow
  const updateWorkflow = useCallback(
    (workflowId, data, parentId = null, segment = null) => {
      const tempWorkflows = workflows;
      if ((parentId && !segment) || (!parentId && segment)) {
        return;
      }
      const position = parentId
        ? tempWorkflows.findIndex((workflow) => workflow.id === parentId)
        : tempWorkflows.findIndex((workflow) => workflow.id === workflowId);
      if (position === -1) {
        return;
      }
      const workflow = tempWorkflows[position];
      if (!segment) {
        tempWorkflows.splice(position, 1, data);
        setWorkflows(() => [...tempWorkflows]);
        updateSelectedRoute(tempWorkflows);
        if (isRouteSaved) {
          setGLobalProperty(globalDispatch, false, "isRouteSaved");
        }
        showToast(globalDispatch, `${workflow?.name} updated`, 4000, "success");
        return;
      }
      switch (segment) {
        case DragSegmentsTypes.TRUE:
          workflow["action"][DragSegmentsTypes.TRUE] = data;
          tempWorkflows.splice(position, 1, workflow);
          setWorkflows(() => [...tempWorkflows]);
          break;
        case DragSegmentsTypes.FALSE:
          workflow["action"][DragSegmentsTypes.FALSE] = data;
          tempWorkflows.splice(position, 1, workflow);
          setWorkflows(() => [...tempWorkflows]);
          break;
        case DragSegmentsTypes.NEXT:
          tempWorkflows.splice(position, 1, data);
          setWorkflows(() => [...tempWorkflows]);
          break;
      }
      updateSelectedRoute(tempWorkflows);
      if (isRouteSaved) {
        setGLobalProperty(globalDispatch, false, "isRouteSaved");
      }
      showToast(globalDispatch, `${workflow?.name} updated`, 4000, "success");
    },
    [selectedWorkflow, workflows, isRouteSaved]
  );

  // Update default workflow - the route configuration
  const updateRouteConfig = useCallback(
    (type, field, value) => {
      const tempWorkflows = workflows;
      const apiConfig = tempWorkflows[0];

      apiConfig.configurations[type][field] = value;

      tempWorkflows.splice(0, 1, apiConfig);

      setWorkflows(() => [...tempWorkflows]);
      updateSelectedRoute(tempWorkflows);
      if (isRouteSaved) {
        setGLobalProperty(globalDispatch, false, "isRouteSaved");
      }
    },
    [workflows, isRouteSaved]
  );

  // Update selectedRoute - global state
  const updateSelectedRoute = useCallback(
    (workflows) => {
      const tempWorkflows = workflows;
      const apiConfig = tempWorkflows[0];
      const responseFlow = workflows?.find(
        (workflow) => workflow?.name === WorkflowTypes.SuccessResponse
      );

      let selectedRouteWorkflows = [];

      if (selectedRoute?.workflows && selectedRoute?.workflows?.length > 2) {
        selectedRouteWorkflows = selectedRoute?.workflows;
        selectedRouteWorkflows.splice(0, 1, workflows[0]);
        selectedRouteWorkflows.splice(
          selectedRoute?.workflows.length - 1,
          1,
          workflows[1]
        );
      } else {
        selectedRouteWorkflows = workflows;
      }
      const status_code =
        responseFlow && responseFlow?.status_code
          ? responseFlow?.status_code
          : selectedRoute?.status_code;
      const response =
        responseFlow && responseFlow?.response && responseFlow?.response?.length
          ? responseFlow?.response
          : selectedRoute?.response;

      const response_model =
        responseFlow && responseFlow?.response_model && responseFlow?.response_model?.length
          ? responseFlow?.response_model
          : selectedRoute?.response_model;

      const route = {
        ...selectedRoute,
        ...apiConfig.configurations[APIRouteConfigTabs.General],
        ...apiConfig.configurations[APIRouteConfigTabs.Authentication],
        ...apiConfig.configurations[APIRouteConfigTabs.Api_Input],
        status_code,
        response,
        response_model,
        columns: handleColumns(response_model),
        workflows: selectedRouteWorkflows,
      };


      setGLobalProperty(
        globalDispatch,
        route,
        "selectedRoute",
        "BasicRouteEditor updateSelectedRoute"
      );
    },
    [selectedRoute]
  );

  // Route Config initial population - General|Auth|Validation
  useEffect(() => {
    if (selectedRoute) {
      const tempWorkflows = workflows;

      const apiConfig = tempWorkflows[0];
      const apiResponse = tempWorkflows[1];
      if (selectedRoute?.workflows && selectedRoute?.workflows?.length > 1) {
        const responseFlow = selectedRoute?.workflows?.find(
          (workflow) => workflow?.name === WorkflowTypes.SuccessResponse
        );
        if (responseFlow) {
          if (responseFlow?.status_code) {
            apiResponse.status_code = responseFlow?.status_code;
          }
          if (responseFlow?.response && responseFlow?.response?.length) {
            apiResponse.response = responseFlow?.response;
          }
          if (responseFlow?.response_model && responseFlow?.response_model?.length) {
            apiResponse.response_model = responseFlow?.response_model;
          }
        } else {
          if (selectedRoute?.status_code) {
            apiResponse.status_code = selectedRoute?.status_code;
          }
          if (selectedRoute?.response) {
            apiResponse.response = selectedRoute?.response;
          }
          if (selectedRoute?.response_model) {
            apiResponse.response_model = selectedRoute?.response_model;
          }
        }
      } else {
        if (selectedRoute?.status_code) {
          apiResponse.status_code = selectedRoute?.status_code;
        }
        if (selectedRoute?.response) {
          apiResponse.response = selectedRoute?.response;
        }
        if (selectedRoute?.response_model) {
          apiResponse.response_model = selectedRoute?.response_model;
        }
      }
      apiConfig.configurations[APIRouteConfigTabs.General] = {
        name: selectedRoute?.name,
        description: selectedRoute?.description,
        route: selectedRoute?.route,
        method: selectedRoute?.method,
        folder: selectedRoute?.folder,
      };
      apiConfig.configurations[APIRouteConfigTabs.Authentication] = {
        protected: selectedRoute?.protected,
        authorizedRoles: selectedRoute?.authorizedRoles,
      };
      apiConfig.configurations[APIRouteConfigTabs.Api_Input] = {
        inputs: selectedRoute?.inputs,
      };
      tempWorkflows.splice(0, 1, apiConfig);
      tempWorkflows.splice(1, 1, apiResponse);
      setWorkflows(() => [...tempWorkflows]);

      setReady(true);
    }
  }, []);

  return (
    <div className="mt-5 flex h-screen min-h-screen w-full min-w-full max-w-full px-8 pb-20">
      <div className="scrollbar-hide relative flex h-full max-h-full grow flex-col items-center justify-start overflow-y-auto py-20 ">
        <LazyLoad>
          {ready && workflows?.length
            ? workflows?.map((workflow, workflowIndex) => (
              <RouteEditorWorkflow
                key={`${workflow.name}_${workflowIndex}`}
                workflow={workflow}
                index={workflowIndex}
                updateWorkflow={updateWorkflow}
                variables={variables}
                totalFlow={workflows?.length}
                updateRouteConfig={updateRouteConfig}
              />
            ))
            : null}
        </LazyLoad>
      </div>

      <button hidden onClick={handleSave} ref={saveRef}>
        save
      </button>
    </div>
  );
};

export default BasicRouteEditor;
