import React from 'react';
import { dbbackupFolder, fixedurl, baseurl, version, db, OQAD_TimeConst, ImageFolderPath, common_ImagePath, KPIFolders, defUploadFolder, VisitorImageFolderPath, FolderForREC, StoreCheckListImagePath, TrainingContentFolderPath, NonProgramLabel_def, StoreSearch_def, ContractFormImagePath, ServerDTurl, CoverageImagePath, visiCoolerImgPath, VisitorLoginImageFolderPath, AddStoreImagePath, URL_IMAGE, kycImagePath, LAST_ServerAPI_CALL, DevType, OLA_MAP_KEY, API_TIMEOUT, GroomingImagePath } from '../constants/constants';
// import Marker, { ImageFormat, Position } from 'react-native-image-marker';
import { manipulateAsync, SaveFormat } from 'react-native-photo-manipulator';
import moment from 'moment';
import { notify } from '../components/notify';
import { AppTables, Table_Structure } from '../constants/tableConstants';
import ImageResizer from 'react-native-image-resizer';
import { get_item } from '../components/localStorage';
import { Q_ALLScreenName, Q_MenuList } from '../constants/ConstantQueries';
import * as RNFS from 'react-native-fs';
import { METHODS, getMethodName } from '../constants/methodNames';
import ImageMarkText from '../components/ImageMarkText';
import { getTimeZone } from "react-native-localize";
import NOTIFICATIONAPISERVICES from '../NotificationApiService';
///jp
import AsyncStorage from '@react-native-async-storage/async-storage';
import NetInfo from '@react-native-community/netinfo';
import { Dimensions, Platform, Linking, PermissionsAndroid } from 'react-native';
import Geolocation from "react-native-geolocation-service";
import SendIntentAndroid from 'react-native-send-intent';
import { Alert } from 'react-native';
import RNExitApp from 'react-native-exit-app';
import Contacts from 'react-native-contacts';

export async function getProjectData(pid) {
  let post_data = { "projectCode": pid, "appName": "Merchandiser", "deviceType": Platform.OS == "ios" ? "iOS" : "Android", "appVariant": DevType }
  const raw = JSON.stringify({
    "Params":
      post_data

  });
  console.log("jsonPay", raw, fixedurl)
  return await fetch(fixedurl, {
    method: 'post',
    headers: {
      'Content-Type': 'application/json',
    },
    body: raw,
  }).then(response => {
    return response.json();
  }).then(res => {
    console.log("project_data_res_info", res);
    let appdata = res.GetAppSettingWithDeviceInfo || [];
    let appdata1 = appdata.length > 0 ? appdata[0] : {};
    appdata1.success = true;
    return {
      success: true,
      rawData: raw,
      responseData: appdata1,
    };
  }).catch(err => {
    console.log('getProjectData error', err);
    return {
      success: false,
      rawData: raw,
    };
  });
}

// getServerDT function for matching and validating the local date time of users’ device with server date time.
export async function getServerDT() {
  const timezone = await getTimeZone();
  console.log('timezone from location => ', timezone)
  // const apiUrl = `https://worldtimeapi.org/api/timezone/${timezone}`;
  const apiUrl = `https://timeapi.io/api/Time/current/zone?timeZone=${timezone}`
  try {
    console.log("apiUrl--------", apiUrl)
    const response = await fetch(apiUrl);

    if (!response.ok) {
      throw new Error('Network response was not ok');
    }

    const res = await response.json();
    // Extract and format date and time
    const datetime = res?.dateTime ? new Date(res?.dateTime) : moment(new date()).format('HH:mm:ss');
    const formattedDate = res?.date;
    // const formattedDate = `${('0' + (datetime.getMonth() + 1)).slice(-2)}/${('0' + datetime.getDate()).slice(-2)}/${datetime.getFullYear()}`;
    // const formattedTime = `${('0' + datetime.getHours()).slice(-2)}:${('0' + datetime.getMinutes()).slice(-2)}:${('0' + datetime.getSeconds()).slice(-2)}`;
    const formattedTime = res?.dateTime ? moment(res?.dateTime).format("HH:mm:ss") : datetime
    let CheckTime = `${formattedDate} ${formattedTime}`
    const finalData = { ServerDate: formattedDate, ServerTime: formattedTime, CheckTime: CheckTime }
    console.log('formate date and time => ', finalData)
    return finalData;
  } catch (err) {
    console.log('getServerDT error', err);
    return await getFallbackTime();
  }
}

async function getFallbackTime() {
  const tz_offset = new Date().getTimezoneOffset();
  const offset = tz_offset < 0 ? Math.abs(tz_offset) : -Math.abs(tz_offset);

  console.log("offset:", offset);
  try {
    const response = await fetch(ServerDTurl, {
      method: 'post',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ "offset": offset }),
    });

    if (!response.ok) {
      throw new Error('Network response was not ok');
    }

    const res = await response.json();
    console.log("project datares", res);
    const appdata = res.GetServerDateTime_INTL || [];
    const appdata1 = appdata.length > 0 ? appdata[0] : {};
    console.log('appdata1 => ', appdata1)
    return appdata1;
  } catch (err) {
    console.log('getFallbackTime error', err);
    return { success: false, error: err };
  }
}

export async function changepassword(url, indata) {

  const data = JSON.stringify({
    "UserName": indata?.un,
    "OldPassword": indata?.oldp,
    "NewPassword": indata?.newp
  });

  console.log(data, "confirm password data.");

  return await fetch(url, {
    method: 'post',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
    },
    body: data,
  })
    .then(response => {
      return response.json();
    })
    .then(res => {
      let appdata = res || '';
      appdata.success = true;
      return appdata;
    })
    .catch(err => {
      console.log('password change error', err);
      return { success: false };
    });
}

export async function getmobileverifyotp(url, indata) {

  const data = JSON.stringify({
    "mobileno": indata?.mobileno,
    "projectcode": indata?.projectcode
  });

  console.log(data, url, "send otppp mobile surveyyy")

  return await fetch(url, {
    method: 'post',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
    },
    body: data,
  })
    .then(response => {
      return response.json();
    })
    .then(res => {
      let appdata = res?.CheckUserAndSendOTP || {};
      if (appdata) {
        return appdata;
      } else {
        return { ...appdata, Status: true };  // Or any default status you prefer
      }
    })
    .catch(err => {
      console.log('get verify mobile otp error', err);
      return { Status: false, error: err, networkErr: networkErr };
    });
}

export async function verifymobileotp(url, indata) {

  const data = JSON.stringify({
    "mobileno": indata?.mobileno,
    "otp": indata?.otp
  });

  return await fetch(url, {
    method: 'post',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
    },
    body: data,
  })
    .then(response => {
      return response.json();
    })
    .then(res => {
      let appdata = res?.otpauthentication || {};
      if (appdata) {
        return appdata;
      } else {
        return { ...appdata, Status: true };  // Or any default status you prefer
      }
    })
    .catch(err => {
      console.log('verify mobile otp error', err);
      return { success: false };
    });
}

export async function getforgotpasswordotp(url, indata) {

  const data = JSON.stringify({
    "Username": indata?.un
  });

  console.log(data, url, "send otppp")

  return await fetch(url, {
    method: 'post',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
    },
    body: data,
  })
    .then(response => {
      return response.json();
    })
    .then(res => {
      let appdata = res?.OTPSendForForgetPasswordResult || {};
      if (appdata.Status === true || appdata.Status === false) {
        return appdata;
      } else {
        return { ...appdata, Status: true };  // Or any default status you prefer
      }
    })
    .catch(err => {
      console.log('get otp error', err);
      return { Status: false, error: err, networkErr: networkErr };
    });
}

export async function verifyotp(url, indata) {

  const data = JSON.stringify({
    "Username": indata?.un,
    "OTP": indata?.otp
  });

  return await fetch(url, {
    method: 'post',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
    },
    body: data,
  })
    .then(response => {
      return response.json();
    })
    .then(res => {
      let appdata = res?.OTPVerifyResult || {};
      if (appdata.Status === true || appdata.Status === false) {
        return appdata;
      } else {
        return { ...appdata, Status: true };  // Or any default status you prefer
      }
    })
    .catch(err => {
      console.log('verify otp error', err);
      return { success: false };
    });
}

export async function createnewpassword(url, indata) {

  const data = JSON.stringify({
    "Username": indata?.un,
    "Password": indata?.newp
  });

  return await fetch(url, {
    method: 'post',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
    },
    body: data,
  })
    .then(response => {
      return response.json();
    })
    .then(res => {
      let appdata = res?.NewPasswordResult || {};
      if (appdata.Status === true || appdata.Status === false) {
        return appdata;
      } else {
        return { ...appdata, Status: true };  // Or any default status you prefer
      }
    })
    .catch(err => {
      console.log('create new password error', err);
      return { success: false };
    });
}


// export async function getNotificationList() {
//   try {
//     let projectInfo = await get_item('projectInfo');
//     let projectDetails = projectInfo != null ? JSON.parse(projectInfo) : {};

//     let loginInfo = await get_item('loginInfo');
//     const loginDetails = JSON.parse(loginInfo);
//     const data = { UserName: loginDetails?.UserId, ProjectCode: projectDetails?.ProjectCode };

//     const resdata = await NOTIFICATIONAPISERVICES.getnotificationlist.post(data);

//     console.log('resDataaa', resdata);

//     if (resdata?.GetNotificationListofUser) {
//       // If GetNotificationListofUser exists, process it
//       const notificationList = resdata.GetNotificationListofUser;

//       if (notificationList.Data && Array.isArray(notificationList.Data)) {
//         // If Data is an array, handle it accordingly
//         console.log('Notification List:', notificationList);
//         return { ...notificationList, success: true };
//       } else {
//         // If Data is not an array or empty, return an empty result
//         console.log('Empty or invalid data in Notification List:', notificationList);
//         return { ...notificationList, success: false };
//       }
//     } else {
//       // If GetNotificationListofUser does not exist, handle the error
//       console.log('Invalid response format:', resdata);
//       return { success: false, error: 'Invalid response format', data: resdata };
//     }
//   } catch (err) {
//     console.log('notification error', err);
//     return { success: false, error: err, networkErr: true };
//   }
// }

export function AlertForServerDT(currDate, d2) {
  Alert.alert(
    "",
    `Your Device Date and Time is not correct. Please correct and restart App.

      Server Date - ${currDate}
      Device Date - ${d2}
      `,
    [
      {
        // text: "Cancel",
        // onPress: () => {},
        // style: "cancel"
      },
      {
        text: "OK", onPress: async () => {
          RNExitApp.exitApp();
          // setHasUnsavedChanges(false);
          // BgUnsavedChanges(false)
          // await clear_item('storeData')
          // props.navigation.dispatch(e.data.action);
        }
      }
    ]
  );
}

// export async function login(url, indata) {
//   const pdata = JSON.stringify({
//     UserName: indata.un,
//     Password: indata.pass,
//     Intime: indata.Intime,
//     Latitude: indata.lat,
//     Longitude: indata.lng,
//     Appversion: version,
//     Attmode: '0',
//     Networkstatus: '0',
//     Manufacturer: indata.manufacturer,
//     ModelNumber: indata.model,
//     OSVersion: indata.os,
//     IMEINumber1: indata.imeiNo1,
//     IMEINumber2: indata.imeiNo2,
//   });

//   console.log(pdata);


//   return await fetch(url, {
//     method: 'post',
//     headers: {
//       'Accept': 'application/json',
//       'Content-Type': 'application/json',
//     },
//     body: pdata,
//   })
//     .then(response => {
//       return response.json();
//     })
//     .then(res => {
//       try {
//         var resdata = JSON.parse(res);
//       }
//       catch (err) {
//         console.log('login error', err + "----pdat-----"+pdata);
//         var resdata = res;
//       }
//       if (resdata.LOGIN != null) {
//         resdata = resdata.LOGIN.length > 0 ? resdata.LOGIN[0] : {};
//         resdata.success = true;
//       } else if (Array.isArray(resdata) && resdata.length > 0 && resdata[0].Result != null) {
//         resdata = { success: false, error: 'Invalid username or password (' + JSON.stringify(resdata) + ')' };
//       } else {
//         resdata = { success: false, error: resdata };
//       }

//       return resdata;
//     })
//     .catch(err => {
//       console.log('login error', err + "----pdat-----"+pdata);
//       let networkErr = true;
//       return { success: false, error: err, networkErr: networkErr };
//     });
// }

