import Database from "../../../../../Components/common/DAsyncStorage";
import NetInfo from "@react-native-community/netinfo";
import {
  detectOnlyPoseFileNames,
  DOC,
  get2WPoseFileNotDoc,
  get4WPoseFileNames,
  image_pose_blur,
  image_pose_dark,
  image_pose_wrong,
  is2Wflow,
  multiplePics,
} from "react-native-digitcamera/src/common/Constants";
import { measureConnectionSpeed } from "react-native-network-bandwith-speed";
import { poseDetection } from "react-native-digitcamera/src/common/Services/poseDetection";
import {
  UELogEvent,
  UELogMessage,
} from "react-native-digitcamera/src/common/libEventLog/UserExperior/LibUserExperior";
import { chassiesPoseDetetction } from "react-native-digitcamera/src/common/Services/chassisPoseDetection";
import { async } from "validate.js";
import moment from "moment";

// save data in realm
export const offlinePIDataToRealm = async (isPIDone) => {
  try {
    const mediaStatusObjs = await Database.get("PIMediaStatus");
    const vechicleData = await Database.get("PIVechicleData");
    console.log(
      "!is2Wflow(vechicleData?.activityTypeId)  isPIDone",
      !is2Wflow(vechicleData?.activityTypeId),
      isPIDone
    );
    if (!is2Wflow(vechicleData?.activityTypeId) || isPIDone) {
      console.log("In if offlinePIDataToRealm ");
      let offlineImageData = [];
      console.log(
        "CommonFunc  offlinePIDataToRealm() mediaStatusObjs \n\n\n ",
        mediaStatusObjs
      );
      offlineImageData = [];
      mediaStatusObjs?.filter((item) => {
        if (item?.status === "failed") {
          offlineImageData.push(item);
        }
      });

      await Database.set("PIOfflineVechicleData", {
        activityId: vechicleData.activityId,
        registrationNumber: vechicleData.licensePlateNumber,
        quoteNumber: vechicleData.quoteNumber,
        dataTobeUploaded: JSON.stringify(offlineImageData),
        isPICompleted: isPIDone,
        activityTypeId: vechicleData?.activityTypeId,
      });
    } else {
      console.log("In else offlinePIDataToRealm ");
    }
  } catch (error) {
    console.log("***** offlinePIDataToRealm catch ", error);
  }
};

// checking internet
export const checkInternet = async () => {
  const state = await NetInfo.fetch();
  console.log("Connection type", state.type);
  console.log("Is connected?", state.isConnected);
  return state.isConnected;
};

export const checkInternetSpeed = async () => {
  const DataSpeed = await measureConnectionSpeed();
  console.log(
    "%%%%%%%%%%%% DataSpeed %%%%%%",
    JSON.stringify(DataSpeed, null, "  "),
    DataSpeed?.speed * 1024
  );
  var kbps = DataSpeed?.speed * 1024;
  console.log("KBPS   ", kbps, kbps >= 100);
  if (kbps >= 100) {
    return true;
  }
  return false;
};
// make desion for offline/online flow
export const checkFlow = () => {};

export const clearAllRealmData = async () => {
  try {
    await Database.remove("PIOfflineData");
    await Database.remove("PIVechicleData");
    await Database.remove("PIVechicleInstruction");

    await Database.update("PIGonePoseDetection", {
      GoneposeDetectionCount: 0,
    });

    await Database.update("PIPoseDetectionCompleted", {
      poseDetectionCompletedCount: 0,
    });

    await Database.update("PIRetryCount", {
      retryCount: 0,
      index: 0,
      isAddNewImageData: false,
    });

    await Database.update("PIclickedCount", {
      clickedCount: 0,
    });

    await Database.update("PIUploadedCount", {
      uploadedCount: 0,
    });
    // await Database.remove("PIMediaStatus"); for Mult Activity
    await Database.remove("PIVideoCompleteStatus");
  } catch (error) {}
};

