import styles from "./styles.module.scss";
import { DataURIToBlob } from "@/services/data";
import { useApi } from "@/api";
import { IPalmistryFinger, IPalmistryLine } from "@/api/resources/Palmistry";
import { IPalmistryFingerLocal } from "@/store/palmistry";
import { useDispatch } from "react-redux";
import { actions } from "@/store";
import { useNavigate } from "react-router-dom";
import routes from "@/routes";
import { useEffect, useState } from "react";
import Loader, { LoaderColor } from "@/components/Loader";
import UploadModal from "@/components/palmistry/upload-modal/upload-modal";
import Toast from "@/components/pages/ABDesign/v1/components/Toast";
import { useTranslations } from "@/hooks/translations";
import { ELocalesPlacement } from "@/locales";
import CameraModal from "../../components/CameraModal";
import metricService, { EGoals, EMetrics } from "@/services/metric/metricService";

const isProduction = import.meta.env.MODE === "production";

enum EToastVisible {
  "try_again" = "try_again",
  "try_again_or_next" = "try_again_or_next",
}

function Camera() {
  const { translate } = useTranslations(ELocalesPlacement.PalmistryV1);
  const navigate = useNavigate();
  const api = useApi();
  const dispatch = useDispatch();
  const [isLoading, setIsLoading] = useState(false);
  const [uploadMenuModalIsOpen, setUploadMenuModalIsOpen] = useState(false);
  const [toastVisible, setToastVisible] = useState<EToastVisible | null>(null);

  const handleNext = () => {
    metricService.reachGoal(EGoals.CAMERA_SUCCESS, [EMetrics.YANDEX, EMetrics.KLAVIYO]);
    navigate(routes.client.palmistryV1ScannedPhoto());
  };

  const fingersNames = {
    thumb: translate("thumb"),
    index_finger: translate("index_finger"),
    middle_finger: translate("middle_finger"),
    ring_finger: translate("ring_finger"),
    pinky: translate("pinky"),
  };

  const setFingersNames = (
    fingers: IPalmistryFinger[]
  ): IPalmistryFingerLocal[] => {
    if (!fingers) return [];
    return fingers.map((finger) => {
      return {
        ...finger,
        fingerName: fingersNames[finger.name as keyof typeof fingersNames],
      };
    });
  };

  /**
   * Check if the palmistry lines are valid for the next step.
   * If the length of the lines is less than 2, show the "try_again" toast.
   * If the length of the lines is 2, show the "try_again_or_next" toast.
   * Otherwise, return true.
   * @param {IPalmistryLine[]} lines - The palmistry lines.
   * @returns {boolean} Whether the palmistry lines are valid for the next step.
   */
  const checkPalmistryLines = (lines: IPalmistryLine[]): boolean => {
    if (!lines.length || lines.length < 2) {
      setToastVisible(EToastVisible.try_again);
      return false;
    }
    if (lines.length === 2) {
      setToastVisible(EToastVisible.try_again_or_next);
      return false;
    }
    return true;
  };

  const getLines = async (file: File | Blob) => {
    setIsLoading(true);
    const formData = new FormData();
    formData.append("file", file);
    try {
      const result = await api.getPalmistryLines({ formData });
      const fingers = setFingersNames(result?.fingers);

      dispatch(
        actions.palmistry.update({
          lines: result?.lines,
          fingers,
        })
      );
      return result;
    } catch (error) {
      dispatch(
        actions.palmistry.update({
          lines: [],
          fingers: [],
        })
      );
      return null;
    } finally {
      setIsLoading(false);
    }
  };

  const onTakePhoto = async (photo: string) => {
    setUploadMenuModalIsOpen(false);

    try {
      const file = DataURIToBlob(photo);

      const result = await getLines(file);

      URL.revokeObjectURL(URL.createObjectURL(file));

      dispatch(
        actions.palmistry.update({
          photo,
        })
      );
      if (!checkPalmistryLines(result?.lines || [])) return;
      handleNext();
    } catch (error) {
      console.error('Ошибка при обработке фото:', error);
    } finally {
      // Принудительный запуск сборщика мусора (не гарантировано, но может помочь)
      if (window.gc) {
        window.gc();
      }
    }
  };

  const onSelectFile = async (event: React.ChangeEvent<HTMLInputElement>) => {
    setUploadMenuModalIsOpen(false);

    if (!event.target.files || event.target.files.length === 0) return;

    const result = await getLines(event.target.files[0]);

    const reader = new FileReader();

    reader.onloadend = () => {
      dispatch(
        actions.palmistry.update({
          photo: reader.result as string,
        })
      );
      if (!checkPalmistryLines(result?.lines || [])) return;
      handleNext();
    };

    reader.readAsDataURL(event.target.files[0]);
  };

  useEffect(() => {
    metricService.reachGoal(EGoals.CAMERA_OPEN, [EMetrics.YANDEX, EMetrics.KLAVIYO]);
  }, []);

  useEffect(() => {
    if (toastVisible === EToastVisible.try_again) {
      metricService.reachGoal(EGoals.CAMERA_ERROR, [EMetrics.YANDEX, EMetrics.KLAVIYO]);
    }
  }, [toastVisible]);

  return (
    <>
      {!isProduction && uploadMenuModalIsOpen && (
        <UploadModal
          onClose={() => setUploadMenuModalIsOpen(false)}
          onSelectFile={onSelectFile}
          onChooseCamera={() => true}
        />
      )}
      {!isProduction && (
        <button
          className={styles["upload-button"]}
          onClick={() => setUploadMenuModalIsOpen(true)}
        >
          Upload
        </button>
      )}
      {!isLoading && !uploadMenuModalIsOpen && (
        // <PalmCameraModal
        //   onClose={() => console.log("close")}
        //   onTakePhoto={onTakePhoto}
        // />
        <CameraModal
          onClose={() => console.log("close")}
          onTakePhoto={onTakePhoto}
          onError={(error) => {
            console.error(error)
            setToastVisible(EToastVisible.try_again)
          }}
        />
      )}
      {isLoading && (
        <Loader className={styles.loader} color={LoaderColor.Black} />
      )}
      {toastVisible === EToastVisible.try_again && (
        <Toast classNameContainer={styles["toast-container"]} variant="error">
          <div className={styles["toast-content"]}>
            <span>{translate("/camera.bad_photo")}</span>
            <button onClick={() => setToastVisible(null)}>
              {translate("/camera.try_again")}
            </button>
          </div>
        </Toast>
      )}
      {toastVisible === EToastVisible.try_again_or_next && (
        <Toast classNameContainer={styles["toast-container"]} variant="error">
          <div
            className={styles["toast-content"]}
            style={{ flexDirection: "column" }}
          >
            <span>{translate("/camera.do_better")}</span>
            <div className={styles["buttons-container"]}>
              <button onClick={() => setToastVisible(null)}>
                {translate("/camera.try_again")}
              </button>
              <button onClick={() => handleNext()}>
                {translate("/camera.next")}
              </button>
            </div>
          </div>
        </Toast>
      )}
    </>
  );
}

export default Camera;