export async function login(url, indata, retries = 3) {
  const pdata = JSON.stringify({
    UserName: indata.un,
    Password: indata.pass,
    Intime: indata.Intime,
    Latitude: indata.lat,
    Longitude: indata.lng,
    Appversion: version,
    Attmode: '0',
    Networkstatus: '0',
    Manufacturer: indata.manufacturer,
    ModelNumber: indata.model,
    OSVersion: indata.os,
    IMEINumber1: indata.imeiNo1,
    IMEINumber2: indata.imeiNo2,
  });

  // ⚠️ Avoid heavy logs in production
  // console.log(pdata);
  const fetchWithTimeout = async (url, options, timeout = 10000) => {
    const controller = new AbortController();
    const id = setTimeout(() => controller.abort(), timeout);
    try {
      const response = await fetch(url, {
        ...options,
        signal: controller.signal,
      });
      clearTimeout(id);
      return response;
    } catch (err) {
      clearTimeout(id);
      throw err;
    }
  };

  try {
    const response = await fetchWithTimeout(url, {
      method: 'post',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
      },
      body: pdata,
    });

    const res = await response.json();
    let resdata;

    try {
      // ⚠️ Keep your original logic intact
      resdata = typeof res === 'string' ? JSON.parse(res) : res;
    } catch (err) {
      console.log('login error', err + "----pdat-----" + pdata);
      resdata = res;
    }

    if (resdata.LOGIN != null) {
      resdata = resdata.LOGIN.length > 0 ? resdata.LOGIN[0] : {};
      resdata.success = true;
    } else if (
      Array.isArray(resdata) &&
      resdata.length > 0 &&
      resdata[0].Result != null
    ) {
      resdata = {
        success: false,
        error:
          'Invalid username or password (' +
          JSON.stringify(resdata) +
          ')',
      };
    } else {
      resdata = { success: false, error: resdata };
    }

    return resdata;

  } catch (err) {

    // 🔁 Retry logic (only for network/timeout errors)
    if (retries > 0) {
      console.log(`Retrying login... attempts left: ${retries}`);
      await new Promise(res => setTimeout(res, 1000));
      return login(url, indata, retries - 1);
    }

    console.log('login error', err + "----pdat-----" + pdata);

    return {
      success: false,
      error: err,
      networkErr: true,
    };
  }
}

export async function CreateDirKPIimg() {

  console.log('CreateDirKPIimg:');
  let allKPIsList = await getScreenNameList();
  await RNFS.mkdir(ImageFolderPath);
  await RNFS.mkdir(VisitorImageFolderPath);
  await RNFS.mkdir(VisitorLoginImageFolderPath);
  await RNFS.mkdir(VisitorImageFolderPath + 'Recordings/');
  await RNFS.mkdir(StoreCheckListImagePath);
  await RNFS.mkdir(TrainingContentFolderPath);
  await RNFS.mkdir(ContractFormImagePath);
  await RNFS.mkdir(CoverageImagePath);
  await RNFS.mkdir(AddStoreImagePath);
  await RNFS.mkdir(visiCoolerImgPath);
  await RNFS.mkdir(kycImagePath);
  await RNFS.mkdir(dbbackupFolder);
  await RNFS.mkdir(GroomingImagePath);
  await Promise.all(
    allKPIsList.map(async (name, index) => {
      const url_dir = ImageFolderPath + `${name.ScreenName}/`;
      await RNFS.mkdir(url_dir);
      await RNFS.mkdir(url_dir + 'Recordings/');
    })
  ).then(() => {
    console.log("Directory is created successfully")
    return
  });


}

async function getScreenNameList() {

  return new Promise((resolve, reject) => {
    db.transaction(async function (txn) {
      let q = Q_ALLScreenName();
      await txn.executeSql(q, [], async function (txn2, txnres) {
        if (txnres.rows.length > 0) {
          let arr = [];
          for (var i = 0; i < txnres.rows.length; i++) {
            let data = txnres.rows.item(i);
            arr.push(data);
            if (i == (txnres.rows.length - 1)) {
              resolve(arr);
            }
          }
        }
        else {
          resolve([])
        }
      }, function (txnerr) { console.log(txnerr); resolve([]); },);
    });
  }).then((val) => {
    return val;
  }).catch((err) => {
    console.log('')
    return []
  })
}

export async function getAllFolderImages() {

  let mainImgFolder = ImageFolderPath
  // let galleryImages=await getAllGalleryImages();
  let allKPIfiles = await getAllOldImages();
  const SubFolders = await RNFS.readDir(mainImgFolder);


  return new Promise.all(
    SubFolders.map(async sfolder => {
      // console.log("sfolder.name",sfolder.name)
      if (sfolder.isDirectory()) {
        let KPIName = sfolder.name

        let subFolPath = sfolder.path;
        let Up_Foldername = KPIFolders[KPIName] != null && KPIFolders[KPIName] != '' ? KPIFolders[KPIName] : defUploadFolder;

        const ImgFiles = await RNFS.readDir(subFolPath);
        return new Promise.all(
          ImgFiles.map(async sfile => {
            if (sfile.isFile() && (sfile.name.includes('jpg') || sfile.name.includes('jpeg') || sfile.name.includes('png'))) {

              let file = {
                uri: sfile.path,
                type: 'image/jpeg',
                name: sfile.name,
                filetype: 'image',
                folderName: Up_Foldername,
              }
              allKPIfiles.push(file);
              return file;
            }
            else if (sfile.isDirectory() && sfile.name == 'Recordings') {
              let recordingsPath = sfile.path;
              let recordingFiles = await RNFS.readDir(recordingsPath);
              let VoiceUp_FolderPath = FolderForREC[KPIName];
              return new Promise.all(
                recordingFiles.map(async rfile => {

                  if (rfile.isFile() && (rfile.name.includes('m4a') || rfile.name.includes('mp3'))) {

                    let file = {
                      uri: rfile.path,
                      type: (Platform.OS == 'ios' ? 'audio/m4a' : 'audio/mp3'),
                      name: rfile.name,
                      filetype: 'audio',
                      folderName: VoiceUp_FolderPath,
                    }
                    allKPIfiles.push(file);
                    return file;
                  }
                  else {
                    return '';
                  }

                })
              ).then((val2) => {
                return val2;
              });
            }
            else {
              return '';
            }
          })
        ).then((val1) => {
          return val1;
        })
      } else {
        return '';
      }
    })
  )
    .then((val) => {
      // console.log('AllImages:',allKPIfiles.length,allKPIfiles);
      return allKPIfiles;
    }).catch((Err) => {
      console.log('Err:', Err);
      return [];
    })

}

export async function getAllFileForAFolder(path, Up_Foldername, KPIName = '') {

  let subFolPath = path;
  const ImgFiles = await RNFS.readDir(subFolPath);
  Up_Foldername = Up_Foldername != null && Up_Foldername != '' ? Up_Foldername : defUploadFolder;

  console.log("ImgFiles in ", subFolPath, ' are:', ImgFiles.length);
  let allKPIfiles = [];
  return new Promise.all(
    ImgFiles.map(async sfile => {
      if (sfile.isFile() && (sfile.name.includes('jpg') || sfile.name.includes('jpeg') || sfile.name.includes('png'))) {

        let file = {
          uri: sfile.path,
          type: 'image/jpeg',
          name: sfile.name,
          filetype: 'image',
          folderName: Up_Foldername,
        }
        allKPIfiles.push(file);
        return file;
      }
      else if (sfile.isDirectory() && sfile.name == 'Recordings') {
        let recordingsPath = sfile.path;
        let recordingFiles = await RNFS.readDir(recordingsPath);
        let VoiceUp_FolderPath = KPIName != null && KPIName != '' ? FolderForREC[KPIName] : defUploadFolder;
        return new Promise.all(
          recordingFiles.map(async rfile => {

            if (rfile.isFile() && (rfile.name.includes('m4a') || rfile.name.includes('mp3'))) {

              let file = {
                uri: rfile.path,
                type: (Platform.OS == 'ios' ? 'audio/m4a' : 'audio/mp3'),
                name: rfile.name,
                filetype: 'audio',
                folderName: VoiceUp_FolderPath,
              }
              allKPIfiles.push(file);
              return file;
            }
            else {
              return '';
            }

          })
        ).then((val2) => {
          return val2;
        });
      }
      else {
        return '';
      }
    })
  ).then((val1) => {
    console.log('getAllFileForAFolder', val1);
    return allKPIfiles;
  }).catch((err) => {
    console.log('error in getAllFileForAFolder', err);
    return allKPIfiles;
  })

}

async function getFolderNameFromFile(filename) {
  let fn = ''
  if (filename.includes('_CEImg-')) {
    fn = KPIFolders['CATEXEONEAPP'];
  }
  else if (filename.includes('_SurveyImg_')) {
    fn = KPIFolders['SURVEY'];
  }
  else {
    fn = defUploadFolder;
  }
  return fn;
}

async function getAllOldImages() {
  let pathOldFolder = common_ImagePath;
  const AllImages = await RNFS.readDir(pathOldFolder);
  console.log('getAllOldImages', pathOldFolder, AllImages.length)
  let allKPIfiles = [];
  return new Promise.all(
    AllImages.map(async sfile => {
      if (sfile.name.includes('jpg') || sfile.name.includes('jpeg') || sfile.name.includes('png')) {
        let Up_Foldername = await getFolderNameFromFile(sfile.name);
        Up_Foldername = Up_Foldername != '' && Up_Foldername != null ? Up_Foldername : defUploadFolder;
        console.log('Up_Foldername', Up_Foldername);
        let file = {
          uri: sfile.path,
          type: 'image/jpeg',
          name: sfile.name,
          filetype: 'image',
          folderName: Up_Foldername,
        }
        allKPIfiles.push(file);
        return file;
      }
      else {
        return '';
      }
    })
  ).then((val) => {
    console.log('oldimages:', allKPIfiles.length);
    return allKPIfiles;
  }).catch((Err) => {
    console.log('Err:', Err);
    return [];
  })

}

async function getAllGalleryImages() {
  let pathOldFolder = RNFS.DownloadDirectoryPath;
  const AllImages = await RNFS.readDir(pathOldFolder);
  console.log('getAllGalleryImages', pathOldFolder, AllImages.length)
  let allKPIfiles = [];
  return new Promise.all(
    AllImages.map(async sfile => {
      if (sfile.isFile() && sfile.name.includes('_SurveyImg_')) {
        let Up_Foldername = KPIFolders['SURVEY'];

        let file = {
          uri: sfile.uri,
          type: 'image/jpeg',
          name: sfile.name,
          filetype: 'image',
          folderName: Up_Foldername,
        }
        allKPIfiles.push(file);
        return file;
      }
      else {
        return '';
      }

    })
  ).then((val) => {
    console.log('AllGalleryImages:', allKPIfiles.length, allKPIfiles[0]);
    return allKPIfiles;
  }).catch((Err) => {
    console.log('Err:', Err);
    return [];
  })

}

export async function getDownloadJson(url, indata) {
  let postdata = {
    Downloadtype: indata.Downloadtype,
    Username: indata.username,
    Param1: indata.empid,
    Param2: Platform.OS === "ios" ? "iOS" : "Android",
  };
  console.log('📡 getDownloadJson postdata:', url, postdata);
  // --- Timeout setup ---
  const controller = new AbortController();
  const timeoutId = setTimeout(() => controller.abort(), API_TIMEOUT);
  // --- Original fetch chain with timeout ---
  return await fetch(url, {
    method: 'POST',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(postdata),
    signal: controller.signal, // attach abort controller
  })
    .then(response => {
      clearTimeout(timeoutId);
      return response.json();
    })
    .then((res) => {
      try {
        // Sometimes API already returns JSON; sometimes it’s a stringified JSON
        let resd = typeof res === 'object' ? res : JSON.parse(res);
        return resd;
      } catch (e) {
        console.log('⚠️ JSON parse error:', e.message);
        return { success: false };
      }
    })
    .catch(err => {
      clearTimeout(timeoutId);
      if (err.name === 'AbortError') {
        console.log(`⏰ getDownloadJson timed out after ${API_TIMEOUT / 1000}s`);
      } else {
        console.log('❌ getDownloadJson error:', err.message || err);
      }

      return { success: false };
    });
}

