import { useState, useEffect, useMemo } from "react";
// useCallback
import { useDropzone } from "react-dropzone";
// import { PromptImage } from "../../../types";
import { toast } from "react-hot-toast";
import { URLS } from "../urls";
import { Badge } from "./ui/badge";
import ScreenRecorder from "./recording/ScreenRecorder";
import { ScreenRecorderState } from "../types";
import { IS_RUNNING_ON_CLOUD } from "../config";
import { addEvent } from "../lib/analytics";

const baseStyle = {
  flex: 1,
  width: "80%",
  margin: "0 auto",
  minHeight: "400px",
  display: "flex",
  flexDirection: "column",
  alignItems: "center",
  justifyContent: "center",
  padding: "20px",
  borderWidth: 2,
  borderRadius: 2,
  borderColor: "#eeeeee",
  borderStyle: "dashed",
  backgroundColor: "#fafafa",
  color: "#bdbdbd",
  outline: "none",
  transition: "border .24s ease-in-out",
};

const focusedStyle = {
  borderColor: "#2196f3",
};

const acceptStyle = {
  borderColor: "#00e676",
};

const rejectStyle = {
  borderColor: "#ff1744",
};

// TODO: Move to a separate file
function fileToDataURL(file: File) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result);
    reader.onerror = (error) => reject(error);
    reader.readAsDataURL(file);
  });
}

type FileWithPreview = {
  preview: string;
} & File;

interface Props {
  setReferenceImages: (
    referenceImages: string[],
    inputMode: "image" | "video"
  ) => void;
}

function ImageUpload({ setReferenceImages }: Props) {
  const [files, setFiles] = useState<FileWithPreview[]>([]);
  // TODO: Switch to Zustand
  const [screenRecorderState, setScreenRecorderState] =
    useState<ScreenRecorderState>(ScreenRecorderState.INITIAL);

  const { getRootProps, getInputProps, isFocused, isDragAccept, isDragReject } =
    useDropzone({
      maxFiles: 1,
      maxSize: 1024 * 1024 * 20, // 20 MB
      accept: {
        // Image formats
        "image/png": [".png"],
        "image/jpeg": [".jpeg"],
        "image/jpg": [".jpg"],
        // Video formats
        "video/quicktime": [".mov"],
        "video/mp4": [".mp4"],
        "video/webm": [".webm"],
      },
      onDrop: (acceptedFiles) => {
        if (IS_RUNNING_ON_CLOUD) {
          const isVideo = acceptedFiles.some((file) =>
            file.type.startsWith("video/")
          );
          if (isVideo) {
            toast.error("Videos are not yet supported on the hosted version.");
            addEvent("VideoUpload");
            return;
          }
        }

        // Set up the preview thumbnail images
        setFiles(
          acceptedFiles.map((file: File) =>
            Object.assign(file, {
              preview: URL.createObjectURL(file),
            })
          ) as FileWithPreview[]
        );

        // Convert images to data URLs and set the prompt images state
        Promise.all(acceptedFiles.map((file) => fileToDataURL(file)))
          .then((dataUrls) => {
            if (dataUrls.length > 0) {
              setReferenceImages(
                dataUrls.map((dataUrl) => dataUrl as string),
                (dataUrls[0] as string).startsWith("data:video")
                  ? "video"
                  : "image"
              );
            }
          })
          .catch((error) => {
            toast.error("Error reading files" + error);
            console.error("Error reading files:", error);
          });
      },
      onDropRejected: (rejectedFiles) => {
        toast.error(rejectedFiles[0].errors[0].message);
      },
    });

  // const pasteEvent = useCallback(
  //   (event: ClipboardEvent) => {
  //     const clipboardData = event.clipboardData;
  //     if (!clipboardData) return;

  //     const items = clipboardData.items;
  //     const files = [];
  //     for (let i = 0; i < items.length; i++) {
  //       const file = items[i].getAsFile();
  //       if (file && file.type.startsWith("image/")) {
  //         files.push(file);
  //       }
  //     }

  //     // Convert images to data URLs and set the prompt images state
  //     Promise.all(files.map((file) => fileToDataURL(file)))
  //       .then((dataUrls) => {
  //         if (dataUrls.length > 0) {
  //           setReferenceImages(dataUrls.map((dataUrl) => dataUrl as string));
  //         }
  //       })
  //       .catch((error) => {
  //         // TODO: Display error to user
  //         console.error("Error reading files:", error);
  //       });
  //   },
  //   [setReferenceImages]
  // );

  // TODO: Make sure we don't listen to paste events in text input components
  // useEffect(() => {
  //   window.addEventListener("paste", pasteEvent);
  // }, [pasteEvent]);

  useEffect(() => {
    return () => files.forEach((file) => URL.revokeObjectURL(file.preview));
  }, [files]); // Added files as a dependency

  const style = useMemo(
    () => ({
      ...baseStyle,
      ...(isFocused ? focusedStyle : {}),
      ...(isDragAccept ? acceptStyle : {}),
      ...(isDragReject ? rejectStyle : {}),
    }),
    [isFocused, isDragAccept, isDragReject]
  );

  return (
    <section className="container">
      {screenRecorderState === ScreenRecorderState.INITIAL && (
        /* eslint-disable-next-line @typescript-eslint/no-explicit-any */
        <div {...getRootProps({ style: style as any })}>
          <input {...getInputProps()} className="file-input" />
          <p className="text-slate-700 text-lg">
            Drag & drop a screenshot here, <br />
            or click to upload
          </p>
        </div>
      )}
      {/* Disable on prod for now */}
      {!IS_RUNNING_ON_CLOUD && (
        <>
          {screenRecorderState === ScreenRecorderState.INITIAL && (
            <div className="text-center text-sm text-slate-800 mt-4">
              <Badge>New!</Badge> Upload a screen recording (.mp4, .mov) or
              record your screen to clone a whole app (experimental).{" "}
              <a
                className="underline"
                href={URLS["intro-to-video"]}
                target="_blank"
              >
                Learn more.
              </a>
            </div>
          )}
          <ScreenRecorder
            screenRecorderState={screenRecorderState}
            setScreenRecorderState={setScreenRecorderState}
            generateCode={setReferenceImages}
          />
        </>
      )}
    </section>
  );
}

export default ImageUpload;
