//import "tui-image-editor/dist/tui-image-editor.css";
import axios from "axios";
import { Result, theme } from "antd";
import * as markerjs2 from "markerjs2";
import { useCallback, useEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors";
import { handleUpload } from "../documents-upload-imgproxy/documents-upload-imgproxy.utility.js";
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
import {
  addGreyscaleButtonToMarkerArea,
  addImageHistoryUndoToMarkerArea,
  applyGreyscaleToMarkerAreaImage,
  setMarkerAreaImageSource
} from "./document-editor.utility";

const mapStateToProps = createStructuredSelector({
  currentUser: selectCurrentUser,
  bodyshop: selectBodyshop
});
const mapDispatchToProps = () => ({
  //setUserLanguage: language => dispatch(setUserLanguage(language))
});

export function DocumentEditorComponent({ currentUser, bodyshop, document }) {
  const imgRef = useRef(null);
  const [loading, setLoading] = useState(false);
  const [uploaded, setuploaded] = useState(false);
  const [imageUrl, setImageUrl] = useState(null);
  const [imageLoaded, setImageLoaded] = useState(false);
  const [imageLoading, setImageLoading] = useState(true);
  const markerArea = useRef(null);
  const imageHistory = useRef([]);
  const { t } = useTranslation();
  const { token } = theme.useToken();
  const notification = useNotification();

  const triggerUpload = useCallback(
    async (dataUrl) => {
      setLoading(true);
      handleUpload(
        {
          filename: `${document.key.split("/").pop()}-${Date.now()}.jpg`,
          file: await b64toBlob(dataUrl),
          onSuccess: () => {
            setLoading(false);
            setuploaded(true);
          },
          onError: () => setLoading(false)
        },
        {
          bodyshop: bodyshop,
          uploaded_by: currentUser.email,
          jobId: document.jobid,
          //billId: billId,
          tagsArray: ["edited"]
          //callback: callbackAfterUpload,
        },
        notification
      );
    },
    [bodyshop, currentUser, document, notification]
  );

  const handleGreyscale = useCallback(() => {
    if (!imgRef.current || loading || uploaded || imageLoading || !imageLoaded) return;

    imageHistory.current.push(imgRef.current.src);
    applyGreyscaleToMarkerAreaImage(markerArea.current, imgRef.current);
  }, [imageLoaded, imageLoading, loading, uploaded]);

  const undoImageEdit = useCallback(() => {
    if (!imgRef.current) return;

    const previousSrc = imageHistory.current.pop();

    if (previousSrc) {
      setMarkerAreaImageSource(markerArea.current, imgRef.current, previousSrc);
    }
  }, []);

  useEffect(() => {
    if (imgRef.current !== null && imageLoaded && !markerArea.current) {
      // create a marker.js MarkerArea
      markerArea.current = new markerjs2.MarkerArea(imgRef.current);

      // attach an event handler to assign annotated image back to our image element
      markerArea.current.addEventListener("close", () => {
        // NO OP
      });

      markerArea.current.addEventListener("render", (event) => {
        const dataUrl = event.dataUrl;
        imgRef.current.src = dataUrl;
        markerArea.current.close();
        triggerUpload(dataUrl);
      });
      // launch marker.js

      markerArea.current.renderAtNaturalSize = true;
      markerArea.current.renderImageType = "image/jpeg";
      markerArea.current.renderImageQuality = 1;
      //markerArea.current.settings.displayMode = "inline";
      markerArea.current.show();
      addGreyscaleButtonToMarkerArea(markerArea.current, handleGreyscale, t("documents.labels.greyscale"));
      addImageHistoryUndoToMarkerArea(markerArea.current, () => imageHistory.current.length > 0, undoImageEdit);
    }
  }, [handleGreyscale, imageLoaded, t, triggerUpload, undoImageEdit]);

  useEffect(() => {
    if (!document?.id) return;
    const controller = new AbortController();

    const loadImage = async () => {
      setImageLoaded(false);
      setImageLoading(true);
      try {
        const response = await axios.post(
          "/media/imgproxy/original",
          { documentId: document.id },
          {
            responseType: "blob",
            signal: controller.signal
          }
        );
        const blobUrl = URL.createObjectURL(response.data);
        imageHistory.current = [];
        setImageUrl((prevUrl) => {
          if (prevUrl) URL.revokeObjectURL(prevUrl);
          return blobUrl;
        });
      } catch (error) {
        if (axios.isCancel?.(error) || error.name === "CanceledError") {
          // request was aborted — safe to ignore
          return;
        }
        console.error("Failed to fetch original image blob", error);
      } finally {
        setImageLoading(false);
      }
    };
    loadImage();
    return () => {
      controller.abort();
    };
  }, [document]);

  useEffect(() => {
    return () => {
      if (imageUrl) {
        URL.revokeObjectURL(imageUrl);
      }
    };
  }, [imageUrl]);

  async function b64toBlob(url) {
    const res = await fetch(url);
    return await res.blob();
  }

  return (
    <div style={{ background: token.colorBgBase, color: token.colorText, minHeight: "100vh" }}>
      {!loading && !uploaded && imageUrl && (
        <img
          ref={imgRef}
          src={imageUrl}
          alt="sample"
          onLoad={() => setImageLoaded(true)}
          onError={(error) => {
            console.error("Failed to load original image", error);
          }}
          style={{ maxWidth: "90vw", maxHeight: "90vh" }}
        />
      )}
      {(loading || imageLoading || !imageLoaded) && !uploaded && (
        <LoadingSpinner message={t("documents.labels.uploading")} />
      )}
      {uploaded && (
        <Result
          status="success"
          title={<span style={{ color: token.colorText }}>{t("documents.successes.edituploaded")}</span>}
        />
      )}
    </div>
  );
}

export default connect(mapStateToProps, mapDispatchToProps)(DocumentEditorComponent);