export async function getDownloadJson1(url, postdata) {
  // Setup AbortController for timeout
  const controller = new AbortController();
  const timeoutId = setTimeout(() => controller.abort(), API_TIMEOUT);
  return await fetch(url, {
    method: 'POST',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(postdata),
    signal: controller.signal, // attach timeout controller
  })
    .then(response => {
      clearTimeout(timeoutId);
      return response.json();
    })
    .then((res) => {
      // console.log('res', res);
      let resd;
      try {
        if (url.includes('api1.parinaam.in')) {
          resd = res; // already JSON
        } else {
          resd = typeof res === 'object' ? res : JSON.parse(res);
        }
      } catch (e) {
        console.log('⚠️ JSON parse error in getDownloadJson1:', e.message);
        resd = { success: false };
      }

      return resd;
    })
    .catch(err => {
      clearTimeout(timeoutId);
      if (err.name === 'AbortError') {
        console.log(`⏰ getDownloadJson1 timed out after ${API_TIMEOUT / 1000}s`);
      } else {
        console.log('❌ getDownloadJson1 error:', err.message || err);
      }
      // Keep same return type (return error itself or object)
      return { success: false, error: err.name === 'AbortError' ? 'Timeout' : err.message };
    });
}




export async function UploadData(url, indata) { // default 30 seconds
  // Create AbortController for timeout
  const controller = new AbortController();
  const timeoutId = setTimeout(() => controller.abort(), API_TIMEOUT);

  return await fetch(url, {
    method: 'POST',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(indata),
    signal: controller.signal, // attach signal for timeout
  })
    .then(response => {
      clearTimeout(timeoutId);
      return response.json();
    })
    .then((res) => {
      clearTimeout(timeoutId);
      try {
        // Handle both already-parsed and stringified JSON
        let resd = typeof res === 'object' ? res : JSON.parse(res);
        return resd;
      } catch (e) {
        console.log('⚠️ UploadData JSON parse error:', e.message);
        return { success: false, error: 'Invalid JSON' };
      }
    })
    .catch(err => {
      clearTimeout(timeoutId);

      if (err.name === 'AbortError') {
        console.log(`⏰ UploadData timed out after ${API_TIMEOUT / 1000}s`);
      } else {
        console.log('❌ UploadData error:', err.message || err);
      }

      return { success: false, error: err.name === 'AbortError' ? 'Timeout' : err.message };
    });
}

export async function UploadData2(url, indata) { // default 30 seconds
  // Setup AbortController for timeout
  const controller = new AbortController();
  const timeoutId = setTimeout(() => controller.abort(), API_TIMEOUT);

  return await fetch(url, {
    method: 'POST',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(indata),
    signal: controller.signal, // enable timeout
  })
    .then(response => {
      clearTimeout(timeoutId);
      return response.json();
    })
    .then((res) => {
      clearTimeout(timeoutId);
      return res; // keep original return structure
    })
    .catch(err => {
      clearTimeout(timeoutId);

      if (err.name === 'AbortError') {
        console.log(`⏰ UploadData2 timed out after ${API_TIMEOUT / 1000}s`);
      } else {
        console.log('❌ UploadData2 error:', err.message || err);
      }

      return { success: false, error: true, errorMsg: err.name === 'AbortError' ? 'Timeout' : err.message };
    });
}

export async function UploadFormData(url, formData) { // default 60 seconds
  // Create abort controller for timeout
  const controller = new AbortController();
  const timeoutId = setTimeout(() => controller.abort(), API_TIMEOUT);

  return await fetch(url, {
    method: 'POST',
    headers: new Headers({
      'Content-Type': 'multipart/form-data',
    }),
    body: formData,
    signal: controller.signal, // attach timeout controller
  })
    .then(response => {
      clearTimeout(timeoutId);
      console.log('UploadData response:', response);
      return response.text(); // keep same structure
    })
    .then((res) => {
      clearTimeout(timeoutId);
      console.log('UploadData result:', res);
      return res; // same as before
    })
    .catch(err => {
      clearTimeout(timeoutId);

      if (err.name === 'AbortError') {
        console.log(`⏰ UploadFormData timed out after ${API_TIMEOUT / 1000}s`);
      } else {
        console.log('❌ UploadFormData error:', err.message || err);
      }

      return { success: false, error: err.name === 'AbortError' ? 'Timeout' : err.message };
    });
}

export const fetchDistanceMatrix = async (stores) => {
  try {
    // 1. Ask for location permission
    if (Platform.OS === "android") {
      const granted = await PermissionsAndroid.request(
        PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION
      );

      if (granted !== PermissionsAndroid.RESULTS.GRANTED) {
        return {
          status: "FAILED",
          message: "Location permission denied",
          data: [],
        };
      }
    }

    // 2. Function to get location
    const getCurrentLocation = () => {
      return new Promise((resolve, reject) => {
        Geolocation.getCurrentPosition(
          (position) => {
            resolve({
              latitude: position.coords.latitude,
              longitude: position.coords.longitude,
            });
          },
          (error) => reject(error),
          {
            enableHighAccuracy: false, // prevents timeout
            timeout: 30000, // 30 seconds
            maximumAge: 60000, // use cached location if available
          }
        );
      });
    };

    // 3. Try getting location (with retry)
    let currentLoc;

    try {
      currentLoc = await getCurrentLocation();
    } catch (error) {
      console.log("Retrying location fetch...");
      currentLoc = await getCurrentLocation();
    }

    // 4. Prepare destinations
    const destinations = stores
      .map((s) => `${s.latitude},${s.longitude}`)
      .join("|");

    // 5. Build API URL
    const url = `https://api.olamaps.io/routing/v1/distanceMatrix?origins=${currentLoc.latitude},${currentLoc.longitude}&destinations=${destinations}&mode=driving&api_key=${OLA_MAP_KEY}`;

    // 6. Fetch API
    const result = await fetchWithRetry(
      url,
      {
        method: "GET",
        headers: { "X-Request-Id": "my-app-request-123" },
      },
      3,
      2000
    );

    // 7. Process result
    const readableArray =
      result?.rows?.[0]?.elements
        ?.map((el, index) => {
          if (el.status !== "OK") return null;

          const formatted = formatRouteData(el.duration, el.distance);

          return {
            StoreId: stores[index]?.StoreId || null,
            ...formatted,
          };
        })
        .filter(Boolean) || [];

    return {
      status: "SUCCESS",
      message: "Distance matrix fetched",
      data: readableArray,
    };
  } catch (error) {
    console.error("Error fetching distance matrix:", error);

    return {
      status: "FAILED",
      message: error.message || "Something went wrong",
      data: [],
    };
  }
};

function formatRouteData(durationSec, distanceMeters) {
  // Distance in km (1 decimal)
  const distanceKm = distanceMeters / 1000;
  // Duration in hours and minutes
  const hours = Math.floor(durationSec / 3600);
  const minutes = Math.floor((durationSec % 3600) / 60);
  // Check if very close
  if (distanceKm < 0.1 && durationSec < 60) {
    return {
      DistanceInMeters: distanceMeters,
      Distance: "Very close to your store!",
      Duration: ""
    };
  }

  return {
    DistanceInMeters: distanceMeters,
    Distance: `${distanceKm.toFixed(1)} Km`,
    Duration: hours > 0 ? `${hours} Hour ${minutes} Minutes` : `${minutes} Minutes`
  };
}
// Generic fetch with retry logic
async function fetchWithRetry(url, options, retries = 6, delay = 2000) {
  for (let i = 0; i < retries; i++) {
    try {
      const response = await fetch(url, options);
      if (!response.ok) throw new Error(`HTTP error! Status: ${response.status}`);
      return await response.json(); // return the parsed JSON
    } catch (err) {
      console.warn(`Fetch attempt ${i + 1} failed:`, err.message);
      if (i < retries - 1) {
        // wait before retry
        await new Promise(res => setTimeout(res, delay));
      } else {
        throw new Error(`Failed after ${retries} attempts: ${err.message}`);
      }
    }
  }
}

export async function DownloadData(props, { isDataDownloaded = false }) {
  if (isDataDownloaded) {
    return true;
  }
  let d1 = new Date();
  let today = moment(d1).format('MM/DD/YYYY');
  return new Promise((resolve, reject) => {
    db.transaction(async function (txn) {

      for (const i in Table_Structure) {
        const table = Table_Structure[i];
        await txn.executeSql(table.SqlText, [], function (txn2, txnres2) {

        },
          function (txnE, txnerr) { console.log(txnerr); });
      }




      // delete all previous data
      let index = 0;
      for (const key in AppTables) {

        // Dont Delete previous IR images Data and session status 
        let SOSIRTable = AppTables[key] == AppTables.SOS_IRUPLOAD || AppTables[key] == AppTables.SOS_IR_IMAGES;
        let PVISIRTable = AppTables[key] == AppTables.PAIDVIS_IRUPLOAD || AppTables[key] == AppTables.PAIDVIS_IR_IMAGES;
        let WINDIRTable = AppTables[key] == AppTables.WINDOW_IRUPLOAD || AppTables[key] == AppTables.WINDOW_IR_IMAGES;
        let AVISIRTable = AppTables[key] == AppTables.ADDVIS_IRUPLOAD || AppTables[key] == AppTables.ADDVIS_IR_IMAGES;
        let CVISIRTable = AppTables[key] == AppTables.COMPVIS_IRUPLOAD || AppTables[key] == AppTables.COMPVIS_IR_IMAGES;
        let PROMOIRTable = AppTables[key] == AppTables.PROMO_IRUPLOAD || AppTables[key] == AppTables.PROMO_IR_IMAGES;
        if (SOSIRTable || PVISIRTable || AVISIRTable || CVISIRTable || WINDIRTable || PROMOIRTable) {
          console.log('Dont Delete previous IR images Data and session status continue.', AppTables[key])
          if (index == Object.keys(AppTables).length - 1) {
            resolve(true);
          }
          index++;
          continue;
        }

        txn.executeSql(`Delete from ${AppTables[key]} where ADDED_DATE!='${today}'`, [], function (txnd, txnresd) {
          if (index == Object.keys(AppTables).length - 1) {
            resolve(true);
          }
          index++;
        },
          function (txnE, txnerr) {
            console.log(txnerr);
            if (index == Object.keys(AppTables).length - 1) {
              resolve(false);
            }
            index++;
          });
      }

    });
  }).catch((err) => {
    console.log('err while creating tables', err)
    return false;
  })


}

export async function getDataPendingStores(props) {
  // returns the stores for which data exists and is not uploaded

  let pendingStores = [];
  return new Promise((resolve, reject) => {
    db.transaction(async function (txn) {

      function getQ(tbname) {
        return `select * from ${tbname} where UploadStatus in ('C','P','D','L')`;
      }

      let MappingJP = getQ('Mapping_JourneyPlan');
      let AdhocJP = getQ('Adhoc_JourneyPlan');

      let storesq = MappingJP + ' UNION ' + AdhocJP;

      if (props.ShowNonMerList == true) {
        let NonMerchJP = getQ('NonMerchandising_JourneyPlan');
        storesq += ` UNION ${NonMerchJP} `;
      }
      if (props.ShowNonProgram == true) {
        let NonProgJP = getQ('NonProgram_JourneyPlan');
        storesq += ` UNION ${NonProgJP} `;
      }
      if (props.ShowStoreSearch == true) {
        let SearchStoreJP = getQ('StoreSearch_JourneyPlan');
        storesq += ` UNION ${SearchStoreJP} `;
      }
      if (props.ShowBeatPlanList == true) {
        let RouteJP = getQ('JourneyPlan_RouteWise');
        storesq += ` UNION ${RouteJP} `;
      }


      txn.executeSql(storesq, [], function (txn2, txnres2) {
        if (txnres2.rows.length > 0) {
          for (var i = 0; i < txnres2.rows.length; i++) {
            let data = txnres2.rows.item(i);
            pendingStores.push(data)
            if (i == txnres2.rows.length - 1) {
              resolve(pendingStores);
            }
          }
        }
        else {
          resolve(pendingStores);
        }
      },
        function (txnE, txnerr) { console.log(txnerr); resolve(pendingStores); });
    });
  }).then((res) => {
    return pendingStores;
  }).catch((err) => {
    console.log("pendingStores err:", err);
    return pendingStores;
  })

}