// export const updateStatusRealm = async (uri, DocumentImageName, newStatus) => {
//   var PIVechicleData = await Database.get("PIVechicleData");
//   console.log(
//     "CommonFunc.js  updateStatusRealm() PIVechicleDat?.activityId ",
//     PIVechicleData?.activityId
//   );
//   var activityId = PIVechicleData?.activityId;
//   var quoteNumber = PIVechicleData?.quoteNumber;
//   var licensePlateNumber = PIVechicleData?.licensePlateNumber;
//   await initStatusRealm(
//     uri,
//     DocumentImageName,
//     activityId,
//     quoteNumber,
//     licensePlateNumber
//   ).then(async () => {
//     var PIVechicleData = await Database.get("PIVechicleData");
//     const activityTypeId = PIVechicleData?.activityTypeId;
//     try {
//       const PIMediaStatus = await Database.get("PIMediaStatus");

//       // getting current activity obj
//       const uploadObj = PIMediaStatus.find((item) => {
//         return item.activityId === activityId;
//       });
//       console.log(
//         "CommonFuction.js OfflineFlow *** UploadFile updateStatusRealm uploadObj: " +
//           JSON.stringify(uploadObj)
//       );
//       if (uploadObj != null) {
//         var newObj;
//         // updating values of Activity
//         newObj = {
//           ...uploadObj,
//           activityId: activityId,
//           activityTypeId: activityTypeId,
//           regNumber: licensePlateNumber,
//         };
//         // updating value of image
//         var updatedImageInfo = newObj.mediaUpload.map((item) => {
//           if (
//             item.imageName == DocumentImageName &&
//             item.status !== "uploaded"
//           ) {
//             return {
//               ...item,
//               imageName: DocumentImageName,
//               status: newStatus,
//               uri: uri,
//             };
//           }
//           return item;
//         });

//         // final array = previousImages + currentImages // rcb1 ,rcb2 ,vdo
//         var finalImages = [{ ...uploadObj, mediaUpload: updatedImageInfo }];

//         // for removing last item
//         // did this for removing duplication and old obj
//         PIMediaStatus.pop();

//         console.log(
//           "CommonFuction.js OfflineFlow PIMediaStatus after pop() : ",
//           JSON.stringify(PIMediaStatus, null, "  ")
//         );

//         // adding new updated item
//         var finalArray = PIMediaStatus.concat(finalImages);
//         console.log(
//           "CommonFuction.js OfflineFlow finalArray : ",
//           JSON.stringify(finalArray, null, "  ")
//         );

//         // setting all data in DB
//         await Database.set("PIMediaStatus", finalArray);
//         const alog = await Database.get("PIMediaStatus");
//         console.log("PIMediaStatus", JSON.stringify(alog, null, "  "));
//       }
//     } catch (error) {
//       console.log(
//         "CommonFuction.js OfflineFlow Error in updateStatusRealm :",
//         error
//       );
//     }
//   });
// };

