import React, { useEffect, useState, useRef } from "react";
import { useRouter } from "next/router";
// react-hook-form
import { Controller, useForm } from "react-hook-form";
// services
import { AIService } from "services/ai.service";
import { TrackEventService } from "services/track_event.service";
// hooks
import useToast from "hooks/use-toast";
import useUserAuth from "hooks/use-user-auth";
// ui
import { Button, Input } from "@plane/ui";
// components
import { RichReadOnlyEditor, RichReadOnlyEditorWithRef } from "@plane/rich-text-editor";
// types
import { IIssue, IPageBlock } from "types";

type Props = {
  isOpen: boolean;
  handleClose: () => void;
  inset?: string;
  content: string;
  htmlContent?: string;
  onResponse: (response: string) => void;
  projectId: string;
  block?: IPageBlock;
  issue?: IIssue;
};

type FormData = {
  prompt: string;
  task: string;
};

// services
const aiService = new AIService();
const trackEventService = new TrackEventService();

export const GptAssistantModal: React.FC<Props> = ({
  isOpen,
  handleClose,
  inset = "top-0 left-0",
  content,
  htmlContent,
  onResponse,
  projectId,
  block,
  issue,
}) => {
  const [response, setResponse] = useState("");
  const [invalidResponse, setInvalidResponse] = useState(false);

  const router = useRouter();
  const { workspaceSlug } = router.query;

  const { user } = useUserAuth();

  const editorRef = useRef<any>(null);

  const { setToastAlert } = useToast();

  const {
    handleSubmit,
    control,
    reset,
    setFocus,
    formState: { isSubmitting },
  } = useForm({
    defaultValues: {
      prompt: content,
      task: "",
    },
  });

  const onClose = () => {
    handleClose();
    setResponse("");
    setInvalidResponse(false);
    reset();
  };

  const handleResponse = async (formData: FormData) => {
    if (!workspaceSlug || !projectId) return;

    if (formData.task === "") {
      setToastAlert({
        type: "error",
        title: "Error!",
        message: "Please enter some task to get AI assistance.",
      });
      return;
    }

    await aiService
      .createGptTask(
        workspaceSlug as string,
        projectId as string,
        {
          prompt: content && content !== "" ? content : htmlContent ?? "",
          task: formData.task,
        },
        user
      )
      .then((res) => {
        setResponse(res.response_html);
        setFocus("task");

        if (res.response === "") setInvalidResponse(true);
        else setInvalidResponse(false);
      })
      .catch((err) => {
        const error = err?.data?.error;

        if (err.status === 429)
          setToastAlert({
            type: "error",
            title: "Error!",
            message: error || "You have reached the maximum number of requests of 50 requests per month per user.",
          });
        else
          setToastAlert({
            type: "error",
            title: "Error!",
            message: error || "Some error occurred. Please try again.",
          });
      });
  };

  useEffect(() => {
    if (isOpen) setFocus("task");
  }, [isOpen, setFocus]);

  useEffect(() => {
    editorRef.current?.setEditorValue(htmlContent ?? `<p>${content}</p>`);
  }, [htmlContent, editorRef, content]);

  return (
    <div
      className={`absolute ${inset} z-20 w-full space-y-4 rounded-[10px] border border-custom-border-200 bg-custom-background-100 p-4 shadow ${
        isOpen ? "block" : "hidden"
      }`}
    >
      {((content && content !== "") || (htmlContent && htmlContent !== "<p></p>")) && (
        <div className="text-sm">
          Content:
          <RichReadOnlyEditorWithRef
            value={htmlContent ?? `<p>${content}</p>`}
            customClassName="-m-3"
            noBorder
            borderOnFocus={false}
            ref={editorRef}
          />
        </div>
      )}
      {response !== "" && (
        <div className="page-block-section text-sm">
          Response:
          <RichReadOnlyEditor
            value={`<p>${response}</p>`}
            customClassName="-mx-3 -my-3"
            noBorder
            borderOnFocus={false}
          />
        </div>
      )}
      {invalidResponse && (
        <div className="text-sm text-red-500">
          No response could be generated. This may be due to insufficient content or task information. Please try again.
        </div>
      )}
      <Controller
        control={control}
        name="task"
        render={({ field: { value, onChange, ref } }) => (
          <Input
            id="task"
            name="task"
            type="text"
            value={value}
            onChange={onChange}
            ref={ref}
            placeholder={`${
              content && content !== "" ? "Tell AI what action to perform on this content..." : "Ask AI anything..."
            }`}
            className="w-full"
          />
        )}
      />
      <div className={`flex gap-2 ${response === "" ? "justify-end" : "justify-between"}`}>
        {response !== "" && (
          <Button
            variant="primary"
            onClick={() => {
              onResponse(response);
              onClose();
              if (block && user)
                trackEventService.trackUseGPTResponseEvent(block, "USE_GPT_RESPONSE_IN_PAGE_BLOCK", user);
              else if (issue && user)
                trackEventService.trackUseGPTResponseEvent(issue, "USE_GPT_RESPONSE_IN_ISSUE", user);
            }}
          >
            Use this response
          </Button>
        )}
        <div className="flex items-center gap-2">
          <Button variant="neutral-primary" onClick={onClose}>
            Close
          </Button>
          <Button variant="primary" onClick={handleSubmit(handleResponse)} loading={isSubmitting}>
            {isSubmitting ? "Generating response..." : response === "" ? "Generate response" : "Generate again"}
          </Button>
        </div>
      </div>
    </div>
  );
};