export async function UpdateStoreStatus(props, data, callback = () => { }, previousDayUpload = false) {
  let d1 = new Date();
  let today = moment(d1).format('MM/DD/YYYY');

  return new Promise((resolve, reject) => {
    if (data && data.UploadStatus) {
      db.transaction((txn) => {
        let { StoreId, UploadStatus, tbname, InTime, outtime } = data;

        // Ensure default values if InTime or OutTime is missing
        InTime = InTime ? InTime : null;
        outtime = outtime ? outtime : null;

        console.log("checkloc--", data, InTime, outtime);

        let query, params;

        if (InTime !== null && outtime !== null) {
          query = `UPDATE ${tbname} 
                         SET UploadStatus = ?, InTime = ?, OutTime = ? 
                         WHERE StoreId = ? AND VisitDate = ?`;
          params = [UploadStatus, InTime, outtime, StoreId, today];
        } else {
          query = `UPDATE ${tbname} 
                         SET UploadStatus = ? 
                         WHERE StoreId = ? `;
          if (!previousDayUpload) {
            query += ` AND VisitDate = ? `;
          }

          console.log("query", query, previousDayUpload);
          params = !previousDayUpload ? [UploadStatus, StoreId, today] : [UploadStatus, StoreId];
        }

        txn.executeSql(
          query,
          params,
          (txn2, txnres2) => {
            console.log('✅ Store status updated:', UploadStatus);
            callback != null ? callback(txnres2) : '';
            resolve(true);
          },
          (txnerr) => {
            console.error("🚨 SQL Error:", txnerr);
            resolve(false);
          }
        );
      });
    } else {
      resolve(false);
    }
  }).catch((err) => {
    console.error("🚨 Promise Error:", err);
    return false;
  });


  // return new Promise((resolve,reject)=>{

  //   if (data!=null && data.UploadStatus!=null && data.UploadStatus!='') {  
  //     db.transaction(async function (txn) {    

  //           let {StoreId,UploadStatus,tbname} = data; 

  //           let q=`UPDATE ${tbname} SET UploadStatus='${UploadStatus}' WHERE StoreId='${StoreId}'  `;
  //           if(!previousDayUpload){
  //             q+=` and VisitDate='${today}' `;
  //           }


  //           await txn.executeSql(q,[],async function (txn2, txnres2) { 
  //               console.log('store status updated',UploadStatus,typeof callback);
  //               callback!=null?callback(txnres2):'';
  //               resolve(true);
  //           },function(Etxn,txnerr){console.log(txnerr);resolve(false);}); 

  //     });
  //   }
  //   else{
  //     resolve(false);
  //   }
  // }).then((val)=>{
  //   return val;
  // }).catch((err)=>{
  //   console.log(err);
  //   return false;
  // });


}

export async function uploadContractData(props, contractData, programdata) {
  const url = props.baseurl + getMethodName(METHODS.UPLOADJSON_METHOD);

  let postData = {
    "MID": 0,
    "Keys": "ContractForm",
    "JsonData": JSON.stringify(contractData),
    "UserId": props.UserId,
  };


  console.log("url:", url);
  console.log("postData:", postData);

  return await UploadData2(url, postData)
    .then(async (res) => {
      console.log('res:', res);
      if (res.UploadJsonResult != null && res.UploadJsonResult == 'Success') {
        let isUpdated = updateCFStatus(programdata)
        return isUpdated;
      } else {
        return false;
      }
    })
    .catch((err) => {
      console.log(err);
      return false;
    });
}

export async function updateCFStatus(data) {
  let { ProgramDefinitionId, ProgramId } = data;
  return new Promise((resolve, reject) => {
    db.transaction(async function (txn) {
      let q = `Update Mapping_ContractForm SET ContractFormStatus='1' WHERE ProgramId='${ProgramId}' and ProgramDefinitionId='${ProgramDefinitionId}'`;
      await txn.executeSql(q, [], async function (txn2, txnres) {
        console.log('CF status Updated to 1');
        resolve(true);
      }, function (txnE, txnerr) { console.log(txnerr); resolve(false); },);

    });
  }).then((val) => {
    return val;
  }).catch((err) => {
    console.log(err);
    return false;
  });
}



export async function UploadAddStoreInfoData(props, addstoreinfoData) {
  const url = props.baseurl + getMethodName(METHODS.UPLOADJSON_METHOD);

  let postData = {
    "MID": 0,
    "Keys": "Add_Store_Info",
    "JsonData": JSON.stringify(addstoreinfoData),
    "UserId": props.UserId,
  };


  console.log("url:", url);
  console.log("postData:", postData);

  return await UploadData2(url, postData)
    .then(async (res) => {
      console.log('res:', res);
      if (res.UploadJsonResult != null && res.UploadJsonResult == 'Success') {
        let isUpdated = updateAddInfoStoreStatus()
        return isUpdated;
      } else {
        return false;
      }
    })
    .catch((err) => {
      console.log(err);
      return false;
    });
}

export async function updateAddInfoStoreStatus() {
  return new Promise((resolve, reject) => {
    db.transaction(async function (txn) {
      let q = `Update ${AppTables.ADD_STORE_INFO} SET STATUS='U' `;

      await txn.executeSql(q, [], async function (txn2, txnres) {
        console.log('Add Store Info status Updated to 1');
        resolve(true);
      }, function (txnE, txnerr) { console.log(txnerr); resolve(false); },);

    });
  }).then((val) => {
    return val;
  }).catch((err) => {
    console.log(err);
    return false;
  });
}


async function UploadImagesWithoutWait(postData, url) {
  console.log(url, postData);
  return await UploadFormData(url, postData)
    .then((res) => {
      console.log('test:', res);
      if (typeof res == 'object' && res.error != null) {
        return false;
      }
      else if (res.includes('Success')) {
        console.log('image uploaded');
        return true;
      }
      return false;
    })
    .catch((err) => {
      console.log(err);
      return false;
    });
}

export async function uploadContractFormFiles(allfiles = [], UpdateUploadCountLocal = () => { }, props) {
  let d1 = new Date();
  let d2 = moment(d1).format('MM/DD/YYYY');
  let uploadCount = 0;
  const url = (props.imageUploadUrl || URL_IMAGE) + getMethodName(METHODS.UPLOADIMAGES_METHOD);
  // const url=( URL_IMAGE)+getMethodName(METHODS.UPLOADIMAGES_METHOD);

  var isAllUploaded = false;
  return await Promise.all(
    allfiles.map(async (file, i) => {
      let index = i;
      let actualfilepath = 'file://' + file.uri;
      let isExists = await RNFS.exists(actualfilepath).then((res) => { return res; });
      console.log('isExists file', isExists, file.uri);
      let isImageUploaded = false;
      if (isExists) {

        let postData = new FormData();
        postData.append('file', {
          uri: actualfilepath,
          type: file.type,
          //type: mime.getType(actualfilepath),
          name: file.name,
        });

        postData.append('Foldername', file.folderName);
        postData.append('Path', d2);

        isImageUploaded = await UploadImagesWithoutWait(postData, url);
        if (isImageUploaded == true) {
          console.log('isExists file uploaded', isExists, uploadCount, index, allfiles.length - 1);
          await RNFS.unlink(actualfilepath);
          uploadCount++;
          UpdateUploadCountLocal(uploadCount + 1)
          if (uploadCount == allfiles.length) {
            isAllUploaded = true;
          }

        } else {
          console.log('file not uploaded:', isExists, actualfilepath);
        }

      }
      else {//file does not exists 
        uploadCount++;
        UpdateUploadCountLocal(uploadCount + 1)
        if (uploadCount == allfiles.length) {
          isAllUploaded = true;
        }
      }

      return isImageUploaded;
    })
  ).then((val) => {
    console.log(val);
    return isAllUploaded;
  })
    .catch((err) => {
      console.log(err);
      return false;
    })
}


export async function UpdateDistributorStatus(props, data, callback = () => { }) {
  let d1 = new Date();
  let today = moment(d1).format('MM/DD/YYYY');

  return new Promise((resolve, reject) => {

    if (data != null && data.UploadStatus != null && data.UploadStatus != '') {
      db.transaction(async function (txn) {

        let { StoreId, UploadStatus, tbname } = data;

        let q = `UPDATE ${tbname} SET UploadStatus='${UploadStatus}' WHERE DistributorId='${StoreId}' `;

        await txn.executeSql(q, [], async function (txn2, txnres2) {
          console.log('distributor status updated', UploadStatus,);
          callback(txnres2);
          resolve(true);
        }, function (Etxn, txnerr) { console.log(txnerr); resolve(false); });

      });
    }
    else {
      resolve(false);
    }
  }).then((val) => {
    return val;
  }).catch((err) => {
    console.log(err);
    return false;
  });


}

export async function getKPIS(MenuList, props) {
  // let allKpis=MenuList;
  // let isMDSIndex=MenuList.findIndex(i=>i.ScreenName=='MDSTOCK');
  // isMDSIndex>=0? allKpis.splice(isMDSIndex,1) : "";
  // let isCLSIndex=MenuList.findIndex(i=>i.ScreenName=='CLSSTOCK');
  // isCLSIndex>=0? allKpis.splice(isCLSIndex,1) : "";
  // console.log("isMDSIndex:",isMDSIndex,isCLSIndex);

  let allKpis = []
  for (let i = 0; i < MenuList.length; i++) {
    let obj = MenuList[i];
    let isValid = obj.ScreenName != 'MDSTOCK' && obj.ScreenName != 'CLSSTOCK';
    if (isValid) {
      allKpis.push(obj);
    }
    if (i == MenuList.length - 1) {
      if (props.ShowStoreChecklist == true) {
        allKpis.push({ "MenuId": 0, "MenuName": "StoreChecklist", "ScreenName": 'StoreChecklist' });
      }
      if (props.ShowStoreProfile == true) {
        allKpis.push({ "MenuId": 0, "MenuName": "StoreProfile", "ScreenName": 'StoreProfile' });
      }
      if (props.ShowReportAfterCheckIn == true) {
        allKpis.push({ "MenuId": 0, "MenuName": "StoreReport", "ScreenName": 'StoreReport' });
      }

      if (props.ShowCompactStoreProfile == true) {
        allKpis.push({ "MenuId": 0, "MenuName": "StoreProfileKyc", "ScreenName": 'StoreProfileKyc' });
      }

      console.log("allKpis:", allKpis);
      return allKpis;
    }
  }




  // return Promise.all(
  //   MenuList.map((item,index)=>{
  //     let ScreenName=item.ScreenName || '';
  //     switch(ScreenName){
  //         case 'STOCK':allKpis.push('Stocks2'); return 'Stocks2';
  //         case 'STOCKWITHCATEGORY':allKpis.push('StockWithCat'); return 'StockWithCat';
  //         case 'OPSTOCK':allKpis.push('Stocks'); return 'Stocks';
  //         case 'BACKSTOCK':allKpis.push('BRS'); return 'BRS';
  //         case 'MDSTOCK':allKpis.indexOf('Stocks')<0?allKpis.push('Stocks'):''; return 'Stocks';
  //         case 'CLSSTOCK':allKpis.indexOf('Stocks')<0?allKpis.push('Stocks'):''; return 'Stocks';
  //         case 'SOS':allKpis.push('SOS'); return 'SOS';
  //         case 'PAIDVISI':allKpis.push('PaidVis'); return 'PaidVis';
  //         case 'ADDITIONALVISI':allKpis.push('AddVis'); return 'AddVis';
  //         case 'COMPVISI':allKpis.push('CompVis'); return 'CompVis';
  //         case 'PROMOTION':allKpis.push('Promotion'); return 'Promotion';
  //         case 'COMPROMO':allKpis.push('CompPromo'); return 'CompPromo';
  //         case 'CONCOV':allKpis.push('Contacts'); return 'Contacts';
  //         case 'SALE':allKpis.push('Sale'); return 'Sale';
  //         case 'ORDER':allKpis.push('Order'); return 'Order';
  //         case 'SURVEY':allKpis.push('Survey'); return 'Survey';
  //         case 'WINDOW':allKpis.push('Window'); return 'Window';
  //         case 'POSM':allKpis.push('POSM'); return 'POSM';
  //         case 'PROMOTION2':allKpis.push('Promotion2'); return 'Promotion2';
  //         case 'STOREIMG':allKpis.push('StoreImages'); return 'StoreImages';
  //         case 'SHELFTALKER':allKpis.push('ShelfTalker'); return 'ShelfTalker';
  //         case 'PROMOTIONONEAPP':allKpis.push('PromotionOneApp'); return 'PromotionOneApp';
  //         case 'PAIDVISIONEAPP':allKpis.push('PaidVisOneApp'); return 'PaidVisOneApp';
  //         case 'SOSONEAPP':allKpis.push('SOSOneApp'); return 'SOSOneApp';
  //         case 'CATEXEONEAPP':allKpis.push('CatExeOneApp'); return 'CatExeOneApp';
  //         case 'ORDERSTATUS':allKpis.push('ORDERSTATUS'); return 'ORDERSTATUS';



  //         default: return '';
  //     }
  //   })
  // ).then((val)=>{
  //   if(props.ShowStoreChecklist==true){
  //     allKpis.push('StoreChecklist');
  //   }
  //   if(props.ShowStoreProfile==true){
  //     allKpis.push('StoreProfile');
  //   }
  //   return allKpis;
  // })
}