const addMediaStatusObj = async (oldStatus, currentActivityObj) => {
  try {
    console.log(
      "CommonFuction.js OfflineFlow currentActivityObj",
      currentActivityObj
    );
    var objectTobeUpdate = currentActivityObj[0]?.mediaUpload[0];
    var newObj;

    console.log(
      "CommonFuction.js OfflineFlow oldStatus",
      JSON.stringify(oldStatus, null, " ")
    );
    console.log(
      "CommonFuction.js OfflineFlow currentActivityObj",
      JSON.stringify(currentActivityObj, null, " ")
    );

    // this will excute only if there is no activity in DB
    if (oldStatus == null || oldStatus == undefined) {
      console.log(
        "CommonFuction.js OfflineFlow oldStatus == null || oldStatus == undefined",
        currentActivityObj
      );
      return currentActivityObj;
    }

    // this will check for activity is present or not
    console.log(
      "CommonFuction.js OfflineFlow currentActivityObj[0]?.activityId : ",
      currentActivityObj[0]?.activityId,
      JSON.stringify(oldStatus, null, "  ")
    );
    var isActivityAlreadyExist = oldStatus.find((item) => {
      return item.activityId === currentActivityObj[0]?.activityId;
    });

    console.log(
      "CommonFuction.js OfflineFlow isActivityAlreadyExist",
      !!isActivityAlreadyExist
    );

    if (!!isActivityAlreadyExist) {
      // checking is current image object is already exist or not
      const isImageExist = isActivityAlreadyExist?.mediaUpload?.some((item) => {
        item.imageName === objectTobeUpdate?.imageName;
      });

      // this will check if any image with same name is exisdt or not
      const isImageAlreadyExist = isActivityAlreadyExist?.mediaUpload?.filter(
        (imageItem) => {
          return imageItem.imageName != objectTobeUpdate.imageName;
        }
      );
      var updatedImageWithOutDuplicates = [
        ...isImageAlreadyExist,
        objectTobeUpdate,
      ];
      newObj = [
        {
          ...isActivityAlreadyExist,
          mediaUpload: updatedImageWithOutDuplicates,
        },
      ];
      console.log(
        "CommonFuction.js OfflineFlow Activity is present and new Image obj : ",
        JSON.stringify(newObj, null, "  ")
      );
      oldStatus.pop();
      return oldStatus.concat(newObj); // adding previous Activity + current different
    } else {
      console.log(
        "CommonFuction.js OfflineFlow Activity is not present so Adding  New Activity ",
        JSON.stringify(currentActivityObj, null, "  ")
      );
      return oldStatus.concat(currentActivityObj);
    }
  } catch (error) {
    console.log("CommonFuction.js OfflineFlow Error in addMediaObj ", error);
  }
  // console.log(
  //   "**** addMediaStatusObj ",
  //   typeof oldStatus,
  //   typeof myObj,
  //   JSON.stringify(oldStatus),
  //   JSON.stringify(myObj)
  // );
  // console.log("0 " + myObj);
  // var newObj;
  // if (oldStatus == null || oldStatus == undefined) {
  //   console.log("oldStatus == null || oldStatus == undefined", myObj);
  //   return [myObj];
  // }
  // if (oldStatus instanceof Array) {
  //   var isImageExist;
  //   oldStatus.map((imageItemToupdate) => {
  //     // if already object present
  //     if (Object.values(imageItemToupdate).includes(myObj.imageName)) {
  //       return (isImageExist = true);
  //     }
  //     console.log(
  //       "CommonFunctions.js >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>",
  //       isImageExist
  //     );
  //   });
  //   if (isImageExist) {
  //     console.log("*******CommonFunc.js Object already in DB");
  //     newObj = oldStatus.filter(
  //       (imageItemToupdate) => imageItemToupdate.imageName != myObj.imageName
  //     ); // removing previous obj
  //     console.log(
  //       "In CommonFunc.js removed Previous Object",
  //       JSON.stringify(newObj, null, "  ")
  //     );
  //     newObj = [...newObj, myObj]; // adding new
  //     console.log(
  //       "In CommonFunc.js added with new Object",
  //       JSON.stringify(newObj, null, "  ")
  //     );
  //   } else {
  //     // no previous obj
  //     // adding new obj
  //     newObj = [...oldStatus, myObj];
  //     console.log("CommonFunc.js oldStatus instanceof Array Added", newObj);
  //   }
  // } else {
  //   console.log("********** **********   In else ");
  //   if (oldStatus != undefined || oldStatus != null) {
  //     newObj = [oldStatus, myObj];
  //     console.log(
  //       "******* oldStatus != undefined || oldStatus != null",
  //       newObj
  //     );
  //   } else {
  //     newObj = [myObj];
  //     console.log("******* newObj = [myObj]", newObj);
  //   }
  // }
  // return newObj;
};

