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, useMemo, 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";
import Modal from "@/components/Modal";
import Title from "@/components/Title";
import { EUnleashFlags, useUnleash } from "@/hooks/ab/unleash/useUnleash";

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

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

function Camera() {
  const isIphoneSafari = useMemo((): boolean => {
    const userAgent = navigator.userAgent;
    const isIOS = /iPhone/i.test(userAgent);
    const isSafari = /Safari/i.test(userAgent) &&
      !/CriOS/i.test(userAgent) && // не Chrome
      !/FxiOS/i.test(userAgent) && // не Firefox
      !/EdgiOS/i.test(userAgent) && // не Edge
      !/OPiOS/i.test(userAgent);   // не Opera

    return isIOS && isSafari;
  }, []);

  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 [cameraKey, setCameraKey] = useState(0);
  const [isCameraModalOpen, setIsCameraModalOpen] = useState(false);

  // const { flags, ready } = useMetricABFlags();

  const { isReady, variant: cameraRequestModalPalmistryV1 } = useUnleash({
    flag: EUnleashFlags.cameraRequestModalPalmistryV1
  });

  // const isCameraRequestModal = flags?.cameraRequestModal?.[0] !== "without";

  const isCameraRequestModal = cameraRequestModalPalmistryV1 !== "hide";

  const [isRequestCameraModalOpen, setIsRequestCameraModalOpen] = useState((isIphoneSafari || !isCameraRequestModal) ? false : true);

  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>) => {
    setToastVisible(null);
    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]);

  const cameraError = (error: string | DOMException) => {
    console.error("Camera error", error)
    if (!isIphoneSafari || !isCameraRequestModal) return;
    if (error === "Video is not ready") {
      return setToastVisible(EToastVisible.no_access_camera)
    }
    return setIsRequestCameraModalOpen(true)
  }

  const requestCameraPermission = async () => {
    if (cameraKey > 2) {
      setIsRequestCameraModalOpen(false);
      setToastVisible(EToastVisible.reload_page);
      return;
    }
    try {
      const stream = await navigator.mediaDevices.getUserMedia({ video: true });
      setToastVisible(null);
      stream.getTracks().forEach(track => track.stop());
      setCameraKey(prev => prev + 1);
    } catch (error) {
      setCameraKey(prev => prev + 1);
      console.error("Ошибка при запросе доступа к камере:", error);
      setIsRequestCameraModalOpen(true);
    }
  };

  if (!isReady) return <Loader color={LoaderColor.Black} />;

  return (
    <>
      <Modal
        isCloseButtonVisible={false}
        open={isRequestCameraModalOpen}
        onClose={() => { }}
        className={styles.modal}
        containerClassName={styles["modal-container"]}
      >
        <Title variant="h4" className={styles["modal-title"]}>
          {translate("/camera.modal.title")}
        </Title>
        <div className={styles["modal-answers"]}>
          <div className={styles["modal-answer"]} onClick={() => {
            setIsRequestCameraModalOpen(false);
            setToastVisible(EToastVisible.no_access_camera);
          }}>
            <p className={styles["modal-answer-text"]}>
              {translate("/camera.modal.cancel")}
            </p>
          </div>
          <div className={styles["modal-answer"]} onClick={() => {
            setIsRequestCameraModalOpen(false)
            if (isIphoneSafari) {
              requestCameraPermission()
            } else {
              setIsCameraModalOpen(true)
            }
          }}>
            <p className={styles["modal-answer-text"]}>
              {translate("/camera.modal.allow")}
            </p>
          </div>
        </div>
      </Modal>
      {!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={cameraError}
          isCameraVisible={(isIphoneSafari || isCameraRequestModal) ? true : isCameraModalOpen}
          reinitializeKey={cameraKey}
        />
      )}
      {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>
            <div className={styles["toast-buttons-container"]}>
              <button onClick={() => setToastVisible(null)}>
                {translate("/camera.try_again")}
              </button>
              <button className={styles.buttonUpload}>
                <input
                  id="upload-input"
                  type="file"
                  accept="image/*"
                  style={{ display: 'none' }}
                  onChange={onSelectFile}
                />
                <label htmlFor="upload-input" className={styles.labelUpload}>
                  {translate("/camera.upload")}
                </label>
              </button>
            </div>
          </div>
        </Toast>
      )}
      {toastVisible === EToastVisible.no_access_camera && (
        <Toast classNameContainer={styles["toast-container"]} variant="error">
          <div className={styles["toast-content"]}>
            <span>{translate("/camera.no_access_camera")}</span>
            <div className={styles["toast-buttons-container"]}>
              <button onClick={() => {
                setToastVisible(null)
                if (isIphoneSafari) {
                  requestCameraPermission()
                } else {
                  setIsCameraModalOpen(true)
                }
              }}>
                {translate("/camera.give_access")}
              </button>
              <button className={styles.buttonUpload}>
                <input
                  id="upload-input"
                  type="file"
                  accept="image/*"
                  style={{ display: 'none' }}
                  onChange={onSelectFile}
                />
                <label htmlFor="upload-input" className={styles.labelUpload}>
                  {translate("/camera.upload")}
                </label>
              </button>
            </div>
          </div>
        </Toast>
      )}
      {toastVisible === EToastVisible.reload_page && (
        <Toast classNameContainer={styles["toast-container"]} variant="error">
          <div className={styles["toast-content"]}>
            <span>{translate("/camera.reload_page")}</span>
            <button onClick={() => {
              setToastVisible(null)
              window.location.reload()
            }}>
              {translate("/camera.reload_page_button")}
            </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;