export const marktext1 = async (text = '', imgurl = '', imgWidth, imgHeight) => {
  if (!imgurl || !text) return { success: false, imagenotfound: true };

  try {
    // top-left coordinates
    const position = { x: 20, y: 20 };

    const result = await manipulateAsync(
      imgurl,
      [
        {
          drawText: {
            text: text,
            position: position,
            color: '#ff0000',
            fontSize: 24,
          },
        },
      ],
      { format: SaveFormat.JPEG, compress: 1 } // 1 = 100% quality
    );

    // Resize if width/height given
    if (imgWidth && imgHeight) {
      const resized = await ImageResizer.createResizedImage(result, imgWidth, imgHeight, 'JPEG', 35, 0, null, false, { onlyScaleDown: true });
      return { success: true, uri: Platform.OS === 'android' ? 'file://' + resized.uri : resized.uri };
    }

    return { success: true, uri: Platform.OS === 'android' ? 'file://' + result : result };
  } catch (err) {
    console.log('marktext1 err:', err);
    return { success: false, error: err };
  }
};

export const markAlltexts = async (text1 = '', text2 = '', imgurl = '', imgWidth, imgHeight) => {
  if (!imgurl || !text1) return { success: false, imagenotfound: true };

  try {
    const operations = [];

    // Top-left text
    operations.push({
      drawText: { text: text1, position: { x: 20, y: 20 }, color: '#ff0000', fontSize: 24 },
    });

    // Bottom-left text
    if (text2) {
      operations.push({
        drawText: { text: text2, position: { x: 20, y: imgHeight - 40 }, color: '#ff0000', fontSize: 16 },
      });
    }

    const result = await manipulateAsync(imgurl, operations, { format: SaveFormat.JPEG, compress: 1 });

    // Resize if needed
    if (imgWidth && imgHeight) {
      const resized = await ImageResizer.createResizedImage(result, imgWidth, imgHeight, 'JPEG', 35, 0, null, false, { onlyScaleDown: true });
      return { success: true, uri: Platform.OS === 'android' ? 'file://' + resized.uri : resized.uri };
    }

    return { success: true, uri: Platform.OS === 'android' ? 'file://' + result : result };
  } catch (err) {
    console.log('markAlltexts err:', err);
    return { success: false, error: err };
  }
};





export const marktext2 = async (text = '', imgurl = '', imgWidth, imgHeight) => {
  if (!imgurl || !text) return { success: false, imagenotfound: true };

  try {
    const position = { x: 20, y: imgHeight - 40 }; // bottom-left
    const result = await manipulateAsync(imgurl, [{ drawText: { text, position, color: '#ff0000', fontSize: 16 } }], { format: SaveFormat.JPEG, compress: 1 });

    if (imgWidth && imgHeight) {
      const resized = await ImageResizer.createResizedImage(result, imgWidth, imgHeight, 'JPEG', 35, 0, null, false, { onlyScaleDown: true });
      return { success: true, uri: Platform.OS === 'android' ? 'file://' + resized.uri : resized.uri };
    }

    return { success: true, uri: Platform.OS === 'android' ? 'file://' + result : result };
  } catch (err) {
    console.log('marktext2 err:', err);
    return { success: false, error: err };
  }
};

export async function Add_metadataToImage(imgdata, TopText, BottomText, imgurl = '') {
  return new Promise(async (resolve, reject) => {
    console.log("start Add_metadataToImage RN: ", moment().format("MM/DD/YYYY HH:mm:ss"));
    if (ImageMarkText != null && imgurl != '') {
      let TextInfo = {
        "text": TopText, "BottomText": BottomText,
        "textStyle": {
          "TopTextfontSize": parseInt(imgdata.width * 0.06), "TopText_x": parseInt(imgdata.width * 0.01), "TopText_y": parseInt((imgdata.width * 0.06) + 50),
          "BottomTextfontSize": parseInt(imgdata.width * 0.03), "BottomText_x": parseInt(imgdata.width * 0.01), "BottomText_y": parseInt(imgdata.height + (imgdata.width * 0.03) + 10)
        }
      };
      let ImgInfo = { src: imgurl, height: imgdata.height, width: imgdata.width, ExtendedHeight: imgdata.ExtendedHeight };
      let url = await ImageMarkText.NativeImageMarkText(JSON.stringify(TextInfo), JSON.stringify(ImgInfo));

      console.log("end Add_metadataToImage RN: ", moment().format("MM/DD/YYYY HH:mm:ss"), url);
      if (url != null && typeof url == 'string') {
        // let fileparts= url.split("/");
        // let filename=fileparts[fileparts.length-1];
        // let destPath1=RNFS.DownloadDirectoryPath+"/"+filename;
        // RNFS.copyFile(url,destPath1);
        resolve({ success: true, "url": url });
      }
      else {
        resolve({ success: false, "error": "Cannot add metdata!" });
      }
    }
    else {
      console.log("end Add_metadataToImage RN: ", moment().format("MM/DD/YYYY HH:mm:ss"));
      resolve({ success: false, "error": "Native Module 'ImageMarkText' not found!" });
    }
  }).then((res) => {
    return res;
  }).catch((err) => {
    console.log("err:", err);
    return { success: false, error: err };
  })


}

//arman
export async function restore_ImageWithMetaDataGst(data, imgdata) {
  let { destFilePath, imgurl, imgWidth, imgHeight, mark_text1, mark_text2 } = data
  // do not append metadata for ios
  if (Platform.OS == 'ios') {
    // let fileparts= destFilePath.split("/");
    // let filename='RES_'+fileparts[fileparts.length-1];
    // let destPath1=RNFS.DownloadDirectoryPath+"/"+filename;
    // console.log('copy image from: ',destFilePath,', to:',destPath1);
    // RNFS.copyFile(destFilePath,destPath1);
    return true;
  }
  // add metadata
  // let res_metadata=await Add_metadataToImage(imgdata,mark_text1,mark_text2);
  // if(res_metadata.success && res_metadata.url!=null){
  // let imgWithMetaDataUrl=res_metadata.url;



  // cpoy to doownlload folder 

  // let fileparts= destFilePath.split("/");
  // let filename='ORG_'+fileparts[fileparts.length-1];
  // let destPath2=RNFS.DownloadDirectoryPath+"/"+filename;
  // console.log('copy org image from: ',imgurl,', to:',destPath2);
  // RNFS.copyFile(imgurl,destPath2);

  // resize file 
  let resize_res = await resizeImageGst(imgurl, imgWidth, imgHeight);
  if (resize_res.success) {
    // add metadata
    let resized_url = resize_res.uri != null && resize_res.uri != '' ? resize_res.uri.replace('file://', '') : '';
    let resized_imgD = resize_res.imgData != null ? resize_res.imgData : {};
    console.log("resized_url:", resized_url)
    // required larger height of image for landscape image 
    let ExtraSpace = 1.1; // portrait image  default 
    if (resized_imgD.width > resized_imgD.height) {
      // landscape image 
      ExtraSpace = 1.2
    }
    let resized_imgData = { uri: resized_url, width: parseInt(resized_imgD.width), height: parseInt(resized_imgD.height), ExtendedHeight: parseInt(resized_imgD.height * ExtraSpace) };

    let res_metadata = await Add_metadataToImageGst(resized_imgData, mark_text1, mark_text2, resized_url);
    if (res_metadata.success && res_metadata.url != null) {
      let imgWithMetaDataUrl = res_metadata.url;

      let reducePixels_res = await reducePixelsGst(imgWithMetaDataUrl, imgWidth, imgHeight);
      if (reducePixels_res.success) {
        await RNFS.unlink(imgurl); // delete local temp image created while we click an image
        await RNFS.unlink(resized_url); // delete local temp image created by first resize image function
        await RNFS.unlink(imgWithMetaDataUrl); // delete local temp image created by Add_metadataToImage function
        let isExists = await RNFS.exists(destFilePath); //delete dest file if exists
        if (isExists) { await RNFS.unlink(destFilePath); }
        console.log(reducePixels_res.uri, destFilePath, 'console....')
        return await RNFS.moveFile(reducePixels_res.uri, destFilePath).then((res) => {
          console.log('file restored to : ', destFilePath);
          // copy image in download folder
          // let fileparts= destFilePath.split("/");
          // let filename='RES_'+fileparts[fileparts.length-1];
          // let destPath1=RNFS.DownloadDirectoryPath+"/"+filename;
          // console.log('copy image from: ',destFilePath,', to:',destPath1);
          // RNFS.copyFile(destFilePath,destPath1);

          return true;
        }).catch((err) => {
          console.log("err:", err);
          return false;
        });
      }
      else {
        notify("Error while reducing pixels! " + (resize_res.error ? resize_res.error : ''));
        return false;
      }
    }
    else {
      notify("Error while adding metadata in image!" + (res_metadata.error ? res_metadata.error : ''));

      return true;
    }
  }
  else {
    notify("Error while resizing image! " + (resize_res.error ? resize_res.error : ''));
    return false;
  }

}

export const resizeImageGst = async (imgurl = '', imgWidth, imgHeight) => {
  if (imgurl != '') {
    const minDimension = 1500; // Minimum width/height to ensure text readability
    const targetWidth = Math.max(imgWidth, minDimension);
    const targetHeight = Math.max(imgHeight, minDimension);
    return await ImageResizer.createResizedImage(imgurl, targetWidth, targetHeight, 'JPEG', 90, 0, null, false, { onlyScaleDown: true })
      .then(response => {
        let size = bytesToSize(response.size);
        console.log('resizeImage: reduced filesize:', size);
        return { success: true, uri: response.uri, imgData: response };
      })
      .catch((err) => {
        console.log(err);
        return { success: false, error: err };
      });
  }
  else {
    return { success: false, imagenotfound: true };
  }
}

export const reducePixelsGst = async (imgurl = '', imgWidth, imgHeight) => {

  if (imgurl != '') {
    // perform resize only whether imgWidth>1100 or imgHeight>1100
    if (imgWidth > 2000 || imgHeight > 2000) {
      // set max width and max height to 1100
      return await ImageResizer.createResizedImage(imgurl, 2000, 2000, 'JPEG', 80, 0, null, false, { onlyScaleDown: true, mode: 'contain' })
        .then(response => {
          let size = bytesToSize(response.size);
          console.log('after pixel reduce file size , w, h:', size, response.width, response.height);
          return { success: true, uri: response.uri };
        })
        .catch((err) => {
          console.log(err);
          return { success: false, error: err };
        });

    }
    else {
      return { success: true, uri: imgurl };
    }

  }
  else {
    return { success: false, imagenotfound: true };
  }
}