const initStatusRealm = async (
  uri,
  DocumentImageName,
  activityId,
  quoteNumber,
  licensePlateNumber
) => {
  try {
    const oldStatus = await Database.get("PIMediaStatus");
    var PIVechicleData = await Database.get("PIVechicleData");
    const activityTypeId = PIVechicleData?.activityTypeId;
    const imageObj = [
      {
        status: "pending", //  pending,uploading, uploaded, failed
        uri: uri,
        imageName: DocumentImageName,
      },
    ];

    const currentActivityObj = [
      {
        activityId: activityId,
        activityTypeId: activityTypeId,
        policyNumber: quoteNumber,
        regNumber: licensePlateNumber,
        activityStatus: "PENDING", // PENDING, IN-PROGRESS, COMPLETED ,FAILED  // this is the status of activity not a perticular image
        mode: "ONLINE", // ONLINE, OFFLINE  // have to make dyanamic
        mediaUpload: imageObj,
        date: moment().format("DD MMM YYYY"),
      },
    ];

    const newObj = await addMediaStatusObj(oldStatus, currentActivityObj);
    console.log(
      "CommonFuction.js OfflineFlow newObj : ",
      JSON.stringify(newObj, null, "  ")
    );
    await Database.set("PIMediaStatus", newObj);
    const PIMediaStatus = await Database.get("PIMediaStatus");
    console.log(
      "CommonFuction.js OfflineFlow PIMediaStatus initStatusRealm",
      JSON.stringify(PIMediaStatus, null, "  ")
    );
  } catch (error) {
    console.log("Error in CommonFunc.js Offline initStatusRealm : ", error);
  }
};

// POSE DETECTION API CALL
export const callPoseDetection = async (
  uri,
  DocumentImageName,
  poseDetectionSucess,
  poseDetectionFailed
) => {
  try {
    var PIVechicleData = await Database.get("PIVechicleData");
    var PIRetryCount = await Database.get("PIRetryCount");
    var activityId = PIVechicleData?.activityId;
    var licensePlateNumber = PIVechicleData?.licensePlateNumber;
    var quoteNumber = PIVechicleData?.quoteNumber;
    var activityTypeId = PIVechicleData?.activityTypeId;

    let isBlur = true,
      isDark = true;
    let imgPose;
    let poseName;
    let isDetect;
    let message;
    var formdata = new FormData();
    var ext = DocumentImageName == "VDO" ? ".mp4" : ".jpg";
    formdata.append("file", {
      uri: uri,
      name: activityId + "_" + DocumentImageName + ext,
      fileName: activityId + "_" + DocumentImageName,
      type: "image/jpeg",
    });

    formdata.append("policyNumber", licensePlateNumber);
    formdata.append("activityTypeId", `${activityTypeId}`);
    formdata.append("checkQuality", true);
    formdata.append("source", "DIGITEDGE");

    console.log("Pose Detection started for ", DocumentImageName);
    console.log("Pose Detection started for formdata : ", formdata);

    const poseDetectionData = await poseDetection(formdata);
    console.log(
      "CommonFunc : pose dection resp parse : ",
      poseDetectionData?.image_pose_array
    );
    isBlur = poseDetectionData?.image_pose_array[0]?.is_blurred;
    isDark = poseDetectionData?.image_pose_array[0]?.is_dark;
    imgPose = poseDetectionData?.image_pose_array[0]?.image_pose;
    console.log("isBlur : isDark : imgPose: ", isBlur, isDark, imgPose);
    poseName = get4WPoseFileNames();

    // if image is type of document like RC/DL
    if (imgPose == DOC) {
      var isIncorrect = false;
      var poseNameNotDoc = get2WPoseFileNotDoc(); // gating Doc
      poseNameNotDoc.forEach((item) => {
        //RCB
        if (item == DocumentImageName) {
          isIncorrect = true;
        }
      });

      if (!isIncorrect) {
        isDetect == true;
      }
    } else {
      // if it is purly images
      poseName.forEach((item) => {
        if (item == imgPose) {
          if (imgPose == DocumentImageName) {
            isDetect = true;
          }
        }
      });
    }

    if (!detectOnlyPoseFileNames().includes(imgPose) && (isBlur || isDark)) {
      isDetect = false;
    }
    console.log("isBlur", isBlur);
    console.log("isDark", isDark);

    if (!isDetect) {
      UELogEvent("is detect is false", {
        isDetect: JSON.stringify(!isDetect),
      });
      var multiCapturePose = true;
      var multiPoseName = "";

      var pose = multiplePics();
      pose.forEach((item) => {
        if (
          DocumentImageName !== undefined &&
          DocumentImageName.includes(item)
        ) {
          multiCapturePose = true;
          multiPoseName = item;
        }
      });

      if (isBlur && isDark) {
        message = image_pose_blur + " " + image_pose_dark;
      } else {
        if (isDark) message = image_pose_dark;
        if (isBlur) message = image_pose_blur;
        if (!isDark && !isBlur) message = image_pose_wrong;
      }
    }

    if (!isBlur && !isDark && isDetect) {
      //if image is good then excute this block
      // upload image
      await poseDetectionSucess();
    } else {
      await poseDetectionFailed();
      //create sensor data ==> if image not  uploaded
      UELogMessage("create sensor data ==> if image not  uploaded");
    }
  } catch (error) {
    await poseDetectionFailed();
    console.log("Error catch : commonFunc.js callPoseDetection : ", error);
  }
};

