import React from "react";
import WireframeSDK from "@/utils/WireframeSDK";
import { formatCode } from "@/utils/utils";
import "codemirror/lib/codemirror.css";
import "codemirror/theme/material.css";
import "codemirror/theme/base16-light.css";
import "codemirror/mode/xml/xml";
import "codemirror/mode/javascript/javascript";
import "codemirror/mode/css/css";
import "codemirror/addon/display/fullscreen.js";
import "codemirror/addon/display/fullscreen.css";
import { Controlled as ControlledEditor } from "react-codemirror2";

let wSDk = new WireframeSDK();

const EndPointLogic = ({
  selectedEndpoint,
  selectedCategory,
  setSelectedCategory,
  selectedAction,
  setSelectedAction,
  handleActionInputChange,
  handleActionInputSave,
  actions,
  fieldValue,
  setFieldValue,
  onFieldChange,
  handleCodeEditorInputChange,
}) => {
  React.useEffect(() => {
    setCode(selectedEndpoint.code || "");
    setDoc(selectedEndpoint.doc || "");
    setUnitTest(selectedEndpoint.unit || "");
  }, []);

  const [activeTab, setActiveTab] = React.useState(1);
  const [code, setCode] = React.useState("");
  const [doc, setDoc] = React.useState("");
  const [unitTest, setUnitTest] = React.useState("");

  const getMiddlewareStack = (endpoint) => {
    if (!endpoint.protected) {
      return " middlewares ";
    }

    if (endpoint.authorizedRoles?.length < 1) {
      return "[ ...middlewares, TokenMiddleware()]";
    }

    return `[ ...middlewares, TokenMiddleware({ role: "${endpoint.authorizedRoles.join(
      "|"
    )}" }) ] `;
  };
  const handleLogicChange = (value) => {
    onFieldChange(
      "code",
      `
            ${getAPITopTemplate()}
            ${value}
            ${getAPIBottomTemplate()}
        `
    );
  };

  const getAPITopTemplate = () => {
    return `app.${selectedEndpoint.method.toLowerCase()}('${
      selectedEndpoint.route
    }', ${getMiddlewareStack(selectedEndpoint)} , async (req, res) => { 
            const sdk = req.sdk;
            sdk.setProjectId(req.projectId)
            try{
    `;
  };

  const getResponseTemplate = () => {
    return Array.isArray(selectedEndpoint.response)
      ? `{${selectedEndpoint.response.map(
          (item) => `${item.key}: ${item.value}`
        )} }`
      : selectedEndpoint.response;
  };
  const getAPIBottomTemplate = () => {
    return `
        return res.status(200).json(${getResponseTemplate()})
        } catch (err) {
            console.error(err);
            res.status(403).json({
                error: true,
                message: err.message
            });
            }
        })
        
    `;
  };

  const onGPTRender = async (e) => {
    let btnText = e.target.innerHTML;
    e.target.innerHTML = "Processing...";
    try {
      const prompt = `Given the code below fill in the logic provided in the comment and return complete route implementation.

            ${getAPITopTemplate()}
            ${fieldValue}
            ${getAPIBottomTemplate()}
            `;
      const result = await wSDk.askGptCustom(prompt);

      if (!result.error) {
        setCode(result.message);
        onFieldChange("code", result.message);
        setActiveTab(2);
      }
    } catch (error) {
      console.log("Error", error);
    }
    e.target.innerHTML = btnText;
  };

  const onGPTAddDoc = async (e) => {
    let btnText = e.target.innerHTML;
    e.target.innerHTML = "Processing...";
    try {
      const prompt = `Given the code below provide the developer documentation.

            ${getAPITopTemplate()}
            ${fieldValue}
            ${getAPIBottomTemplate()}
            `;
      const result = await wSDk.askGptCustom(prompt.trim());

      if (!result.error) {
        setDoc(result.message);
        onFieldChange("doc", result.message);
        setActiveTab(3);
      }
    } catch (error) {
      console.log("Error", error);
    }
    e.target.innerHTML = btnText;
  };

  const onGPTAddUnit = async (e) => {
    try {
      e.target.innerHTML = "Processing...";
      const prompt = `Given the nodejs express route below provide the jest unit test

            ${getAPITopTemplate()}
            ${fieldValue}
            ${getAPIBottomTemplate()}
            `;
      const result = await wSDk.askGptCustom(prompt.trim());

      if (!result.error) {
        setUnitTest(result.message);
        onFieldChange("unit", result.message);
        setActiveTab(4);
      }
    } catch (error) {
      console.log("Error", error);
    }
    e.target.innerHTML = btnText;
  };

  const onAddValidation = () => {
    const inputs = selectedEndpoint.inputs;
    const body = inputs
      .filter((i) => i.type === "body")
      .filter((i) => i.rules != "");
    let bodyValidation = ``;
    if (body?.length >= 1) {
      bodyValidation = `
                let validation = await validateObject({
                    ${body.map(
                      (input) => ` ${input.name}: '${input.rules}'
                    `
                    )}
                }, req.body,)
                if (validation.error) return res.status(403).json(validation)
            `;
    }
    const newCode = formatCode(
      ` ${bodyValidation} \n ${selectedEndpoint.logic} `
    );
    onFieldChange("logic", newCode);
    setFieldValue(newCode);
  };

  return (
    <div className="text-sm text-[#525252]">
      <div className="my-4 flex gap-x-2">
        <div
          role="button"
          className={`flex items-center rounded-md border border-[#E0E0E0] px-2 py-1 transition-all ${
            activeTab == 1
              ? "bg-[#393939] text-[#F9F9F9]"
              : "bg-[#F4F4F4] text-[#8D8D8D]"
          }`}
          onClick={(e) => setActiveTab(1)}
        >
          Code
        </div>
        <div
          role="button"
          className={`flex items-center rounded-md border border-[#E0E0E0] px-2 py-1 transition-all ${
            activeTab == 2
              ? "bg-[#393939] text-[#F9F9F9]"
              : "bg-[#F4F4F4] text-[#8D8D8D]"
          }`}
          onClick={(e) => setActiveTab(2)}
        >
          Preview
        </div>
        <div
          role="button"
          className={`flex items-center rounded-md border border-[#E0E0E0] px-2 py-1 transition-all ${
            activeTab == 3
              ? "bg-[#393939] text-[#F9F9F9]"
              : "bg-[#F4F4F4] text-[#8D8D8D]"
          }`}
          onClick={(e) => setActiveTab(3)}
        >
          Documentation
        </div>
        <div
          role="button"
          className={`flex items-center rounded-md border border-[#E0E0E0] px-2 py-1 transition-all ${
            activeTab == 4
              ? "bg-[#393939] text-[#F9F9F9]"
              : "bg-[#F4F4F4] text-[#8D8D8D]"
          }`}
          onClick={(e) => setActiveTab(4)}
        >
          Unit Test
        </div>
      </div>

      {/* CODE TAB */}
      {activeTab == 1 && (
        <div>
          <p className="text-xs">{getAPITopTemplate()}</p>
          <div className="relative flex bg-[#F8F8FF]">
            <ControlledEditor
              onBeforeChange={(editor, data, value) => {
                handleLogicChange(value);
                handleCodeEditorInputChange(value);
              }}
              value={`${fieldValue}`}
              className="w-full"
              options={{
                lineWrapping: true,
                lint: true,
                mode: "javascript",
                lineNumbers: true,
                styleActiveLine: true,
                theme: "base16-light",
              }}
            />
          </div>
          <p className="text-xs">{getAPIBottomTemplate()}</p>
        </div>
      )}
      {/* PREVIEW TAB */}
      {activeTab == 2 && (
        <div className="rounded-md p-4 font-mono">
          <ControlledEditor
            value={`${formatCode(code)}`}
            className="w-full"
            options={{
              lineWrapping: true,
              lint: true,
              mode: "javascript",
              lineNumbers: true,
              styleActiveLine: true,
              theme: "base16-light",
            }}
          />
        </div>
      )}
      {/* DOC TAB */}
      {activeTab == 3 && (
        <div className="rounded-md p-4 font-mono">
          <ControlledEditor
            value={`${doc}`}
            className="w-full"
            options={{
              lineWrapping: true,
              lint: true,
              mode: "javascript",
              lineNumbers: true,
              styleActiveLine: true,
              theme: "base16-light",
            }}
          />
        </div>
      )}
      {/* UNIT TEST TAB */}
      {activeTab == 4 && (
        <div className="rounded-md p-4 font-mono">
          <ControlledEditor
            value={`${unitTest}`}
            className="w-full"
            options={{
              lineWrapping: true,
              lint: true,
              mode: "javascript",
              lineNumbers: true,
              styleActiveLine: true,
              theme: "base16-light",
            }}
          />
        </div>
      )}
      <div className="my-2 flex gap-2">
        <button
          type="button"
          onClick={(e) => onGPTRender(e)}
          className="flex items-center gap-2 rounded-md border-2 border-[#C6C6C6] p-2 px-3 py-2 text-[#525252] shadow-sm"
        >
          <svg
            xmlns="http://www.w3.org/2000/svg"
            width="17"
            height="16"
            viewBox="0 0 17 16"
            fill="none"
          >
            <path
              fillRule="evenodd"
              clipRule="evenodd"
              d="M2.83301 3.16667C2.83301 2.52233 3.35534 2 3.99967 2H13.6663C14.3107 2 14.833 2.52233 14.833 3.16667V12.8333C14.833 13.4777 14.3107 14 13.6663 14H3.99967C3.35534 14 2.83301 13.4777 2.83301 12.8333V3.16667ZM8.01989 5.64645C8.21516 5.84171 8.21516 6.15829 8.01989 6.35355L6.4913 7.88215C6.42621 7.94724 6.42621 8.05276 6.4913 8.11785L8.01989 9.64645C8.21516 9.84171 8.21516 10.1583 8.01989 10.3536C7.82463 10.5488 7.50805 10.5488 7.31279 10.3536L5.78419 8.82496C5.32858 8.36935 5.32858 7.63065 5.78419 7.17504L7.31279 5.64645C7.50805 5.45118 7.82463 5.45118 8.01989 5.64645ZM10.3532 5.64645C10.158 5.45118 9.84138 5.45118 9.64612 5.64645C9.45086 5.84171 9.45086 6.15829 9.64612 6.35355L11.1747 7.88215C11.2398 7.94724 11.2398 8.05276 11.1747 8.11785L9.64612 9.64645C9.45086 9.84171 9.45086 10.1583 9.64612 10.3536C9.84138 10.5488 10.158 10.5488 10.3532 10.3536L11.8818 8.82496C12.3374 8.36935 12.3374 7.63065 11.8818 7.17504L10.3532 5.64645Z"
              fill="#A8A8A8"
            />
          </svg>
          <span>Generate Code</span>
        </button>
        <button
          type="button"
          onClick={(e) => onGPTAddDoc(e)}
          className="flex items-center gap-2 rounded-md border-2 border-[#C6C6C6] p-2 px-3 py-2 text-[#525252] shadow-sm"
        >
          <svg
            xmlns="http://www.w3.org/2000/svg"
            width="17"
            height="16"
            viewBox="0 0 17 16"
            fill="none"
          >
            <path
              fillRule="evenodd"
              clipRule="evenodd"
              d="M3.16699 2.50016C3.16699 1.85583 3.68933 1.3335 4.33366 1.3335H12.667C13.3113 1.3335 13.8337 1.85583 13.8337 2.50016V13.5002C13.8337 14.1445 13.3113 14.6668 12.667 14.6668H4.33366C3.68933 14.6668 3.16699 14.1445 3.16699 13.5002V2.50016ZM6.33366 4.00016C6.05752 4.00016 5.83366 4.22402 5.83366 4.50016C5.83366 4.77631 6.05752 5.00016 6.33366 5.00016H10.667C10.9431 5.00016 11.167 4.77631 11.167 4.50016C11.167 4.22402 10.9431 4.00016 10.667 4.00016H6.33366ZM6.33366 6.66683C6.05752 6.66683 5.83366 6.89069 5.83366 7.16683C5.83366 7.44297 6.05752 7.66683 6.33366 7.66683H10.667C10.9431 7.66683 11.167 7.44297 11.167 7.16683C11.167 6.89069 10.9431 6.66683 10.667 6.66683H6.33366ZM6.33366 9.3335C6.05752 9.3335 5.83366 9.55735 5.83366 9.8335C5.83366 10.1096 6.05752 10.3335 6.33366 10.3335H8.00033C8.27647 10.3335 8.50033 10.1096 8.50033 9.8335C8.50033 9.55735 8.27647 9.3335 8.00033 9.3335H6.33366Z"
              fill="#A8A8A8"
            />
          </svg>
          <span>Add Doc</span>
        </button>
        <button
          type="button"
          onClick={(e) => onGPTAddUnit(e)}
          className="flex items-center gap-2 rounded-md border-2 border-[#C6C6C6] p-2 px-3 py-2 text-[#525252] shadow-sm"
        >
          <svg
            xmlns="http://www.w3.org/2000/svg"
            width="17"
            height="16"
            viewBox="0 0 17 16"
            fill="none"
          >
            <path
              d="M1.99902 2C1.72288 2 1.49902 2.22386 1.49902 2.5V4.16667C1.49902 4.44281 1.72288 4.66667 1.99902 4.66667H14.3324C14.6085 4.66667 14.8324 4.44281 14.8324 4.16667V2.5C14.8324 2.22386 14.6085 2 14.3324 2H1.99902Z"
              fill="#A8A8A8"
            />
            <path
              fillRule="evenodd"
              clipRule="evenodd"
              d="M14.1657 5.66667H2.16569L2.16569 12.4508C2.16568 12.6225 2.16567 12.7801 2.17643 12.9119C2.18804 13.054 2.21462 13.2095 2.29285 13.363C2.4047 13.5825 2.58318 13.761 2.8027 13.8728C2.95624 13.9511 3.11169 13.9776 3.25378 13.9893C3.38556 14 3.54322 14 3.71487 14H12.6165C12.7882 14 12.9458 14 13.0776 13.9893C13.2197 13.9776 13.3751 13.9511 13.5287 13.8728C13.7482 13.761 13.9267 13.5825 14.0385 13.363C14.1168 13.2095 14.1433 13.054 14.1549 12.9119C14.1657 12.7801 14.1657 12.6225 14.1657 12.4508V5.66667ZM6.33236 7.83333C6.33236 7.55719 6.55621 7.33333 6.83236 7.33333H9.49902C9.77517 7.33333 9.99902 7.55719 9.99902 7.83333C9.99902 8.10948 9.77517 8.33333 9.49902 8.33333H6.83236C6.55621 8.33333 6.33236 8.10948 6.33236 7.83333Z"
              fill="#A8A8A8"
            />
          </svg>
          <span>Add Unit Test</span>
        </button>
      </div>

      <div className="mt-8 flex w-full flex-row items-center gap-4">
        <div className="mr-5 w-1/2 p-2">
          <p className=" mb-4 font-medium">Actions</p>
          <div className="flex-col items-center gap-3">
            <button
              type="button"
              onClick={onAddValidation}
              className="mb-2 mr-3 whitespace-nowrap rounded-md bg-primaryBlue p-2 px-3 py-2 text-white shadow-sm "
            >
              Add Validation
            </button>
            <button
              type="button"
              onClick={() => setSelectedCategory("db")}
              className="mb-2 whitespace-nowrap rounded-md bg-primaryBlue p-2 px-3 py-2 text-white shadow-sm "
            >
              Database
            </button>
          </div>
        </div>

        <div className="w-1/2 p-2">
          <p className=" mb-4 font-medium">
            {selectedCategory && selectedCategory}
          </p>
          {selectedCategory &&
            actions
              .filter((action) => action.category === selectedCategory)
              .map((action, index) => (
                <button
                  key={index}
                  className="mb-2 w-full whitespace-nowrap rounded-md bg-primaryBlue px-3  py-2 text-white"
                  onClick={() => setSelectedAction(action)}
                >
                  {action.name}
                </button>
              ))}
        </div>
      </div>
      <div className="w-full p-2">
        <p className=" mb-4 font-medium">
          {selectedAction && selectedAction.name}
        </p>
        {selectedAction && (
          <div className="w-full">
            <p>{selectedAction.description}</p>
            {selectedAction.inputs?.map((input, index) => (
              <div key={index}>
                <label>{input}</label>
                <input
                  type="text"
                  onChange={(e) =>
                    handleActionInputChange(index, e.target.value)
                  }
                  className="mb-2 w-full rounded border border-gray-400 px-2 py-1"
                />
              </div>
            ))}
            <button
              className="my-3 mb-2 w-full whitespace-nowrap rounded-md bg-primaryBlue  px-3 py-2 text-lg text-white"
              onClick={handleActionInputSave}
            >
              Save
            </button>
          </div>
        )}
      </div>
    </div>
  );
};

export default EndPointLogic;