export async function Add_metadataToImageGst(imgdata, TopText, BottomText, imgurl = '') {
  return new Promise(async (resolve, reject) => {
    console.log("start Add_metadataToImage RN: ", moment().format("MM/DD/YYYY HH:mm:ss"));
    if (ImageMarkText != null && imgurl != '') {
      let TextInfo = {
        "text": TopText, "BottomText": BottomText,
        "textStyle": {
          "TopTextfontSize": parseInt(imgdata.width * 0.06), "TopText_x": parseInt(imgdata.width * 0.01), "TopText_y": parseInt((imgdata.width * 0.06) + 50),
          "BottomTextfontSize": parseInt(imgdata.width * 0.03), "BottomText_x": parseInt(imgdata.width * 0.01), "BottomText_y": parseInt(imgdata.height + (imgdata.width * 0.03) + 30)
        }
      };
      let ImgInfo = { src: imgurl, height: imgdata.height, width: imgdata.width, ExtendedHeight: imgdata.ExtendedHeight };
      let url = await ImageMarkText.NativeImageMarkText(JSON.stringify(TextInfo), JSON.stringify(ImgInfo));

      console.log("end Add_metadataToImage RN: ", moment().format("MM/DD/YYYY HH:mm:ss"), url);
      if (url != null && typeof url == 'string') {
        // let fileparts= url.split("/");
        // let filename=fileparts[fileparts.length-1];
        // let destPath1=RNFS.DownloadDirectoryPath+"/"+filename;
        // RNFS.copyFile(url,destPath1);
        resolve({ success: true, "url": url });
      }
      else {
        resolve({ success: false, "error": "Cannot add metdata!" });
      }
    }
    else {
      console.log("end Add_metadataToImage RN: ", moment().format("MM/DD/YYYY HH:mm:ss"));
      resolve({ success: false, "error": "Native Module 'ImageMarkText' not found!" });
    }
  }).then((res) => {
    return res;
  }).catch((err) => {
    console.log("err:", err);
    return { success: false, error: err };
  })


}

export async function restore_ImageWithMetaData(data, imgdata) {
  let { destFilePath, imgurl, imgWidth, imgHeight, mark_text1, mark_text2 } = data
  // do not append metadata for ios
  if (Platform.OS == 'ios') {
    // let fileparts= destFilePath.split("/");
    // let filename='RES_'+fileparts[fileparts.length-1];
    // let destPath1=RNFS.DownloadDirectoryPath+"/"+filename;
    // console.log('copy image from: ',destFilePath,', to:',destPath1);
    // RNFS.copyFile(destFilePath,destPath1);
    return true;
  }
  // add metadata
  // let res_metadata=await Add_metadataToImage(imgdata,mark_text1,mark_text2);
  // if(res_metadata.success && res_metadata.url!=null){
  // let imgWithMetaDataUrl=res_metadata.url;



  // cpoy to doownlload folder 

  // let fileparts= destFilePath.split("/");
  // let filename='ORG_'+fileparts[fileparts.length-1];
  // let destPath2=RNFS.DownloadDirectoryPath+"/"+filename;
  // console.log('copy org image from: ',imgurl,', to:',destPath2);
  // RNFS.copyFile(imgurl,destPath2);

  // resize file 
  let resize_res = await resizeImage(imgurl, imgWidth, imgHeight);
  if (resize_res.success) {
    // add metadata
    let resized_url = resize_res.uri != null && resize_res.uri != '' ? resize_res.uri.replace('file://', '') : '';
    let resized_imgD = resize_res.imgData != null ? resize_res.imgData : {};
    console.log("resized_url:", resized_url)
    // required larger height of image for landscape image 
    let ExtraSpace = 1.1; // portrait image  default 
    if (resized_imgD.width > resized_imgD.height) {
      // landscape image 
      ExtraSpace = 1.2
    }
    let resized_imgData = { uri: resized_url, width: parseInt(resized_imgD.width), height: parseInt(resized_imgD.height), ExtendedHeight: parseInt(resized_imgD.height * ExtraSpace) };

    let res_metadata = await Add_metadataToImage(resized_imgData, mark_text1, mark_text2, resized_url);
    if (res_metadata.success && res_metadata.url != null) {
      let imgWithMetaDataUrl = res_metadata.url;

      let reducePixels_res = await reducePixels(imgWithMetaDataUrl, imgWidth, imgHeight);
      if (reducePixels_res.success) {
        // await RNFS.unlink(imgurl); // delete local temp image created while we click an image
        // await RNFS.unlink(resized_url); // delete local temp image created by first resize image function
        // await RNFS.unlink(imgWithMetaDataUrl); // delete local temp image created by Add_metadataToImage function
        let isExists = await RNFS.exists(destFilePath); //delete dest file if exists
        if (isExists) { await RNFS.unlink(destFilePath); }
        console.log(reducePixels_res.uri, destFilePath, 'console....')
        return await RNFS.moveFile(reducePixels_res.uri, destFilePath).then(async (res) => {
          console.log('file restored to : ', destFilePath);
          await RNFS.unlink(imgurl); // delete local temp image created while we click an image
          await RNFS.unlink(resized_url); // delete local temp image created by first resize image function
          await RNFS.unlink(imgWithMetaDataUrl); // delete local temp image created by Add_metadataToImage function
          // copy image in download folder
          // let fileparts= destFilePath.split("/");
          // let filename='RES_'+fileparts[fileparts.length-1];
          // let destPath1=RNFS.DownloadDirectoryPath+"/"+filename;
          // console.log('copy image from: ',destFilePath,', to:',destPath1);
          // RNFS.copyFile(destFilePath,destPath1);

          return true;
        }).catch((err) => {
          console.log("err:", err);
          return false;
        });
      }
      else {
        notify("Error while reducing pixels! " + (resize_res.error ? resize_res.error : ''));
        return false;
      }
    }
    else {
      notify("Error while adding metadata in image!" + (res_metadata.error ? res_metadata.error : ''));

      return true;
    }
  }
  else {
    notify("Error while resizing image! " + (resize_res.error ? resize_res.error : ''));
    return false;
  }

}

export const resizeImage = async (imgurl = '', imgWidth, imgHeight) => {
  if (imgurl != '') {
    return await ImageResizer.createResizedImage(imgurl, imgWidth, imgHeight, 'JPEG', 90, 0, null, false, { onlyScaleDown: true })
      .then(response => {
        let size = bytesToSize(response.size);
        console.log('resizeImage: reduced filesize:', size);
        return { success: true, uri: response.uri, imgData: response };
      })
      .catch((err) => {
        console.log(err);
        return { success: false, error: err };
      });
  }
  else {
    return { success: false, imagenotfound: true };
  }
}

export const reducePixels = async (imgurl = '', imgWidth, imgHeight) => {

  if (imgurl != '') {
    // perform resize only whether imgWidth>1100 or imgHeight>1100
    if (imgWidth > 1100 || imgHeight > 1100) {
      // set max width and max height to 1100
      return await ImageResizer.createResizedImage(imgurl, 1100, 1100, 'JPEG', 40, 0, null, false, { onlyScaleDown: true, mode: 'contain' })
        .then(response => {
          let size = bytesToSize(response.size);
          console.log('after pixel reduce file size , w, h:', size, response.width, response.height);
          return { success: true, uri: response.uri };
        })
        .catch((err) => {
          console.log(err);
          return { success: false, error: err };
        });

    }
    else {
      return { success: true, uri: imgurl };
    }

  }
  else {
    return { success: false, imagenotfound: true };
  }
}

export async function RestoreProjectInProps(props) {
  // clear_item('firsttime');clear_item('islogin');clear_item('mpin');clear_item('loginToken');
  if (props.baseurl == '' || props.baseurl == null || props.baseurl == undefined) {
    let projectInfo = await get_item('projectInfo');
    let projectCode = await get_item('projectCode');
    let projectDetails = projectInfo != null ? JSON.parse(projectInfo) : {};
    let pdata = getProjectInfo(projectDetails)
    //set project info in global redux state
    props.set_project(pdata);
  }
}

export function getProjectInfo(projectDetails, projectCode, AppClearData) {
  // const myKeys={"DownloadKey":[{"KeyId":1,"DownloadKey":"Table_Structure","IsMandatory":true,"DevActive":true,"ProdActive":true,"DownloadSequence":1},{"KeyId":4,"DownloadKey":"Mapping_JourneyPlan","IsMandatory":false,"DevActive":true,"ProdActive":true,"DownloadSequence":3},{"KeyId":5,"DownloadKey":"Adhoc_JourneyPlan","IsMandatory":true,"DevActive":true,"ProdActive":true,"DownloadSequence":4},{"KeyId":6,"DownloadKey":"Product_Master","IsMandatory":true,"DevActive":true,"ProdActive":true,"DownloadSequence":5},{"KeyId":7,"DownloadKey":"Non_Working_Reason","IsMandatory":true,"DevActive":true,"ProdActive":true,"DownloadSequence":2}]};
  let imgurl = projectDetails.imageUploadURL != null ? projectDetails.imageUploadURL + '/' : '';
  const pdata = {
    pid: (projectCode || ''), pname: (projectDetails.projectName || ''), pcode: (projectDetails.ProjectCode || ''),
    alldata: projectDetails, baseurl: (projectDetails.baseURL || baseurl),

    companylogo: (projectDetails.login_logo_Url || ''),
    splashlogo: (projectDetails.splash_logo_Url || ''),
    drawerlogo: (projectDetails.menu_top_logo || ''),

    imageUploadUrl: imgurl,
    GeoFenceEnable: (projectDetails.GeoFenceEnable_checkin != null && projectDetails.GeoFenceEnable_checkin == 1),
    GeoFenceRadius: (projectDetails.GeoFenceRadius_checkin || 0),
    GFEnable_checkout: (projectDetails.GeoFenceEnable_checkout != null && projectDetails.GeoFenceEnable_checkout == 1),
    GFRadius_checkout: (projectDetails.GeoFenceRadius_checkout || 0),

    DBCI_GeoFenceEnable: (projectDetails.DBCI_GeoFenceEnable != null && projectDetails.DBCI_GeoFenceEnable == 1),
    DBCI_GeoFenceRadius: (projectDetails.DBCI_GeoFenceRadius || 0),
    DBCO_GeoFenceEnable: (projectDetails.DBCO_GeoFenceEnable != null && projectDetails.DBCO_GeoFenceEnable == 1),
    DBCO_GeoFenceRadius: (projectDetails.DBCO_GeoFenceRadius || 0),

    CheckOut_PhotoReq: projectDetails.PhotoRequired_Checkout != null ? projectDetails.PhotoRequired_Checkout : false,
    CameraGallery: projectDetails.CameraGallery != null ? projectDetails.CameraGallery : false,
    CheckInCameraGallery: projectDetails.CheckInCameraGallery != null ? projectDetails.CheckInCameraGallery : false,
    DownloadKey: projectDetails.DownloadKey != null ? projectDetails.DownloadKey : '',
    //DownloadKey:'', 
    OQAD_TimeOut: projectDetails.OQAD_TimeOut != null ? projectDetails.OQAD_TimeOut : OQAD_TimeConst,
    ShowMenuType: projectDetails.ShowMenuType != null ? projectDetails.ShowMenuType : true,
    ShowStoreChecklist: projectDetails.ShowStoreChecklist != null ? projectDetails.ShowStoreChecklist : false,
    RefImagePopUpTime: projectDetails.RefImagePopUpTime != null ? projectDetails.RefImagePopUpTime : 0,
    AdhocActivated: projectDetails.AdhocActivated != null ? projectDetails.AdhocActivated : "",
    ShowBeatPlanList: projectDetails.ShowBeatPlanList != null ? projectDetails.ShowBeatPlanList : false,
    ShowDBPOSM: projectDetails.ShowDBPOSM != null ? projectDetails.ShowDBPOSM : false,
    ShowStoreAdd: projectDetails.ShowStoreAdd != null ? projectDetails.ShowStoreAdd : false,
    ShowStoreProfile: projectDetails.ShowStoreProfile != null ? projectDetails.ShowStoreProfile : false,
    ShowReportAfterCheckIn: projectDetails.ShowReportAfterCheckIn != null ? projectDetails.ShowReportAfterCheckIn : false,
    ///armaan shaikh
    ShowCompactStoreProfile: projectDetails.ShowCompactStoreProfile != null ? projectDetails.ShowCompactStoreProfile : false,
    ShowSideMenuKYC: projectDetails.ShowSideMenuKYC != null ? projectDetails.ShowSideMenuKYC : false,

    ShowNonMerList: projectDetails.ShowNonMerList != null ? projectDetails.ShowNonMerList : false,
    Show_VisitorFeedBack: projectDetails.Show_VisitorFeedBack != null ? projectDetails.Show_VisitorFeedBack : false,
    Show_ConsumerSection: projectDetails.Show_ConsumerSection != null ? projectDetails.Show_ConsumerSection : false,
    Clear_storage: AppClearData != null ? AppClearData : false,

    ShowNonProgram: projectDetails.ShowNonProgram != null ? projectDetails.ShowNonProgram : false,
    FaceRecognition: projectDetails.FaceRecognition != null ? projectDetails.FaceRecognition : false,
    Gyancast: projectDetails.Gyancast != null ? projectDetails.Gyancast : false,
    Chatbot: projectDetails.Chatbot != null ? projectDetails.Chatbot : false,
    StoreMapView: projectDetails.StoreMapView != null ? projectDetails.StoreMapView : false,
    StoreRouteView: projectDetails.StoreRouteView != null ? projectDetails.StoreRouteView : false,
    NoCheckIn_Photo: projectDetails.NoCheckIn_Photo != null ? projectDetails.NoCheckIn_Photo : false,


    ShowStoreSearch: projectDetails.ShowStoreSearch != null ? projectDetails.ShowStoreSearch : false,
    ShowStoreSearchLabel: projectDetails.ShowStoreSearchLabel != null && projectDetails.ShowStoreSearchLabel != '' ? projectDetails.ShowStoreSearchLabel : StoreSearch_def,
    PartialSaveAllow: projectDetails.PartialSaveAllow != null ? projectDetails.PartialSaveAllow : false,
    CheckinOpenBackCamera: projectDetails.CheckinOpenBackCamera != null ? projectDetails.CheckinOpenBackCamera : false,
    CheckoutOpenBackCamera: projectDetails.CheckoutOpenBackCamera != null ? projectDetails.CheckoutOpenBackCamera : false,
    CheckInSwitchingCamera: projectDetails.CheckInSwitchingCamera != null ? projectDetails.CheckInSwitchingCamera : false,

    NonProgramLabel: projectDetails.NonProgramLabel != null && projectDetails.NonProgramLabel != '' ? projectDetails.NonProgramLabel : NonProgramLabel_def,
    IR_CameraEnableOnApp: projectDetails.IR_CameraEnableOnApp != null ? projectDetails.IR_CameraEnableOnApp : false,
    IR_Creds: projectDetails.IR_Creds != null ? projectDetails.IR_Creds : {},
    Chatbot_Creds: projectDetails.Chatbot_Creds != null ? projectDetails.Chatbot_Creds : {},
    ShowAddNewStore: projectDetails.ShowAddNewStore != null ? projectDetails.ShowAddNewStore : false,
    WebViewDashboard: projectDetails.WebViewDashboard != null ? projectDetails.WebViewDashboard : false,


    AddNewStoreInJCP: projectDetails.AddNewStoreInJCP != null ? projectDetails.AddNewStoreInJCP : false,
    AddNewStoreVerificationReq: projectDetails.AddNewStoreVerificationReq != null ? projectDetails.AddNewStoreVerificationReq : false,

    ShowContractForm: projectDetails.ShowContractForm != null ? projectDetails.ShowContractForm : false,
    WarehouseShow: projectDetails.WarehouseShow != null ? projectDetails.WarehouseShow : false,
    Show_OldMTDReports: projectDetails.Show_OldMTDReports == 1 || projectDetails.Show_OldMTDReports == "true" ? true : false,

    Allow_Change_Password: projectDetails.Allow_Change_Password != null ? projectDetails.Allow_Change_Password : false,
    forget_Password_on_LoginPage: projectDetails.forget_Password_on_LoginPage != null ? projectDetails.forget_Password_on_LoginPage : false,

  };

  return pdata;
}