//CALL CHASSIS POSE DETECTION
export const callChassisPoseDetection = async (
  uri,
  DocumentImageName,
  chassiesPoseDetectionSucess,
  chassiesPDetectionFailed
) => {
  var PIRetryCount = await Database.get("PIRetryCount");
  var PIVechicleData = await Database.get("PIVechicleData");
  var activityId = PIVechicleData?.activityId;
  var formdata = new FormData();
  var ext = DocumentImageName == "VDO" ? ".mp4" : ".jpg";

  formdata.append("file", {
    uri: uri,
    name: activityId + "_" + DocumentImageName + ext,
    fileName: activityId + "_" + DocumentImageName,
    type: "image/jpeg",
  });
  console.log("888888888888888888", activityId);
  formdata.append("activityId", activityId);

  try {
    var ChassisPoseDetectionData = await chassiesPoseDetetction({
      body: formdata,
    });
    console.log("chassis pose detection   >>>", ChassisPoseDetectionData);
  } catch (e) {
    console.log("***PreviewImage, error in chassiesPoseDetection =>", e);
  }

  if (
    ChassisPoseDetectionData &&
    ChassisPoseDetectionData?.match_ratio >
      ChassisPoseDetectionData?.threshold_match_ratio
  ) {
    console.log("Chassis Sucess : CommonmFunc : ");
    await chassiesPoseDetectionSucess();
  } else {
    console.log("Chassis fail : CommonmFunc : ");
    await chassiesPDetectionFailed();
  }
};

export const updateActivityStatus = async (ActivityStatus, currentActivity) => {
  try {
    const mediaStatusArray = await Database.get("PIMediaStatus");
    console.log("mediaStatusObjs : ", mediaStatusArray, currentActivity);

    var currentActivityData = mediaStatusArray?.filter((activity) => {
      return activity.activityId == currentActivity?.activityId;
    });

    const updatedActivityData = [
      {
        ...currentActivityData[0],
        activityStatus: ActivityStatus,
      },
    ];
    console.log(
      "CommonFunc : updateActivityStatus : ",
      JSON.stringify(updatedActivityData, null, "  ")
    );

    // search and delete previous obj
    const activityWithOutCurrentActivity = mediaStatusArray.filter(
      (activity) => {
        console.log(
          "activity.activityId != PIVechicleData?.activityId",
          activity.activityId,
          currentActivity?.activityId,
          activity.activityId != currentActivity?.activityId
        );
        return activity.activityId != currentActivity?.activityId;
      }
    );

    console.log(
      "CommonFunc : activityWithOutCurrentActivity : ",
      !!activityWithOutCurrentActivity,
      JSON.stringify(activityWithOutCurrentActivity, null, "  ")
    );
    var finalActivity;
    if (!!activityWithOutCurrentActivity) {
      // if present then
      finalActivity = [
        ...activityWithOutCurrentActivity,
        updatedActivityData[0],
      ];
      console.log(
        "CommonFunc : updateActivityStatus Activity Found : ",
        JSON.stringify(finalActivity, null, "  ")
      );
    } else {
      // if not present previously
      finalActivity = updatedActivityData;
      console.log(
        "CommonFunc : updateActivityStatus Activity not Found : ",
        JSON.stringify(finalActivity, null, "  ")
      );
    }
    // setting all data in DB
    await Database.set("PIMediaStatus", finalActivity);

    const alog = await Database.get("PIMediaStatus");
    console.log(
      "CommonFunc : updateActivityStatus PIMediaStatus : ",
      JSON.stringify(alog, null, "  ")
    );
  } catch (error) {
    console.log("Error CommonFunc.js updateActivityStatus : ", error);
  }
};