export function get_rowColSettings(colVal, colName, row) {

  let res = { "color": '', "fontsize": "", "bold": 0 };
  let gset_obj = row["Color"] != null && row["Color"] != null != '' ? JSON.parse(row["Color"]) : {};
  if (Object.keys(gset_obj).length > 0 && colVal != null && colVal != '') {
    let settings_Obj = gset_obj;

    let color_obj = settings_Obj["colors"] != null && typeof settings_Obj["colors"] == 'object' ? settings_Obj["colors"] : {};
    let column_settings = color_obj[colName] != null && color_obj[colName] != '' ? color_obj[colName] : [];

    if (column_settings.length > 0) {
      for (let i = 0; i < column_settings.length; i++) {
        let colset_obj = column_settings[i];

        // if min and max both is present
        if (colset_obj["min"] != null && Math.round(colVal) >= colset_obj["min"] && colset_obj["max"] != null && Math.round(colVal) <= colset_obj["max"]) {

          res = { "color": colset_obj.color, "fontsize": colset_obj.fontsize, "bold": colset_obj.bold };
          return res;
        }
        // if only min is present
        else if (colset_obj["min"] != null && Math.round(colVal) >= colset_obj["min"] && (colset_obj["max"] == null || colset_obj["max"] == '')) {

          res = { "color": colset_obj.color, "fontsize": colset_obj.fontsize, "bold": colset_obj.bold };
          return res;
        }
        // if only max is present
        else if (colset_obj["max"] != null && Math.round(colVal) <= colset_obj["max"] && (colset_obj["min"] == null || colset_obj["min"] == '')) {

          res = { "color": colset_obj.color, "fontsize": colset_obj.fontsize, "bold": colset_obj.bold };
          return res;
        }

        if (i == column_settings.length - 1) {
          console.log("end")
          return res;
        }
      }
    }
    else {
      return res;
    }
  }
  else {
    return res
  }
}

export function checkRange(lat1, lon1, lat2, lon2) {
  var R = 6371; // km (change this constant to get miles)
  var dLat = (lat2 - lat1) * Math.PI / 180;
  var dLon = (lon2 - lon1) * Math.PI / 180;
  var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
    Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
    Math.sin(dLon / 2) * Math.sin(dLon / 2);
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  var d = R * c;
  return Math.round(d * 1000);
}


export function cal_distance(lat1, lon1, lat2, lon2) {
  var p = 0.017453292519943295;    // Math.PI / 180
  var c = Math.cos;
  var a = 0.5 - c((lat2 - lat1) * p) / 2 +
    c(lat1 * p) * c(lat2 * p) *
    (1 - c((lon2 - lon1) * p)) / 2;
  R = 6371;// km
  return Math.asin(Math.sqrt(a)) * 2 * R; //12742 miles
}

export function bytesToSize(bytes) {
  var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
  if (bytes == 0) return '0 Byte';
  var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
  return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i];
}

export async function getKPIFields(menu1, getAll = false) {
  return new Promise((resolve, reject) => {
    db.transaction(async function (txn) {
      let q = `select * from Mapping_MenuConfiguration `;
      if (!getAll) {
        q += `where ScreenName='${menu1.ScreenName}'`;
      }

      await txn.executeSql(q, [], async function (txn2, txnres) {
        if (txnres.rows.length > 0) {
          let arr = [];
          for (var i = 0; i < txnres.rows.length; i++) {
            let data = txnres.rows.item(i);
            let isenable = data.KPIFieldEnable == 'true' || data.KPIFieldEnable == 1 || data.KPIFieldEnable == '1' ? true : false;
            data['KPIFieldEnable'] = isenable;
            arr.push(data);
            if (i == txnres.rows.length - 1) {
              resolve(arr)
            }
          }
        }
        else {
          resolve([])
        }
      }, function (txnE, txnerr) { console.log(txnerr); resolve([]) },);
    });
  }).then((val) => {
    return val;
  }).catch((err) => {
    console.log(err);
    return [];
  });
}

//for storeCompactKyc
export async function getKPIFieldsForKyc(getAll = false) {
  return new Promise((resolve, reject) => {
    db.transaction(async function (txn) {
      let q = `select * from Mapping_MenuConfiguration `;

      txn.executeSql(q, [], async function (txn2, txnres) {
        if (txnres.rows.length > 0) {
          let arr = [];
          for (var i = 0; i < txnres.rows.length; i++) {
            let data = txnres.rows.item(i);
            let isenable = data.KPIFieldEnable == 'true' || data.KPIFieldEnable == 1 || data.KPIFieldEnable == '1' ? true : false;
            data['KPIFieldEnable'] = isenable;
            arr.push(data);
            if (i == txnres.rows.length - 1) {
              resolve(arr);
            }
          }
        }
        else {
          resolve([]);
        }
      }, function (txnE, txnerr) { console.log(txnerr); resolve([]); });
    });
  }).then((val) => {
    return val;
  }).catch((err) => {
    console.log(err);
    return [];
  });
}


export async function getIRPendingSessionCount(props) {
  console.log("getIRSessionStatus");
  return new Promise(async (resolve, reject) => {

    db.transaction(async function (txn) {
      function getJPQuery(PJPTableName) {
        let join = `Inner Join ${PJPTableName} JP on IR.STORE_ID=JP.StoreId `;
        let commonQ = ` 
        Select IR.STORE_ID,IR.TEMP_SESSION_ID FROM ${AppTables.SOS_IRUPLOAD} IR ${join}  where IR.SYNC_STATUS!='Synced'
        UNION
        Select IR.STORE_ID,IR.TEMP_SESSION_ID FROM ${AppTables.PAIDVIS_IRUPLOAD} IR ${join}  where IR.SYNC_STATUS!='Synced'
        UNION
        Select IR.STORE_ID,IR.TEMP_SESSION_ID FROM ${AppTables.WINDOW_IRUPLOAD} IR ${join}  where IR.SYNC_STATUS!='Synced'
        UNION
        Select IR.STORE_ID,IR.TEMP_SESSION_ID FROM ${AppTables.ADDVIS_IRUPLOAD} IR ${join}  where IR.SYNC_STATUS!='Synced'
        UNION
        Select IR.STORE_ID,IR.TEMP_SESSION_ID FROM ${AppTables.COMPVIS_IRUPLOAD} IR ${join}  where IR.SYNC_STATUS!='Synced'
        `;//IR.VISIT_DATE='${d2}' and 
        return commonQ;
      }

      let MappingJP = getJPQuery('Mapping_JourneyPlan');
      let AdhocJP = getJPQuery('Adhoc_JourneyPlan');
      let q = `${MappingJP}  UNION ${AdhocJP}`;

      if (props.ShowNonMerList == true) {
        let NonMerchJP = getJPQuery('NonMerchandising_JourneyPlan');
        q += ` UNION ${NonMerchJP} `;
      }
      if (props.ShowNonProgram == true) {
        let NonProgJP = getJPQuery('NonProgram_JourneyPlan');
        q += ` UNION ${NonProgJP} `;
      }
      if (props.ShowStoreSearch == true) {
        let SearchStoreJP = getJPQuery('StoreSearch_JourneyPlan');
        q += ` UNION ${SearchStoreJP} `;
      }
      if (props.ShowBeatPlanList == true) {
        let RouteJP = getJPQuery('JourneyPlan_RouteWise');
        q += ` UNION ${RouteJP} `;
      }

      await txn.executeSql(q, [], async function (txn2, txnres) {
        let count = txnres.rows.length;
        console.log("IR Pending count", count);
        resolve(count);
      }, function (txnE, txnerr) { console.log(txnerr); resolve(0); },);

    });
  }).catch((Err) => {
    console.log('getIRSessionStatus err', Err);
    return 0;
  })

}



export const useOrientation2 = (value) => {
  // const dim=window;
  let isPortrait = value == "LANDSCAPE-LEFT" || value == "LANDSCAPE-RIGHT";
  return isPortrait ? 'LANDSCAPE' : 'PORTRAIT';
}


export async function checkMDStockScreenExists(storeData1, screen = '') {
  return new Promise((resolve, reject) => {
    db.transaction(async function (txn) {
      let q = Q_MenuList(storeData1, screen);

      await txn.executeSql(q, [], async function (txn2, txnres) {
        if (txnres.rows.length > 0) {
          resolve(true);
        }
        else {
          resolve(false);
        }
      }, function (txnE, txnerr) { console.log(txnerr); resolve(true); },);
    });
  }).catch((err) => {
    console.log(err);
    return false;
  })
}

export function goToMenuPage({ props, storeData = {}, screenname = '', MenuItem = {}, BgNav = false, BgNavData = {}, isAdhocScreen, isBeatPlan, isNonMerchan, isNonProg, isStoreSearch, ShowCatWise = false, CatData = {}, ExtraData }) {
  props.set_autoback({ 'AutoGoToPrev': false });
  console.log("goToMenuPage", screenname, storeData, BgNav);
  props.navigation.navigate(screenname, { storeData: storeData, menu: MenuItem, 'isAdhoc': isAdhocScreen, 'isBeat': isBeatPlan, 'isNonMerchans': isNonMerchan, isNonProgs: isNonProg, isStoreSearch: isStoreSearch, 'redirect': BgNav, 'BgNavData': BgNavData, 'ShowCatWise': ShowCatWise, 'CatData': CatData, ExtraData: ExtraData })
}

export const useOrientation = (width, height) => {
  // const dim=window;
  let isPortrait = height >= width;
  return isPortrait ? 'PORTRAIT' : 'LANDSCAPE';
}


export function validateNumber(val, type = '', showMsg = true) {
  let isValid = true;
  if (type.toLowerCase() == 'numeric' && val != '') {
    let regex = new RegExp(/^\d+$/);
    let isNUmeric = regex.test(val);
    if (!isNUmeric) {
      isValid = false;
      if (showMsg) notify('Please enter whole numbers only', 'SHORT');
    }
  }
  else if (type.toLowerCase() == 'decimal' && val != '') {
    let regex = new RegExp(/^\d*\.?\d*$/);
    let isNUmeric = regex.test(val);
    if (!isNUmeric) {
      isValid = false;
      if (showMsg) notify('Please enter decimal numbers only', 'SHORT');
    }
  }
  else if (type.toLowerCase() == 'text' && val != '') {
    let regex = new RegExp(/^[a-zA-Z0-9@\s_.-]*$/);
    let isNUmeric = regex.test(val);
    if (!isNUmeric) {
      isValid = false;
      if (showMsg) notify('Please enter only characters and digits', 'SHORT');
    }

  } else if (type.toLowerCase() == 'qrtext' && val != '') {
    let regex = new RegExp(/^[a-zA-Z0-9@\s_.-\/:&$%#]*$/);
    let isNUmeric = regex.test(val);
    if (!isNUmeric) {
      isValid = false;
      if (showMsg) notify('Please enter only characters and digits', 'SHORT');
    }

  } else if (type.toLowerCase() == 'textspc' && val != '') {
    let regex = new RegExp(/^[a-zA-Z0-9\/-]*$/);
    let isNUmeric = regex.test(val);
    if (!isNUmeric) {
      isValid = false;
      if (showMsg) notify('Please enter only characters and digits', 'SHORT');
    }
  } else if (type.toLowerCase() == 'alphanumeric' && val != '') {
    let regex = new RegExp(/^[a-zA-Z0-9]+$/);
    let isNUmeric = regex.test(val);
    if (!isNUmeric) {
      isValid = false;
      if (showMsg) notify('Please enter only characters and digits', 'SHORT');
    }
  }

  return isValid;
}



export function validateNumber12(val, type = '', showMsg = true) {
  let isValid = true;

  if (type.toLowerCase() === 'numeric' && val !== '') {
    // Numeric validation logic
  } else if (type.toLowerCase() === 'decimal' && val !== '') {
    // Decimal validation logic
  } else if (type.toLowerCase() === 'text' && val !== '') {
    // RegExp(/^[a-zA-Z0-9@\s_.-]*$/);
    let regex = new RegExp(/^[a-zA-Z0-9\-\/ ,]*$/);
    let isNumeric = regex.test(val);
    if (!isNumeric) {
      isValid = false;
      if (showMsg) notify('Please enter only specified characters', 'SHORT');
    }
  } else if (type.toLowerCase() === 'qrtext' && val !== '') {
    let regex = new RegExp(/^[a-zA-Z0-9\-\/]*$/);
    let isNumeric = regex.test(val);
    if (!isNumeric) {
      isValid = false;
      if (showMsg) notify('Please enter only specified characters', 'SHORT');
    }
  } else if (type.toLowerCase() == 'textspc' && val != '') {
    let regex = new RegExp(/^[a-zA-Z0-9\/-]*$/);
    let isNUmeric = regex.test(val);
    if (!isNUmeric) {
      isValid = false;
      if (showMsg) notify('Please enter only characters and digits', 'SHORT');
    }
  } else if (type.toLowerCase() == 'alphanumeric' && val != '') {
    let regex = new RegExp(/^[a-zA-Z0-9]+$/);
    let isNUmeric = regex.test(val);
    if (!isNUmeric) {
      isValid = false;
      if (showMsg) notify('Please enter only characters and digits', 'SHORT');
    }
  }

  return isValid;
}




export function ValidateEmail(email) {
  let val = false;
  if (/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(email)) {
    val = true;
  }
  return val;
}

export const isDeviceTimeValid = async () => {
  let serverDateTimeString = ''
  try {
    const state = await NetInfo.fetch();
    const lastCallString = await AsyncStorage.getItem(LAST_ServerAPI_CALL);
    const lastCallTime = lastCallString ? parseInt(lastCallString, 10) : 0;
    const now = Date.now();
    if (now - lastCallTime < 5 * 60 * 1000) {
      console.log("Function call blocked to avoid frequent calls");
      return; // Don't call again within 5 minutes
    }
    await AsyncStorage.setItem(LAST_ServerAPI_CALL, now.toString());
    if (state.isConnected) {
      const serverDT = await getServerDT();
      const checkTime = serverDT?.CheckTime;
      if (typeof checkTime === 'string' && checkTime.trim() !== '') {
        serverDateTimeString = checkTime;
      } else {
        console.warn('CheckTime is missing or invalid.');
      }
    } else {
      return false;
    }

    if (serverDateTimeString == '' || !serverDateTimeString || typeof serverDateTimeString !== 'string') {
      console.warn("Invalid serverDateTimeString input", serverDateTimeString);
      await AsyncStorage.setItem(LAST_ServerAPI_CALL, lastCallString);
      return false;
    }

    // Parse server time
    const [datePart, timePart] = serverDateTimeString.split(" ");
    const [month, day, year] = datePart.split("/").map(Number);
    const [hours, minutes, seconds] = timePart.split(":").map(Number);
    const serverDate = new Date(year, month - 1, day, hours, minutes, seconds);
    const deviceDate = new Date();
    // Date check
    const isSameDate =
      serverDate.getDate() === deviceDate.getDate() &&
      serverDate.getMonth() === deviceDate.getMonth() &&
      serverDate.getFullYear() === deviceDate.getFullYear();
    // Time diff in minutes
    const diffMs = Math.abs(serverDate.getTime() - deviceDate.getTime());
    const diffMinutes = diffMs / (60 * 1000);
    // If date different and time difference > 15 mins
    console.log("server_datetime_with_localDateTime", isSameDate + "---", diffMinutes + "----" + serverDateTimeString + "\n" + serverDate + "\n" + deviceDate);
    if (!isSameDate || diffMinutes > 10) {
      await AsyncStorage.setItem(LAST_ServerAPI_CALL, lastCallString);
      Alert.alert(
        'Device Date/Time Mismatch',
        'To continue, please ensure your device’s date and time are correct or set to automatic.',
        [
          {
            text: 'Go to Settings',
            onPress: () => {
              // Open Date & Time settings
              if (Platform.OS === 'android') {
                SendIntentAndroid.openSettings('android.settings.DATE_SETTINGS')
              } else {
                Linking.openURL('App-Prefs:General&path=DATE_AND_TIME'); // iOS specific
              }
              // Close the app after short delay
              setTimeout(() => {
                RNExitApp.exitApp(); // Exits the app
              }, 1000);
            },
          },
        ],
        { cancelable: false }
      );

      return false;
    }
    return true;
  } catch (error) {
    console.error("Time validation error:", error);
    return false;
  }
};

export async function mergeStoreDistances(realStores, distances) {
  // Create a lookup object for fast access
  const distanceLookup = distances.reduce((acc, d) => {
    acc[d.StoreId] = {
      Distance: d.Distance,
      Duration: d.Duration,
      DistanceInMeters: d.DistanceInMeters
    };
    return acc;
  }, {}); // 👈 no type assertion in JS

  // Merge distance/duration into all stores (full merge)
  const mergedAll = realStores.map(store => {
    const match = distanceLookup[store.StoreId];
    return {
      ...store,
      Distance: match ? match.Distance : "0 meters",
      Duration: match ? match.Duration : "0 Minutes",
      DistanceInMeters: match ? match.DistanceInMeters : 0  // ✅ safe fallback
    };
  });

  return { mergedAll };
}

export async function getKPIFieldsWithSpecific() {
  return new Promise((resolve, reject) => {
    db.transaction(async function (txn) {
      let q = `select * from Mapping_MenuConfiguration where KPIFieldName in ('Color_MSL','Color_NONMSL','Color_Competition') `;

      await txn.executeSql(q, [], async function (txn2, txnres) {
        if (txnres.rows.length > 0) {
          let arr = [];
          for (var i = 0; i < txnres.rows.length; i++) {
            let data = txnres.rows.item(i);
            let isenable = data.KPIFieldEnable == 'true' || data.KPIFieldEnable == 1 || data.KPIFieldEnable == '1' ? true : false;
            data['KPIFieldEnable'] = isenable;
            arr.push(data);
            if (i == txnres.rows.length - 1) {
              resolve(arr)
            }
          }
        }
        else {
          resolve([])
        }
      }, function (txnE, txnerr) { console.log(txnerr); resolve([]) },);
    });
  }).then((val) => {
    return val;
  }).catch((err) => {
    console.log(err);
    return [];
  });
}


export function getValidStores(_storeData = []) {
  const filtered = _storeData.filter((store) => {
    const lat = parseFloat(store.Latitude);
    const lng = parseFloat(store.Longitude);
    return lat !== 0 && lng !== 0;
  });

  return filtered.length > 0 ? filtered : [];
}

const requestContactPermission = async () => {
  if (Platform.OS === 'android') {
    const result = await PermissionsAndroid.requestMultiple([
      PermissionsAndroid.PERMISSIONS.READ_CONTACTS,
      PermissionsAndroid.PERMISSIONS.WRITE_CONTACTS,
    ]);

    console.log('Contacts permissions:', result);

    return (
      result[PermissionsAndroid.PERMISSIONS.READ_CONTACTS] === PermissionsAndroid.RESULTS.GRANTED &&
      result[PermissionsAndroid.PERMISSIONS.WRITE_CONTACTS] === PermissionsAndroid.RESULTS.GRANTED
    );
  }
  return true;
};


export const openWebBrowser = async (url) => {
  console.log("webBUrl", url)
  const supported = await Linking.canOpenURL(url);
  if (supported) {
    await Linking.openURL(url);
  } else {
    console.warn("Can't open this URL:", url);
  }
}

export const createContact = async (rawData) => {
  const parsedData = parseRawData(rawData);
  console.log('parsedData', parsedData);
  if (!parsedData) return;
  console.log("rawData", rawData)
  const granted = await requestContactPermission();
  console.log("grante_a", granted)
  if (!granted) return;

  Contacts.addContact({
    givenName: parsedData?.Name || 'CPM Helpline',
    phoneNumbers: [{ label: parsedData?.Label || 'mobile', number: parsedData?.Value }],
  }).then(() => {
    notify('Contact saved successfully')
    Linking.openURL(`tel:${parsedData?.Value}`)
  }).catch(err => {
    console.log('Error saving contact', err);
  });
};

const parseRawData = (data) => {
  if (typeof data === 'string') {
    try {
      return JSON.parse(data);
    } catch (e) {
      console.log('Invalid JSON:', data);
      return null;
    }
  }
  return data;
};

export const requestLocationPermission = async () => {
  if (Platform.OS === "android") {
    const result = await PermissionsAndroid.requestMultiple([
      PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
      PermissionsAndroid.PERMISSIONS.ACCESS_COARSE_LOCATION,
    ]);

    return (
      result["android.permission.ACCESS_FINE_LOCATION"] ===
      PermissionsAndroid.RESULTS.GRANTED ||
      result["android.permission.ACCESS_COARSE_LOCATION"] ===
      PermissionsAndroid.RESULTS.GRANTED
    );
  }
  return true;
};

export const getLocationWithFallback = async () => {
  try {
    return await getCurrentLocation();
  } catch {
    return new Promise((resolve, reject) => {
      const watchId = Geolocation.watchPosition(
        pos => {
          Geolocation.clearWatch(watchId);
          resolve({
            latitude: pos.coords.latitude,
            longitude: pos.coords.longitude,
          });
        },
        reject,
        { enableHighAccuracy: false }
      );

      setTimeout(() => {
        Geolocation.clearWatch(watchId);
        reject(new Error("Location timeout"));
      }, 30000);
    });
  }
};