export const updateActivityId = async (activityDetails, activityId) => {
  try {
    var mediaStatusArray = await Database.get("PIMediaStatus");

    // remove current activity from PIMediaStatus DB
    var removedActivityToChange = mediaStatusArray.filter((activity) => {
      return activity.activityId != activityDetails.activityId;
    });

    console.log("removedActivityToChange : ", removedActivityToChange);

    var updateActivityIdObj = {
      ...activityDetails,
      activityId: activityId,
    };
    console.log("updateActivityIdObj : ", updateActivityIdObj);
    var updateMediaActivityObj = updateActivityIdObj.mediaUpload.map(
      (mediaItem) => {
        return { ...mediaItem, mObjActivityId: activityId };
      }
    );
    var updatedActivityWithMediaObj = {
      ...updateActivityIdObj,
      mediaUpload: updateMediaActivityObj,
    };

    var allActivity = [...removedActivityToChange, updatedActivityWithMediaObj];

    console.log(
      "CommonFunc : updateActivityId allActivity : ",
      JSON.stringify(allActivity, null, "  ")
    );

    // setting all data in DB
    await Database.set("PIMediaStatus", allActivity);

    const alog = await Database.get("PIMediaStatus");

    console.log(
      "CommonFunc : updateActivityId PIMediaStatus : ",
      JSON.stringify(alog, null, "  ")
    );
  } catch (error) {
    console.log("Error CommonFunc.js updateActivityId : ", error);
  }
};

export const canCreateActivityId = (activityId) => {
  if (typeof activityId === "string") {
    if (activityId.includes("Offline_")) {
      return true;
    }
  }
  return false;
};

export const getCurrentActivity = async () => {
  const PIMediaStatus = await Database.get("PIMediaStatus");
  const PIVechicleData = await Database.get("PIVechicleData");

  var currentActivity = PIMediaStatus.filter((item) => {
    return item.activityId == PIVechicleData.activityId;
  });
  return currentActivity[0];
};

export const canUpload = (imageName) => {
  try {
    if (
      imageName == "SF" ||
      imageName == "VDO" ||
      imageName == "SF" ||
      imageName == "CNG" ||
      imageName == "IWS" ||
      imageName?.includes("RCB") ||
      imageName == "PUC"
    ) {
      // console.log("canUpload() :CommonFunc : sucess");
      return true;
    } else {
      // console.log("canUpload() :CommonFunc : fail");
      return false;
    }
  } catch (error) {
    console.log("Error : canUpload() :CommonFunc : ", error);
  }
};

export const wait = async (milliseconds = 500) => {
  console.log("##WAITING... ", new Date());

  return await new Promise((resolve) => {
    const timer = setTimeout(() => {
      clearTimeout(timer);

      console.log("###WAIT OVER. ", new Date());

      resolve(true);
    }, milliseconds);
  });
};

export const getUserType = async () => {
  var type;
  var AppLoginStatus = await Database.get("AppLoginStatus");
  const USERTYPE = AppLoginStatus?.userType;
  switch (USERTYPE) {
    case "Customer":
      type = "CUSTOMER";
      break;
    case "DealerOrAgent":
      type = "AGENT";
      break;
    case "OEMDealer":
      type = " OEM DEALER";
      break;
    default:
      type = "CUSTOMER";
      break;
  }
  console.log("USER TYPE : CommonFunc : ", type);
  return type;
};
