//const Tank = require("../models/tanks");
const { Tank, MotorData, IotData,MotorIot,TankWaterLevel,TankConsumptionSchema,TankConsumptionOriginalSchema } = require('../models/tanks')

const {User} = require("../models/User");
const boom = require("boom");
const fastify = require("fastify")({
  logger: true,
});
// const tanksController = require("./tanksController")
const cron = require('node-cron');
const moment = require('moment');

const EventEmitter = require('events');
const eventEmitter = new EventEmitter();
async function deleteOldRecords() {
  const SEVEN_DAYS_IN_MILLISECONDS = 7 * 24 * 60 * 60 * 1000;
  const sevenDaysAgo = new Date(Date.now() - SEVEN_DAYS_IN_MILLISECONDS);

  await MotorData.deleteMany({ startTime: { $lt: sevenDaysAgo } });
}




// exports.addTanks = async (req, reply) => {
//   try {

//     var customerId = req.params.customerId
//     //const username = req.params.username;

// console.log(req.params);
//     //const  {username}  = loginObject.user.username;
//     //console.log(loginObject.user.username)
//     // const userInfo = await User.findOne({ username: username.toString() });
//     // const updateData = req.body;



//     // console.log("This is the reply in the handler after the validations", reply);
//     tankData = {
//       customerId: customerId,
//       hardwareId: req.body.hardwareId,
//       tankName: req.body.tankName,
//       blockName: req.body.blockName,
//       capacity: req.body.capacity,
//       typeOfWater: req.body.typeOfWater,
   
//       tankLocation:req.body.tankLocation.toLowerCase(),

//     };
//     //console.log( req.body.tankLocation.toLowerCase())
    
//     var tank_name = req.body.tankName
//     var tankLocation = req.body.tankLocation.toLowerCase()
//     var i_tank = await Tank.findOne({ tankName: tank_name,customerId:customerId,tankLocation:tankLocation})
//     if(i_tank){
//     throw new Error('tankname already exists');
//             }
//   else {

//     var tank = new Tank(tankData);

//     checkFormEncoding = isUserFormUrlEncoded(req);
//     if (checkFormEncoding.isUserFormUrlEncoded) {
//       usertobeInserted = checkFormEncoding.tank;
//       console.log("thsi true url string");
//       tank.customerId = usertobeInserted.customerId
//       tank.hardwareId = usertobeInserted.hardwareId;
//       tank.tankName = usertobeInserted.tankName;
//       tank.blockName = usertobeInserted.blockName;
//       tank.capacity = usertobeInserted.capacity;
//       tank.typeOfWater = usertobeInserted.typeOfWater;
    
//       tank.tankLocation = (usertobeInserted.tankLocation).toLowerCase();
//       console.log((usertobeInserted.tankLocation).toLowerCase())
//     }
//   }
//     const insertedTank = await tank.save();

//     return insertedTank;
  

//   } catch (err) {
//     throw boom.boomify(err);
//   }
// };


exports.addTanks = async (req, reply) => {
  try {

    const customerId = req.params.customerId;
    const { hardwareId, tankhardwareId,tankName,tankLocation,need_sensor,blockName } = req.body;
    

    const existingTank = await Tank.findOne({
      customerId: customerId,
      hardwareId: hardwareId,
      tankhardwareId: tankhardwareId,
      tankName:tankName,
      tankLocation:tankLocation.toLowerCase(),
      blockName:blockName
    });

    if (existingTank) {
      throw new Error('The combination of hardwareId and tankhardwareId already exists.');
    }
                                               
    const tankData = {
     // InstallerId:InstallerId,
      customerId: customerId,
      hardwareId: hardwareId,
      tankhardwareId: tankhardwareId,
      shape: req.body.shape,
      tankName: req.body.tankName,
      blockName: req.body.blockName,
      capacity: req.body.capacity,
      typeOfWater: req.body.typeOfWater,
      tankLocation: req.body.tankLocation.toLowerCase(),
      waterCapacityPerCm:req.body.waterCapacityPerCm,
      height:req.body.height,
      length:req.body.length,
      width:req.body.width,
      need_sensor:req.body.need_sensor

      // ... other fields
    };

    const tank = new Tank(tankData);
    const insertedTank = await tank.save();

    return insertedTank;
  } catch (err) {
    throw boom.boomify(err);
  }
};


//update selected tank
exports.updateTanksInfo = async (req, reply) => {

  try {
    const customerId = req.params.customerId;
   
    const tankName = req.query.tankName;
    const tank = req.body;
    const { ...updateData } = tank;
    console.log(tank)
    const update = await Tank.findOneAndUpdate({customerId:customerId,tankName: tankName,tankLocation:req.body.tankLocation }, updateData, { new: true });
    //console.log(update.username)
    //return update;

    reply.send({ status_code: 200, data: update });



  } 
  catch (err) {
    throw boom.boomify(err);
  }
};

//delete selected tank
exports.deleteTanksInfo = async (req, reply) => {
  try {
    const customerId = req.params.customerId;
   
    const tankName = req.query.tankName;
    const tankLocation = req.body.tankLocation.toLowerCase();
    const tank = await Tank.findOneAndDelete({ tankName: tankName,customerId:customerId,tankLocation:tankLocation });

    reply.send({ status_code: 200, data: tank});
   // return tank;
  } catch (err) {
    throw boom.boomify(err);
  }
};


exports.getConnectionsInfoOfParticularTank = async (req, reply) => {
  try {
    const customerId = req.params.customerId;
    const tankName = req.body.tankName;
    const tankLocation = req.body.tankLocation.toLowerCase();
    console.log(customerId, tankName, tankLocation);

    // Find the specific tank
    const mainTank = await Tank.findOne({
      tankName: tankName,
      customerId: customerId,
      tankLocation: tankLocation
    });

    if (!mainTank) {
      return reply.send({ status_code: 404, error: "Main tank not found" });
    }

    // Send the found tank within a list
    reply.send({ status_code: 200, data: [mainTank] });
  } catch (err) {
    throw boom.boomify(err);
  }
};




//get tanks data by passing username
exports.getTank = async (req, reply) => {
  try {
    await Tank.find({ customerId: req.query.customerId })
      .exec()
      .then((docs) => {
        let totalSwitchCount = 0;
        let totalSensorCount = 0;

        const transformedDocs = docs.map((tank) => {
          const inputConnections = tank.connections?.inputConnections || [];
          
          // Count switches
          const switchCount = inputConnections.reduce((count, connection) => {
            return count + (connection.inputismotor === true ? 1 : 0);
          }, 0);
          totalSwitchCount += switchCount;

          // Count sensors
          if (tank.need_sensor?.toLowerCase() === "yes") {
            totalSensorCount++;
          }

          // Determine all_motor_status
          const allMotorStatus = inputConnections.some(connection => connection.motor_status === "2");

          // Add switch_count and all_motor_status to the response
          return {
            ...tank.toObject(), // Convert Mongoose document to plain object
            connections: {
              ...tank.connections,
              switch_count: switchCount,
            },
            all_motor_status: allMotorStatus, // Add all_motor_status field
          };
        });

        reply.send({
          status_code: 200,
          data: transformedDocs,
          count: transformedDocs.length,
          total_switch_count: totalSwitchCount,
          total_sensor_count: totalSensorCount,
        });
      })
      .catch((err) => {
        console.error(err);
        reply.send({ status_code: 500, error: err.message });
      });
  } catch (err) {
    console.error(err);
    reply.send({ status_code: 500, error: "Internal Server Error" });
  }
};



exports.getTanksensorcount = async (req, reply) => {
  try {
    const { customerId } = req.params;

    // Find all tanks for the given customerId
    const tanks = await Tank.find({ customerId });

    if (!tanks || tanks.length === 0) {
      return reply.send({
        message: "No tanks found for the given customerId",
        data: [],
      });
    }

    // Process each tank
    const tankResults = tanks.map(tank => {
      const needSensorCount = {
        YES: tank.need_sensor === "YES" ? 1 : 0,
       
      };

      const inputConnections = tank.connections.inputConnections || [];
      const inputIsMotorCounts = inputConnections.reduce(
        (acc, connection) => {
          if (connection.inputismotor === true) acc.true += 1;
        
          return acc;
        },
        { true: 0 }
      );

      const totalInputConnections = inputConnections.length;

      return {
        tankName: tank.tankName,
        needSensorCount,
        inputIsMotorCounts,
        totalInputConnections,
        inputConnections,
      };
    });

    reply.send({
      customerId,
      tanks: tankResults,
    });
  } catch (error) {
    reply.status(500).send({ error: "An error occurred while fetching the data." });
  }
},




exports.getTanksofParticularInstaller = async (req, reply) => {
  try {
    await Tank.find({InstallerId: req.query.InstallerId})
      .exec()
      .then((docs) => {
        reply.send({ status_code: 200, data: docs, count: docs.length });
      })
      .catch((err) => {
        console.log(err);
        reply.send({ error: err });
      });
  } catch (err) {
    throw boom.boomify(err);
  }
};
//exports.getTanklevels = async (req, reply) => {
//  try {
 // const customerId = req.params.customerId;
//  const tankName = req.query.tankName;

//  setInterval(async function () {
 //   const randomNumber = Math.floor(Math.random() * (5500 - 1000) + 1000);
//    console.log(randomNumber)
//   console.log( await Tank.findOneAndUpdate({ customerId: customerId, tankName: tankName }, { $set: { waterlevel: randomNumber } }));
//  }, 2000);

//  return { message: 'Water level will be updated every 2 seconds' };
//}

 //  catch (err) {
 //   throw boom.boomify(err);
 // }
//};

exports.getTankmotordata = async (req, reply) => {
  try {
    await MotorData.find({customerId: req.query.customerId})
      .exec()
      .then((docs) => {
        reply.send({ status_code: 200, data: docs, count: docs.length });
      })
      .catch((err) => {
        console.log(err);
        reply.send({ error: err });
      });
  } catch (err) {
    throw boom.boomify(err);
  }
};


exports.updateTanklevels = async (req, reply) => {
  try {
    const customerId = req.params.customerId;
    const tanks = await Tank.find({ customerId,tankLocation:"overhead" });

    const intervals = {};

    for (const tank of tanks) {
      const tankId = tank._id;
      const tank_name = tank.tankName
      let capacity = parseInt(tank.capacity.replace(/,/g, ''), 10);
     //let waterLevel = parseInt(tank.waterlevel.replace(/,/g, ''), 10);

      const intervalId = setInterval(async function () {
        const tank_data = await Tank.findOne({ _id:tankId });
        const motorStatus = tank_data.motor_status
        let waterLevel = parseInt(tank_data.waterlevel.replace(/,/g, ''), 10);
      const newWaterLevel = Math.floor(waterLevel - 150);
      console.log("motorstatus:"+motorStatus)
        
        if (newWaterLevel <= 0 ) {
          clearInterval(intervals[tankId]);
          console.log(`Stopped updating tank with ID ${tankId}`);
          return;
        }
        else{
        const result = await Tank.findOneAndUpdate(
          { _id: tankId },
          { $set: { waterlevel: newWaterLevel } }
        );
        console.log(tank_name+"="+newWaterLevel)
      }

       // console.log(result);

        

       // waterLevel = newWaterLevel;
      }, 5000);

      intervals[tankId] = intervalId;
    }

    return { message: 'Water level updates started' };
  } catch (err) {
    throw boom.boomify(err);
  }
};



exports.getTanklevels = async (req, reply) => {
  try {
    const customerId = req.params.customerId;
    let sumSumpDrinkingWater = 0;
    let totalavailableDrinkingwater = 0;
    let totalDrinkingcapacity = 0;
    let totalavailableBorewater = 0;
    let totalBorewatercapacity = 0;

    let sumOverheadDrinkingWater = 0;
    let sumSumpBoreWater = 0;
    let sumOverheadBoreWater = 0;
    let sumSumpDrinkingWaterCapacity = 0;
    let sumOverheadDrinkingWaterCapacity = 0;
    let sumSumpBoreWaterCapacity = 0;
    let sumOverheadBoreWaterCapacity = 0;

    const updated_data = await Tank.find({ customerId: customerId });
    console.log("updated_data", updated_data);

    updated_data.forEach((tank) => {
      const waterlevel = parseInt(tank.waterlevel ? tank.waterlevel.replace(/,/g, '') : '0', 10);
      const capacity = parseInt(tank.capacity ? tank.capacity.replace(/,/g, '') : '0', 10);
      const waterlevelPercentage = ((waterlevel / capacity) * 100).toFixed(2);
      tank.waterlevelPercentage = waterlevelPercentage; // Add water level percentage to each tank object
      console.log(`Processing tank: ${tank.tankName}`);
      console.log(`Type of Water: ${tank.typeOfWater}, Location: ${tank.tankLocation}, Waterlevel: ${waterlevel}, Capacity: ${capacity}, Waterlevel Percentage: ${waterlevelPercentage}%`);

      let totalInputPercentage = 0;
      let inputCount = 0;
      let totalOutputPercentage = 0;
      let outputCount = 0;

      // Calculate and add water level percentages for inputConnections
      if (tank.connections.inputConnections) {
        tank.connections.inputConnections.forEach(inputConnection => {
          const inputWaterLevel = inputConnection.water_level ? parseInt(inputConnection.water_level.replace(/,/g, ''), 10) : 0;
          const inputCapacity = inputConnection.capacity ? parseInt(inputConnection.capacity.replace(/,/g, ''), 10) : 0;

          if (inputCapacity > 0) {
            inputConnection.waterlevelPercentage = ((inputWaterLevel / inputCapacity) * 100).toFixed(2);
            totalInputPercentage += parseFloat(inputConnection.waterlevelPercentage);
            inputCount++;
          } else {
            inputConnection.waterlevelPercentage = null;
          }
        });

        // Add the average input water level percentage to the tank's connections object
        tank.connections.inputWaterlevelPercentage = inputCount > 0 ? (totalInputPercentage / inputCount).toFixed(2) : null;
      }

      // Calculate and add water level percentages for outputConnections
      if (tank.connections.outputConnections) {
        tank.connections.outputConnections.forEach(outputConnection => {
          const outputWaterLevel = outputConnection.water_level ? parseInt(outputConnection.water_level.replace(/,/g, ''), 10) : 0;
          const outputCapacity = outputConnection.capacity ? parseInt(outputConnection.capacity.replace(/,/g, ''), 10) : 0;

          if (outputCapacity > 0) {
            outputConnection.waterlevelPercentage = ((outputWaterLevel / outputCapacity) * 100).toFixed(2);
            totalOutputPercentage += parseFloat(outputConnection.waterlevelPercentage);
            outputCount++;
          } else {
            outputConnection.waterlevelPercentage = null;
          }
        });

        // Add the average output water level percentage to the tank's connections object
        tank.connections.outputWaterlevelPercentage = outputCount > 0 ? (totalOutputPercentage / outputCount).toFixed(2) : null;
      }

      // Summing up the total water levels and capacities
      if (tank.tankLocation === 'sump' && tank.typeOfWater === 'drinking') {
        sumSumpDrinkingWater += waterlevel;
        sumSumpDrinkingWaterCapacity += capacity;
      } else if (tank.tankLocation === 'overhead' && tank.typeOfWater === 'drinking') {
        sumOverheadDrinkingWater += waterlevel;
        sumOverheadDrinkingWaterCapacity += capacity;
      } else if (tank.tankLocation === 'sump' && tank.typeOfWater === 'bore') {
        sumSumpBoreWater += waterlevel;
        sumSumpBoreWaterCapacity += capacity;
      } else if (tank.tankLocation === 'overhead' && tank.typeOfWater === 'bore') {
        sumOverheadBoreWater += waterlevel;
        sumOverheadBoreWaterCapacity += capacity;
      }
      else if ( tank.typeOfWater === 'drinking') {
        totalavailableDrinkingwater += waterlevel;
        totalDrinkingcapacity += capacity;
      }
     
      
      else if ( tank.typeOfWater === 'bore') {
        totalavailableBorewater += waterlevel;
        totalBorewatercapacity += capacity;
      }
    });

    const user = await User.findOne({ customerId: customerId });
    const buildingName = user ? user.buildingName : null;
    const address1 = user ? user.profile.address1 : null;

    const responseData = {
      status_code: 200,
      data: updated_data,
      totalDrinkingWaterInSump: sumSumpDrinkingWater,
      totalDrinkingWaterInOverhead: sumOverheadDrinkingWater,
      totalBoreWaterInSump: sumSumpBoreWater,
      totalBoreWaterInOverhead: sumOverheadBoreWater,
      totalDrinkingWaterInSumpCapacity: sumSumpDrinkingWaterCapacity,
      totalDrinkingWaterInOverheadCapacity: sumOverheadDrinkingWaterCapacity,
      totalBoreWaterInSumpCapacity: sumSumpBoreWaterCapacity,
      totalBoreWaterInOverheadCapacity: sumOverheadBoreWaterCapacity,
      buildingName: buildingName,
      address1: address1,
    };

    if (!reply.sent) {
      reply.send(responseData);
    }

  } catch (err) {
    if (!reply.sent) {
      reply.code(500).send({ error: 'Internal Server Error' });
    }
    throw boom.boomify(err);
  }
};



const intervals = {};
let sump_water_levels=[];
let supplier_tanks = [];

// exports.motorAction = async (req, reply) => {
//   try {
    
// 7
//     const customerId = req.params.customerId;
//     const action = req.body.action
//     const receiver_tank = req.body.to
//     const receiver_tank_info = await Tank.findOne({ customerId ,tankName:receiver_tank,tankLocation:(req.body.to_type).toLowerCase()});
//     const receiver_capacity =  parseInt((receiver_tank_info.capacity).replace(/,/g, ''), 10)
//     const desired_water_percentage =  parseInt((req.body.percentage).replace(/,/g, ''), 10)

    
//     const supplier_tank = req.body.from
//     const supplier_tank_type = (req.body.from_type).toLowerCase()
//     const receiver_type = (req.body.to_type).toLowerCase()
//    // console.log(supplier_tank)
//     //  const suplr_tank_info1 = await Tank.findOne({ customerId ,tankName:supplier_tank,tankLocation:supplier_tank_type});
//     const interval_variable = supplier_tank+receiver_tank
//     let currentTank = supplier_tanks.find(tank => tank.supplier_tank === supplier_tank);
//     let currentSump = sump_water_levels.find(tank => tank.supplier_tank === supplier_tank);

//     if(action === "start"){
      
//       if (!currentTank) {
//         currentTank = {
//           supplier_tank: supplier_tank,
//           start_time: new Date().toLocaleString('en-US', { timeZone: 'Asia/Kolkata' })
//         };
//         supplier_tanks.push(currentTank);
//       }
//      // start_time = new Date().toLocaleString('en-US', {timeZone: 'Asia/Kolkata'})
//       console.log(supplier_tanks)
//     // const stop_at = req.body.stop_at 
     
   

//      if(supplier_tank_type==="sump" && receiver_type === "overhead"){

//       await Tank.findOneAndUpdate({customerId, tankName: receiver_tank,tankLocation:receiver_type}, { $set: { motor_status: "1" } });

//        const supplier_tank_info1 = await Tank.findOne({ customerId ,tankName:supplier_tank,tankLocation:supplier_tank_type});
//        //console.log(supplier_tank_info1)
//         //const initial_update = parseInt(supplier_tank_info1.waterlevel.replace(/,/g, ''), 10)-200;
//        // await Tank.findOneAndUpdate({customerId, tankName: supplier_tank,tankLocation:supplier_tank_type}, { $set: { waterlevel: initial_update } });
//         const supplier_tank_info = await Tank.findOne({ customerId ,tankName:supplier_tank,tankLocation:supplier_tank_type});
//        const sump_water_level=  parseInt(supplier_tank_info.waterlevel.replace(/,/g, ''), 10)
//            const receiver_tank_info2 = await Tank.findOne({ customerId ,tankName:receiver_tank,tankLocation:(req.body.to_type).toLowerCase()});

//           const water_added_from_midnight =  parseInt((receiver_tank_info2.total_water_added_from_midnight).replace(/,/g, ''), 10)

//        if (!currentSump) {
//         currentSump = {
//           supplier_tank: supplier_tank,
//           supplier_initial_waterlevel:sump_water_level,
//           receiver_tank_total_water_added_from_midnight:water_added_from_midnight
  
          
//         };
//         sump_water_levels.push(currentSump);
//       }
        
//       console.log(sump_water_levels)
//         const overheadTank = await Tank.findOne({ customerId, tankName: receiver_tank, tankLocation: receiver_type });
//         const connection = overheadTank.connections.inputConnections.find((conn) => conn.inputConnections === supplier_tank);
        
//         if (connection) {
//           connection.motor_status = "1";
//           await overheadTank.save();
//         }

       

//        // await changingfrom_tankwaterlevel(customerId,initial_update,supplier_tank_info);
//       //  let supplier_waterlevel = parseInt(supplier_tank_info.waterlevel.replace(/,/g, ''), 10)
//        // console.log(supplier_waterlevel)
//        //  let receiver_waterlevel = parseInt(receiver_tank_info.waterlevel.replace(/,/g, ''), 10)
//          intervals[interval_variable] = setInterval(async function () {
//           // Calculate new water levels
//           const supplier_tank_info2 = await Tank.findOne({ customerId ,tankName:supplier_tank,tankLocation:supplier_tank_type});
//           const rcvr_info = await Tank.findOne({ customerId ,tankName:receiver_tank,tankLocation:receiver_type});
//           let receiver_waterlevel = parseInt(rcvr_info.waterlevel.replace(/,/g, ''), 10)

//           let supplier_waterlevel = parseInt(supplier_tank_info2.waterlevel.replace(/,/g, ''), 10)
//           const newWaterLevel = receiver_waterlevel  + 250//Math.floor(supplier_waterlevel  * 0.1);
//           const newSupplierWaterLevel = supplier_waterlevel-250//Math.floor(supplier_waterlevel  * 0.1);
//           const supplier_capacity = parseInt(supplier_tank_info.capacity.replace(/,/g, ''), 10)
//           console.log((newSupplierWaterLevel/supplier_capacity)*100)
//           // Check if updating should stop
//           if ((newSupplierWaterLevel/supplier_capacity)*100 <= 5 || (newWaterLevel/receiver_capacity)*100 >= 95  || (newWaterLevel/receiver_capacity)*100 >= desired_water_percentage || rcvr_info.motor_status === "0") {
//             console.log((newSupplierWaterLevel/supplier_capacity)*100,(newWaterLevel/receiver_capacity)*100,(newWaterLevel/receiver_capacity)*100,)
//             clearInterval(intervals[interval_variable]); // Clear the interval for this tank
//             delete intervals[interval_variable]; 
               
//             const overheadTank = await Tank.findOne({ customerId, tankName: receiver_tank, tankLocation: receiver_type });
//            const connection = overheadTank.connections.inputConnections.find((conn) => conn.inputConnections === supplier_tank);
  
//                if (connection) {
//                connection.motor_status = "0";
//                  await overheadTank.save();
//                    }
//             // Find the tank based on customerId, tankName, and tankLocation
//             const tankToUpdate = await Tank.findOne({ customerId, tankName: receiver_tank, tankLocation: receiver_type });

// // Check if all objects in inputConnections have motor_status === "0"
//             const allMotorStatusZero = tankToUpdate.connections.inputConnections.every(connection => connection.motor_status === "0");

//             if (allMotorStatusZero) {
//   // Update the motor_status field to "0" for the tank
//              await Tank.findOneAndUpdate(
//              { customerId, tankName: receiver_tank, tankLocation: receiver_type },
//               { $set: { motor_status: "0" } }
//                  );
//                         }

        
    
//             console.log("end for"+receiver_tank);
//           } else {
//             // Update water levels in database
//             //supplier_waterlevel = newSupplierWaterLevel;
//            // receiver_waterlevel = newWaterLevel;
//             console.log((newSupplierWaterLevel/supplier_capacity)*100)
//            // console.log((newWaterLevel/receiver_capacity)*100)
//             console.log(newWaterLevel+""+receiver_type)
//             console.log(newSupplierWaterLevel+""+supplier_tank)

//             await Tank.findOneAndUpdate({customerId, tankName: receiver_tank,tankLocation:receiver_type}, { $set: { waterlevel: newWaterLevel } })
//             await  Tank.findOneAndUpdate({customerId, tankName: supplier_tank,tankLocation:supplier_tank_type}, { $set: { waterlevel: newSupplierWaterLevel } })

//             //if (supplier_tank_info2.motor_status==="0"){
//            // await  Tank.findOneAndUpdate({customerId, tankName: supplier_tank,tankLocation:supplier_tank_type}, { $set: { waterlevel: supplier_waterlevel } })
//           //  }

//           }
//         }, 2000);

//       }



//       //    if(supplier_tank_type==="sump" && receiver_type === "sump"){
//       //   await Tank.findOneAndUpdate({customerId, tankName: receiver_tank,tankLocation:receiver_type}, { $set: { motor_status: 1 } });
        
//       //  // console.log(rcvr_info.motor_status)
//       // //  const supplier_tank_info1 = await Tank.findOne({ customerId ,tankName:supplier_tank});
//       //  // initial_update = parseInt(supplier_tank_info1.capacity.replace(/,/g, ''), 10)/2;

//       //  // await Tank.findOneAndUpdate({customerId, tankName: supplier_tank}, { $set: { waterlevel: initial_update } });
//       //   const supplier_tank_info = await Tank.findOne({ customerId ,tankName:supplier_tank,tankLocation:supplier_tank_type});
        
//       //   let supplier_waterlevel = parseInt(supplier_tank_info.waterlevel.replace(/,/g, ''), 10)
//       //    let receiver_waterlevel = parseInt(receiver_tank_info.waterlevel.replace(/,/g, ''), 10)
//       //    intervals[interval_variable] = setInterval(async function () {
//       //     const rcvr_info = await Tank.findOne({ customerId ,tankName:receiver_tank,tankLocation:receiver_type});
//       //     const supplier_capacity = parseInt(supplier_tank_info.capacity.replace(/,/g, ''), 10)
//       //     // Calculate new water levels
//       //     const newWaterLevel = receiver_waterlevel  + 200//Math.floor(supplier_waterlevel  * 0.1);
//       //     const newSupplierWaterLevel = Math.min(supplier_capacity, supplier_waterlevel - 200);// Math.floor(supplier_waterlevel * 0.15));
//       //   //  console.log(newWaterLevel)
//       //   //  console.log(newSupplierWaterLevel)
//       //   //  console.log(rcvr_info.motor_status)
//       //   //  console.log(rcvr_info.tankName)

//       //     // Check if updating should stop
//       //     if ( (newWaterLevel/receiver_capacity)*100 >= 95   ||  (newWaterLevel/receiver_capacity)*100 >= desired_water_percentage || rcvr_info.motor_status === 0  || (newSupplierWaterLevel/supplier_capacity)*100 <= 5) {

//       //       clearInterval(interval_variable)
//       //       delete intervals[interval_variable]; 
//       //       await Tank.findOneAndUpdate({customerId, tankName: receiver_tank,tankLocation:receiver_type}, { $set: { motor_status: 0 } });
            
//       //       console.log("end");
//       //     } else {
//       //       // Update water levels in database
//       //       supplier_waterlevel = newSupplierWaterLevel;
//       //       receiver_waterlevel = newWaterLevel;
//       //       console.log(supplier_waterlevel,"0")
//       //       console.log(receiver_waterlevel,"1")
//       //     //  console.log((newSupplierWaterLevel/supplier_capacity)*100)
//       //      // console.log((newWaterLevel/receiver_capacity)*100)
//       //       await Promise.all([
//       //         Tank.findOneAndUpdate({customerId, tankName: receiver_tank}, { $set: { waterlevel: newWaterLevel } }),
//       //         Tank.findOneAndUpdate({customerId, tankName: supplier_tank}, { $set: { waterlevel: newSupplierWaterLevel } })
//       //       ]);
//       //     }
//       //   }, 2000);


//       // }



//       if(supplier_tank_type==="sump" && receiver_type === "sump"){
//         const receiver_capacity =   parseInt(receiver_tank_info.capacity.replace(/,/g, ''), 10)
        

//         const sumpTank = await Tank.findOne({ customerId, tankName: receiver_tank, tankLocation: receiver_type });
//         const connection = sumpTank.connections.inputConnections.find((conn) => conn.inputConnections === supplier_tank);
        
//         if (connection) {
//           connection.motor_status = "1";
//           await sumpTank.save();
//         }

//        // console.log(receiver_capacity,"0",receiver_tank_info.tankName)
//         await Tank.findOneAndUpdate({customerId, tankName: receiver_tank,tankLocation:receiver_type}, { $set: { motor_status: "1" } });
//         const supplier_tank_info = await Tank.findOne({ customerId ,tankName:supplier_tank,tankLocation:supplier_tank_type});

//       //  let supplier_waterlevel = parseInt(supplier_tank_info.waterlevel.replace(/,/g, ''), 10)
//       // let receiver_waterlevel = parseInt(receiver_tank_info.waterlevel.replace(/,/g, ''), 10)
//       // console.log(receiver_waterlevel,"1")
//        intervals[interval_variable] = setInterval(async function () {
//         // Calculate new water levels
//         const splr_tank_info = await Tank.findOne({ customerId ,tankName:supplier_tank,tankLocation:supplier_tank_type});
//         const rcvr_info = await Tank.findOne({ customerId ,tankName:receiver_tank,tankLocation:receiver_type});
//           const supplier_capacity = parseInt(supplier_tank_info.capacity.replace(/,/g, ''), 10)
//           let supplier_waterlevel = parseInt(splr_tank_info.waterlevel.replace(/,/g, ''), 10)
//           let receiver_waterlevel = parseInt(rcvr_info.waterlevel.replace(/,/g, ''), 10)
//           // Calculate new water levels
//           const newWaterLevel = receiver_waterlevel  + 250//Math.floor(supplier_waterlevel  * 0.1);
//           const newSupplierWaterLevel = Math.min(supplier_capacity, supplier_waterlevel - 250);// Math.floor(supplier_waterlevel * 0.15));
//         // Check if updating should stop
//         if ((newWaterLevel/receiver_capacity)*100 >= 97 || (newWaterLevel/receiver_capacity)*100 >= desired_water_percentage || rcvr_info.motor_status === "0" || (newSupplierWaterLevel/supplier_capacity)*100 <= 5   ) {
 
//           clearInterval(intervals[interval_variable]); // Clear the interval for this tank
//           delete intervals[interval_variable]; 
//           const sumpTank = await Tank.findOne({ customerId, tankName: receiver_tank, tankLocation: receiver_type });
//           const connection = sumpTank.connections.inputConnections.find((conn) => conn.inputConnections === supplier_tank);
 
//               if (connection) {
//               connection.motor_status = "0";
//                 await sumpTank.save();
//                   }
//                  }
//           const tankToUpdate = await Tank.findOne({ customerId, tankName: receiver_tank, tankLocation: receiver_type });

//           // Check if all objects in inputConnections have motor_status === "0"
//                       const allMotorStatusZero = tankToUpdate.connections.inputConnections.every(connection => connection.motor_status === "0");
          
//                       if (allMotorStatusZero) {
//             // Update the motor_status field to "0" for the tank
//                        await Tank.findOneAndUpdate(
//                        { customerId, tankName: receiver_tank, tankLocation: receiver_type },
//                         { $set: { motor_status: "0" } }
//                            );
                         
//           console.log("end for" + receiver_tank);
//         } else {
//           // Update water levels in database
          
//        //   supplier_waterlevel = newSupplierWaterLevel;
//        //     receiver_waterlevel = newWaterLevel;
//             console.log(supplier_waterlevel,"0")
//             console.log(receiver_waterlevel,"1")
//           //  console.log((newSupplierWaterLevel/supplier_capacity)*100)
//            // console.log((newWaterLevel/receiver_capacity)*100)
//             await Promise.all([
//               Tank.findOneAndUpdate({customerId, tankName: receiver_tank}, { $set: { waterlevel: newWaterLevel } }),
//               Tank.findOneAndUpdate({customerId, tankName: supplier_tank}, { $set: { waterlevel: newSupplierWaterLevel } })
//             ]);
//         }
//       }, 2000);

//     }
  

      
//       if(supplier_tank_type==="bore" && receiver_type === "sump"){
//           const receiver_capacity =   parseInt(receiver_tank_info.capacity.replace(/,/g, ''), 10)
//          // console.log(receiver_capacity,"0",receiver_tank_info.tankName)
//           await Tank.findOneAndUpdate({customerId, tankName: receiver_tank,tankLocation:receiver_type}, { $set: { motor_status: "1" } });
//           const sumpTank = await Tank.findOne({ customerId, tankName: receiver_tank, tankLocation: receiver_type });
//           const connection = sumpTank.connections.inputConnections.find((conn) => conn.inputConnections === supplier_tank);
          
//           if (connection) {
//             connection.motor_status = "1";
//             await sumpTank.save();
//           }
  

//         // let receiver_waterlevel = parseInt(receiver_tank_info.waterlevel.replace(/,/g, ''), 10)
//         // console.log(receiver_waterlevel,"1")
//          intervals[interval_variable] = setInterval(async function () {
//           // Calculate new water levels
//           const rcvr_info = await Tank.findOne({ customerId ,tankName:receiver_tank,tankLocation:receiver_type});
//           //console.log(rcvr_info)
//           let receiver_waterlevel = parseInt(rcvr_info.waterlevel.replace(/,/g, ''), 10)

//           //console.log(rcvr_info.motor_status)
//           const newWaterLevel = receiver_waterlevel+250;
//           //console.log(newWaterLevel,"2",receiver_tank_info.tankName)
//           // Check if updating should stop
//           if ((newWaterLevel/receiver_capacity)*100 >= 97 || (newWaterLevel/receiver_capacity)*100 >= desired_water_percentage || rcvr_info.motor_status === "0"   ) {
            
//             clearInterval(intervals[interval_variable]); // Clear the interval for this tank
//             delete intervals[interval_variable];

//             const sumpTank = await Tank.findOne({ customerId, tankName: receiver_tank, tankLocation: receiver_type });
//             const connection = sumpTank.connections.inputConnections.find((conn) => conn.inputConnections === supplier_tank);
            
//             if (connection) {
//               connection.motor_status = "0";
//               await sumpTank.save();
//             }
                          
//              const tankToUpdate = await Tank.findOne({ customerId, tankName: receiver_tank, tankLocation: receiver_type });

// // Check if all objects in inputConnections have motor_status === "0"
//             const allMotorStatusZero = tankToUpdate.connections.inputConnections.every(connection => connection.motor_status === "0");

//             if (allMotorStatusZero) {
//   // Update the motor_status field to "0" for the tank
//              await Tank.findOneAndUpdate(
//              { customerId, tankName: receiver_tank, tankLocation: receiver_type },
//               { $set: { motor_status: "0" } }
//                  );
//                         }

           
//             console.log("end for" + receiver_tank);
//           } else {
//             // Update water levels in database
            
//            // receiver_waterlevel = newWaterLevel;
            
//             //console.log((newWaterLevel/receiver_capacity)*100,"4",receiver_tank_info.tankName)
//             await  Tank.findOneAndUpdate({customerId, tankName: receiver_tank,tankLocation:receiver_type}, { $set: { waterlevel: newWaterLevel } })
//             console.log(receiver_tank+"="+newWaterLevel+"="+"bore to sump")
//           }
//         }, 2000);

//       }
//      // console.log(customerId,req.body.from,req.body.from_type,receiver_tank,req.body.to_type,)
//     }
    
//     else if (action === "stop") {
//     //stop_time = new Date().toLocaleString('en-US', {timeZone: 'Asia/Kolkata'})
//     clearInterval(intervals[interval_variable]); // Clear the interval for this tank
//     delete intervals[interval_variable]; 
    
//       const stopTime = new Date().toLocaleString('en-US', { timeZone: 'Asia/Kolkata' });
//      // console.log(currentTank.start_time)
//       const startTime = currentTank.start_time;
//      // const duration = calculateDuration(startTime, stopTime);
      
//       // Store the duration or perform any required operations
      
//       supplier_tanks = supplier_tanks.filter(tank => tank.supplier_tank !== supplier_tank);
//      // console.log(supplier_tanks)
    
//     // storing data of how amny water supplied from sump to overhead to calculate the consumption
//           const suplr_tank_info2 = await Tank.findOne({ customerId ,tankName:supplier_tank,tankLocation:supplier_tank_type});

//     let water_added_from_midnight1=0
//     if (supplier_tank_type === "sump") {
//      // const rcvr_info2 =  await Tank.findOne({ customerId ,tankName:receiver_tank,tankLocation:receiver_type});
//     console.log(currentSump.receiver_tank_total_water_added_from_midnight,"5")
//      water_added_from_midnight1=currentSump.receiver_tank_total_water_added_from_midnight

//      console.log(water_added_from_midnight1)
     
//      }
//      const sump_water_level1 =currentSump.supplier_initial_waterlevel  
//      console.log(sump_water_level1,"1")
//     // console.log(water_added_from_midnight)
//     const sump_final_water_level= parseInt(suplr_tank_info2.waterlevel.replace(/,/g, ''), 10)
//     console.log(sump_final_water_level,"2")
//     sump_water_levels = sump_water_levels.filter(tank => tank.supplier_tank !== supplier_tank);

//     const quantity_delivered = Math.abs(sump_water_level1 - sump_final_water_level);


//      if (supplier_tank_type === "sump") {
    
//      final_added_water=water_added_from_midnight1+quantity_delivered
//      await Tank.findOneAndUpdate({customerId, tankName: receiver_tank,tankLocation:receiver_type}, { $set: { total_water_added_from_midnight: final_added_water } })

//      }

//     const overheadTank = await Tank.findOne({ customerId, tankName: receiver_tank, tankLocation: receiver_type });
//     const connection = overheadTank.connections.inputConnections.find((conn) => conn.inputConnections === supplier_tank);
  
//     if (connection) {
//     connection.motor_status = "0";
//     await overheadTank.save();
//      }

//      const tankToUpdate = await Tank.findOne({ customerId, tankName: receiver_tank, tankLocation: receiver_type });

//      // Check if all objects in inputConnections have motor_status === "0"
//       const allMotorStatusZero = tankToUpdate.connections.inputConnections.every(connection => connection.motor_status === "0");
     
//       if (allMotorStatusZero) {
//         console.log(allMotorStatusZero)
//        // Update the motor_status field to "0" for the tank
//        await Tank.findOneAndUpdate(
//        { customerId, tankName: receiver_tank, tankLocation: receiver_type },
//            { $set: { motor_status: "0" } }
//                       );
//                              }

//                              //saving the motor run time and data

//                              motorData = {

//                               customerId:customerId,
//                               supplierTank : supplier_tank,
//                               supplier_type: supplier_tank_type,
//                               receiverTank: receiver_tank,
//                               receiver_type: receiver_type,
//                               startTime: startTime,
//                               stopTime: stopTime,
//                               quantity_delivered:quantity_delivered
                              
                            
                        
//                             };
//                             var motorData = new MotorData(motorData);
                      
//                           checkFormEncoding = isUserFormUrlEncoded(req);
//                           if (checkFormEncoding.isUserFormUrlEncoded) {
//                             usertobeInserted = checkFormEncoding.motorData;
//                             console.log("thsi true url string");
//                             motorData.customerId = customerId;
//                             motorData.supplierTank = supplierTank;
//                             motorData.receiverTank = receiver_tank;
//                             motorData.supplier_type = supplier_type;
//                             motorData.receiver_type = receiver_type;
//                             motorData.startTime = startTime;
//                             motorData.stopTime = stopTime;
//                             motorData.quantity_delivered = quantity_delivered;
                           
                            
//                           }
//                           const motor_data = await motorData.save();
//                           console.log(motor_data)
//                          // reply.send({ status_code: 200, data: motor_data });
                         
                      
                      
                       
//                            // reply.send({ status_code: 200, "start time": start_time, data: motor_data});
//                           //  console.log(start_time)
//                           //  return motor_data
                      
                      
     
//      // console.log(stop_time)
//          // clearInterval(intervalId);

//         //  await Tank.findOneAndUpdate({customerId, tankName: receiver_tank,tankLocation:(req.body.to_type).toLowerCase()}, { $set: { motor_status: "0" } });

//        reply.send({ status_code: 200, "stop time": stopTime,data: motor_data});
//       } else {
//           throw new Error("Invalid action");
//       }
      
//       return { message: 'Water level updates started' };
      
//   } catch (err) {
//       throw new Error(`Failed to start/stop water level updates: ${err.message}`);

//   };
// };

 
// exports.consumption = async (request, reply) => {
//   try {
//     const customerId = req.params.customerId;
//     const tanks = await Tank.find({ customerId,tankLocation:"overhead"});
//     const tankData = []; 
//     for (const tank of tanks) {
//       const tankId = tank._id;
//       const waterlevel_at_midnight = parseInt(tank.waterlevel_at_midnight.replace(/,/g, ''), 10);
//       const total_water_added_from_midnight = parseInt(tank.total_water_added_from_midnight.replace(/,/g, ''), 10);
//       const waterlevel = parseInt(tank.waterlevel.replace(/,/g, ''), 10);
      
//       const tankname = tank.tankName
//       const consumption = (waterlevel_at_midnight+total_water_added_from_midnight)-waterlevel
      
//         tankData.push({ tankname, waterLevel: consumption }); 

        
//        // console.log(newWaterLevel);

//     }
//     reply.send({ status_code: 200, tankData }); 

//     return { message: 'Water level updates started' };
//   } catch (err) {
//     throw boom.boomify(err);
//   }









exports.consumption = async (request, reply) => {
  try {
    const { customerId } = request.params;
    const { startDate, stopDate, block } = request.body;
    let { typeofwater } = request.body;

    // Convert typeofwater to lowercase
    typeofwater = typeofwater.toLowerCase();
    const start = moment(startDate, "DD-MMM-YYYY - HH:mm").toDate();
    const end = moment(stopDate, "DD-MMM-YYYY - HH:mm").toDate();

    // Construct the query object
    const tankQuery = { customerId, tankLocation: "overhead" };
    if (block !== "All") tankQuery.blockName = block;

    // Add typeofwater filter
    if (typeofwater === "bore") {
      tankQuery.typeOfWater = { $in: ["bore", "Bore Water"] };
    } else if (typeofwater === "drinking") {
      tankQuery.typeOfWater = { $in: ["drinking", "Drinking Water"] };
    }

    const tanks = await Tank.find(tankQuery);
    const tankData = [];
    const tankconsumptionData = [];
    let totalConsumptionForSelectedBlockAndTypeOfWater = 0;
    let totalBoreConsumptionForSelectedBlockAndTypeOfWater = 0;
    let totalBoreCapacityForSelectedBlockAndTypeOfWater = 0;
    let totalDrinkingConsumptionForSelectedBlockAndTypeOfWater = 0;
    let totalDrinkingCapacityForSelectedBlockAndTypeOfWater = 0;

    for (const tank of tanks) {
      const waterlevel_at_midnight = parseInt(tank.waterlevel_at_midnight.replace(/,/g, ''), 10);
      const total_water_added_from_midnight = parseInt(tank.total_water_added_from_midnight.replace(/,/g, ''), 10);
      const waterlevel = parseInt(tank.waterlevel.replace(/,/g, ''), 10);
      const tankname = tank.tankName;
      const capacity = parseInt(tank.capacity.replace(/,/g, ''), 10);

      const tankConsumptions = await TankConsumptionOriginalSchema.find({
        customerId,
        tankName: tank.tankName,
        tankLocation: tank.tankLocation,
        ...(block !== "All" && { block: tank.blockName }),
        ...(typeofwater === "bore" && { typeofwater: { $in: ["bore", "Bore Water"] } }),
        ...(typeofwater === "drinking" && { typeofwater: { $in: ["drinking", "Drinking Water"] } }),
      });

      const filteredConsumptions = tankConsumptions.filter((record) => {
        const recordTime = moment(record.time, "DD-MMM-YYYY - HH:mm").toDate();
        return recordTime >= start && recordTime <= end;
      });

      const total_consumption_from_records = filteredConsumptions.reduce((acc, record) => {
        return acc + parseInt(record.consumption, 10);
      }, 0);

      const consumption = (waterlevel_at_midnight + total_water_added_from_midnight) - waterlevel + total_consumption_from_records;
      totalConsumptionForSelectedBlockAndTypeOfWater += consumption;
     
      // Add to the total consumption and capacities based on water type
      if (tank.typeOfWater === "bore" || tank.typeOfWater === "Bore Water") {
        totalBoreConsumptionForSelectedBlockAndTypeOfWater += consumption;
        totalBoreCapacityForSelectedBlockAndTypeOfWater += capacity;
      } else if (tank.typeOfWater === "drinking" || tank.typeOfWater === "Drinking Water") {
        totalDrinkingConsumptionForSelectedBlockAndTypeOfWater += consumption;
        totalDrinkingCapacityForSelectedBlockAndTypeOfWater += capacity;
      }

      tankData.push({
        tankname,
        totalConsumption: consumption,
        block: tank.blockName,
        TypeofWater: tank.typeOfWater,
        location: tank.tankLocation,
        capacity: tank.capacity,
        waterlevel: tank.waterlevel,
      });

      tankconsumptionData.push({
        tankname,
        consumptionRecordsdatewise: filteredConsumptions,
      });
    }

    // Calculate total consumption percentages
    const boreConsumptionPercentage = totalBoreCapacityForSelectedBlockAndTypeOfWater
      ? ((totalBoreConsumptionForSelectedBlockAndTypeOfWater / totalBoreCapacityForSelectedBlockAndTypeOfWater) * 100).toFixed(2)
      : 0;

    const drinkingConsumptionPercentage = totalDrinkingCapacityForSelectedBlockAndTypeOfWater
      ? ((totalDrinkingConsumptionForSelectedBlockAndTypeOfWater / totalDrinkingCapacityForSelectedBlockAndTypeOfWater) * 100).toFixed(2)
      : 0;

    const totalConsumptionPercentage =
      typeofwater === "bore"
        ? boreConsumptionPercentage
        : typeofwater === "drinking"
        ? drinkingConsumptionPercentage
        : ((totalBoreConsumptionForSelectedBlockAndTypeOfWater + totalDrinkingConsumptionForSelectedBlockAndTypeOfWater) /
           (totalBoreCapacityForSelectedBlockAndTypeOfWater + totalDrinkingCapacityForSelectedBlockAndTypeOfWater) *
           100
          ).toFixed(2);

    // Include the total consumption in the response
    const response = {
      status_code: 200,
      tankData,
      consumptiorecordsdatewise: tankconsumptionData,
      totalConsumptionPercentage,
      ...(typeofwater === "all"
        ? {
            totalConsumptionPercentageForBore: boreConsumptionPercentage,
            totalConsumptionPercentageForDrinking: drinkingConsumptionPercentage,
            totalConsumptionForBore: totalBoreConsumptionForSelectedBlockAndTypeOfWater,
            totalConsumptionForDrinking: totalDrinkingConsumptionForSelectedBlockAndTypeOfWater,
          }
        : {
            [`total consumption of ${typeofwater} and selected block`]:
              typeofwater === "bore"
                ? totalBoreConsumptionForSelectedBlockAndTypeOfWater
                : totalDrinkingConsumptionForSelectedBlockAndTypeOfWater,
          }
        ),
        [`total consumption of ${typeofwater} and selected block`]: totalConsumptionForSelectedBlockAndTypeOfWater
    };

    reply.send(response);
  } catch (err) {
    throw boom.boomify(err);
  }
};



exports.consumptiondatewiseofalltanks = async (request, reply) => {
  try {
    const { customerId } = request.params;
    const { startDate, stopDate, block } = request.body;
    let { typeofwater } = request.body;

    typeofwater = typeofwater.toLowerCase();
    const start = moment(startDate, "DD-MMM-YYYY - HH:mm").toDate();
    const end = moment(stopDate, "DD-MMM-YYYY - HH:mm").toDate();

    const tankQuery = { customerId, tankLocation: "overhead" };
    if (block !== "All") {
      tankQuery.blockName = block;
    }
    if (typeofwater !== "all") {
      tankQuery.typeOfWater = typeofwater;
    }

    const tanks = await Tank.find(tankQuery);
    const tankconsumptionData = {};
    let totalConsumptionForSelectedBlockAndTypeOfWater = 0;
    let totalAvailableCapacity = 0;
    let totalConsumed = 0;

    for (const tank of tanks) {
      const tankname = tank.tankName;

      const tankConsumptions = await TankConsumptionOriginalSchema.find({
        customerId,
        tankName: tankname,
        tankLocation: tank.tankLocation,
        ...(block !== "All" && { block: tank.blockName }),
        ...(typeofwater !== "all" && { typeofwater: tank.typeOfWater })
      });

      const filteredConsumptions = tankConsumptions.filter((record) => {
        const recordTime = moment(record.time, "DD-MMM-YYYY - HH:mm").toDate();
        return recordTime >= start && recordTime <= end;
      });

      // filteredConsumptions.forEach(record => {
      //   totalConsumed += parseInt(record.consumption, 10);
      //   totalAvailableCapacity += parseInt(record.capacity, 10);
      // });

      for (const record of filteredConsumptions) {
        const recordTime = moment(record.time, "DD-MMM-YYYY - HH:mm").format("DD-MMM-YYYY - HH:mm");
        const tank_info = await Tank.findOne({
          customerId:record.customerId,
          tankName: record.tankName,
          tankLocation: record.tankLocation,
        
        });
        totalConsumptionForSelectedBlockAndTypeOfWater+=parseInt(record.consumption, 10);
        totalConsumed += parseInt(record.consumption, 10);
       ;
        // console.log( parseInt(tank_info.capacity.replace(/,/g, ''), 10))
        totalAvailableCapacity +=  parseInt(tank_info.capacity.replace(/,/g, ''), 10)
        if (!tankconsumptionData[recordTime]) {
          tankconsumptionData[recordTime] = {
            date: recordTime,
            consumptionRecordsdatewise: [],
            count: 0
          };
        }

        const recordExists = tankconsumptionData[recordTime].consumptionRecordsdatewise.some(r => r.tankName === record.tankName);
        
        if (!recordExists) {
          tankconsumptionData[recordTime].consumptionRecordsdatewise.push({
            tankName: record.tankName,
            consumption: record.consumption,
            available_capacity: record.available_capacity,
            time: record.time
          });
          tankconsumptionData[recordTime].count++;
        }
      }
    }

    const responseData = Object.values(tankconsumptionData);
    const totalConsumptionPercentage = totalAvailableCapacity > 0 ? ((totalConsumed / totalAvailableCapacity) * 100).toFixed(2) : "0";
    console.log(totalConsumed,"totalConsumed",totalAvailableCapacity,"totalAvailableCapacity",totalConsumptionForSelectedBlockAndTypeOfWater,"totalConsumptionForSelectedBlockAndTypeOfWater")
    const response = {
      status_code: 200,
      consumptiorecordsdatewise: responseData,
      [`total consumption of ${typeofwater} and selected block`]: totalConsumptionForSelectedBlockAndTypeOfWater,
      totalConsumptionPercentage: `${totalConsumptionPercentage}%`
    };

    reply.send(response);
  } catch (err) {
    throw boom.boomify(err);
  }
};












const delay = ms => new Promise(resolve => setTimeout(resolve, ms));

//const moment = require('moment'); // Import moment.js for date/time operations
const formatDate = (date) => {
  const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
  const day = String(date.getDate()).padStart(2, '0');
  const month = months[date.getMonth()];
  const year = date.getFullYear();
  const hours = String(date.getHours()).padStart(2, '0');
  const minutes = String(date.getMinutes()).padStart(2, '0');
  return `${day}-${month}-${year} - ${hours}:${minutes}`;
};


// exports.motorAction = async (req, reply) => {
//   try {
//     const customerId = req.params.customerId;
//     const action = req.body.action;
//     const motorId = req.body.motor_id;
//     const start_instance_id = req.body.start_instance_id
//     console.log(req.body.startTime)
//     // Ensure motor_id is provided
//     if (!motorId) {
//       throw new Error("Motor ID is required.");
//     }

//     // Determine the motor stop status based on the action
//     let motorStopStatus;
//     if (action === "start") {
//       motorStopStatus = "2"; // If action is start, set stop status to "2"
//     } else if (action === "stop") {
//       motorStopStatus = "1"; // If action is stop, set stop status to "1"
//     } else {
//       throw new Error("Invalid action provided.");
//     }

//     // Update the motor stop status immediately if action is stop
//     if (action === "stop") {
//       // Update the motor stop status and other fields
//       await Tank.updateOne(
//         { customerId, "connections.inputConnections.motor_id": motorId },
//         { 
//           $set: { 
//             "connections.inputConnections.$.motor_stop_status": "1",
//             "connections.inputConnections.$.stopTime": req.body.stopTime,
//             "connections.inputConnections.$.threshold_type": null,
//             "connections.inputConnections.$.manual_threshold_time": null,
//             "connections.inputConnections.$.manual_threshold_percentage": null
//           }
//         }
//       );

//       // Send immediate response to the client
//       reply.code(200).send({ message: "Motor stopped successfully." });

//       // Perform stop operations in the background
//       (async () => {
//         await delay(300000);

//         // Update the existing motor data entry with stop details
//         const motorData = await MotorData.findOne({ customerId, motor_id: motorId, start_instance_id: start_instance_id });
//         if (motorData) {
//           const receiverTank = await Tank.findOne({ customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() });
//           const receiverFinalWaterLevel = parseInt(receiverTank.waterlevel, 10);
//           const quantityDelivered = receiverFinalWaterLevel - parseInt(motorData.receiverInitialwaterlevel, 10);
//           const water_pumped_till_now = parseInt(receiverTank.total_water_added_from_midnight, 10);
//           const totalwaterpumped = quantityDelivered + water_pumped_till_now;
//           await Tank.findOneAndUpdate(
//             { customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() },
//             { $set: { total_water_added_from_midnight: totalwaterpumped } }
//           );

//           await MotorData.updateOne(
//             { customerId, motor_id: motorId, start_instance_id: start_instance_id },
//             { 
//               $set: { 
//                 stopTime: req.body.stopTime,
//                 receiverfinalwaterlevel: receiverFinalWaterLevel.toString(),
//                 quantity_delivered: quantityDelivered.toString()
//               }
//             }
//           );
//         }
//       })();

//       // Return here to ensure the rest of the code is not executed for the stop action
//       return;
//     } else {
//       // Update the motor stop status to "2" for start action
//       await Tank.updateOne(
//         { customerId, "connections.inputConnections.motor_id": motorId },
//         { $set: { "connections.inputConnections.$.motor_stop_status": "2" } }
//       );
//     }

//     // Check threshold settings if action is start
//     if (action === "start") {
//       if (req.body.threshold_type === "time") {
//         // If threshold type is time, update threshold time
//         // await Tank.updateOne(
//         //   { customerId, "connections.inputConnections.motor_id": motorId },
//         //   { $set: { "connections.inputConnections.$.manual_threshold_time": req.body.manual_threshold_time,startTime:req.body.startTime } }
//         // );
//         const receiver_tank_info7 = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() });

//         const newMotorData = new MotorData({
//           customerId: customerId,
//           motor_id: motorId,
//           start_instance_id: start_instance_id,
//           supplierTank: req.body.from,
//           receiverTank: req.body.to,
//           supplier_type: req.body.from_type,
//           receiver_type: req.body.to_type,
//           startTime: req.body.startTime,
//           receiverInitialwaterlevel:parseInt(receiver_tank_info7.waterlevel, 10)
//         });
//         await newMotorData.save();

//         for await (const tank of Tank.find({  "connections.inputConnections.motor_id": motorId })) {
//           const index = tank.connections.inputConnections.findIndex(connection => connection.motor_id === motorId);
//           if (index !== -1) {
//             await Tank.updateOne(
//               { customerId, "connections.inputConnections.motor_id": motorId },
//               { $set: { [`connections.inputConnections.${index}.manual_threshold_time`]: req.body.manual_threshold_time, [`connections.inputConnections.${index}.startTime`]: req.body.startTime,[`connections.inputConnections.${index}.start_instance_id`]: start_instance_id } }
//             );
//           }
//         }
        

//         // Start monitoring water level based on threshold time
//         const thresholdTime = moment().add(req.body.manual_threshold_time, 'minutes').toDate();
//         const intervalId = setInterval(async () => {
//           const splr_tank_info3 = await Tank.findOne({ customerId, tankName: req.body.from, tankLocation: req.body.from_type.toLowerCase() });
//           const splr_tank_info3_waterlevel = parseInt(splr_tank_info3.waterlevel, 10);
//           //console.log(splr_tank_info3_waterlevel,"splr_tank_info3_waterlevel")
//           const splr_tank_info3_capacity = parseInt(splr_tank_info3.capacity.replace(/,/g, ''), 10);
//          // const splr_tank_info3_capacity = parseInt(splr_tank_info3.capacity, 10);
//          // console.log(splr_tank_info3.capacity,splr_tank_info3_capacity,"splr_tank_info3_capacity")
//           const splr_tank_info3_percentage = (splr_tank_info3_waterlevel / splr_tank_info3_capacity) * 100;
//          // console.log(splr_tank_info3_percentage, "percentage for less than 20");

//           if (new Date() >= thresholdTime || splr_tank_info3_percentage <= 20) {
//             console.log(splr_tank_info3_percentage,)
//             await Tank.updateOne(
//               { customerId, "connections.inputConnections.motor_id": motorId },
//               {
//                 $set: {
//                   "connections.inputConnections.$.motor_stop_status": "1",
//                   "connections.inputConnections.$.threshold_type": null,
//                   "connections.inputConnections.$.manual_threshold_time": null,
//                   "connections.inputConnections.$.manual_threshold_percentage": null
//                 }
//               }
//             );
//             clearInterval(intervalId);

//             await delay(300000);

//             const motorData = await MotorData.findOne({ customerId, motor_id: motorId, start_instance_id: start_instance_id });
//             if (motorData) {
//               const receiverTank = await Tank.findOne({ customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() });
//               const receiverFinalWaterLevel = parseInt(receiverTank.waterlevel, 10);
//               const quantityDelivered = receiverFinalWaterLevel - parseInt(motorData.receiverInitialwaterlevel, 10);
//               const water_pumped_till_now = parseInt(receiverTank.total_water_added_from_midnight, 10);
//               const totalwaterpumped = quantityDelivered + water_pumped_till_now
//               await  Tank.findOneAndUpdate({customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase()}, { $set: { total_water_added_from_midnight: totalwaterpumped } })

//               const stopTime = formatDate(new Date());

//               await MotorData.updateOne(
//                 { customerId, motor_id: motorId, start_instance_id: start_instance_id },
//                 {
//                   $set: {
//                     stopTime:stopTime,
//                     receiverfinalwaterlevel: receiverFinalWaterLevel.toString(),
//                     quantity_delivered: quantityDelivered.toString()
//                   }
//                 }
//               );
//             }
//           }
//         }, 60000);
//       } else if (req.body.threshold_type === "litres") {
//         console.log("entered litres")
//         const receiver_tank_info7 = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() });

//         const newMotorData = new MotorData({
//           customerId: customerId,
//           motor_id: motorId,
//           start_instance_id: start_instance_id,
//           supplierTank: req.body.from,
//           receiverTank: req.body.to,
//           supplier_type: req.body.from_type,
//           receiver_type: req.body.to_type,
//           startTime: req.body.startTime,
//           receiverInitialwaterlevel:parseInt(receiver_tank_info7.waterlevel, 10)
//         });
//         await newMotorData.save();
//         // If threshold type is percentage, calculate percentage threshold
//         const receiver_tank_info = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() });
//         const supplier_tank_info = await Tank.findOne({ customerId, tankName: req.body.from, tankLocation: req.body.from_type.toLowerCase() });
//         if (!receiver_tank_info) {
//           throw new Error("Receiver tank not found.");
//         }
//         if (!supplier_tank_info) {
//           throw new Error("Supplierr tank not found.");
//         }
//         const supplier_capacity =  parseInt(supplier_tank_info.capacity, 10);
//         const supplier_waterLevel = parseInt(supplier_tank_info.waterlevel, 10); 

//         const capacity = parseInt(receiver_tank_info.capacity, 10);
//         const waterLevel = parseInt(receiver_tank_info.waterlevel, 10); 
//         const desired_percentage = parseInt(req.body.manual_threshold_litres.replace(/,/g, ''), 10);

//         console.log(desired_percentage)
//         const threshold_water_level = waterLevel+desired_percentage;

//         const supplier_threshold = supplier_waterLevel-desired_percentage
//         console.log(supplier_threshold,"supplier_threshold")

//         for await (const tank of Tank.find({  "connections.inputConnections.motor_id": motorId })) {
//           const index = tank.connections.inputConnections.findIndex(connection => connection.motor_id === motorId);
//           if (index !== -1) {
//             await Tank.updateOne(
//               { customerId, "connections.inputConnections.motor_id": motorId },
//               { $set: { [`connections.inputConnections.${index}.manual_threshold_percentage`]: supplier_threshold.toString(), [`connections.inputConnections.${index}.startTime`]: req.body.startTime } }
//             );
//           }
//         }
        


//         // Update water level threshold
       

//         // Start monitoring water level based on threshold percentage
//         const intervalId = setInterval(async () => {
//           // Check if water level has reached the threshold percentage
//           const supplier_tank_info1 = await Tank.findOne({ customerId, tankName: req.body.from, tankLocation: req.body.from_type.toLowerCase() });
//           const current_water_level = parseInt(supplier_tank_info1.waterlevel, 10);
//           if (current_water_level <= supplier_threshold) {
//             // Stop the motor pump
//             await Tank.updateOne(
//               { customerId, "connections.inputConnections.motor_id": motorId },
//               { 
//                 $set: { 
//                   "connections.inputConnections.$.motor_stop_status": "1",
                
//                   "connections.inputConnections.$.threshold_type": null,
//                   "connections.inputConnections.$.manual_threshold_time": null,
//                   "connections.inputConnections.$.manual_threshold_percentage": null
//                 }
//               }
//             );
//             clearInterval(intervalId); // Stop monitoring water level
//             await delay(300000);

//             const motorData = await MotorData.findOne({ customerId, motor_id: motorId, start_instance_id: start_instance_id });
//             if (motorData) {
//               const receiverTank = await Tank.findOne({ customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() });
//               const receiverFinalWaterLevel = parseInt(receiverTank.waterlevel, 10);
//               const quantityDelivered = receiverFinalWaterLevel - parseInt(motorData.receiverInitialwaterlevel, 10);


//               const stopTime = formatDate(new Date());

//               await MotorData.updateOne(
//                 { customerId, motor_id: motorId, start_instance_id: start_instance_id },
//                 {
//                   $set: {
//                     stopTime:stopTime,
//                     receiverfinalwaterlevel: receiverFinalWaterLevel.toString(),
//                     quantity_delivered: quantityDelivered.toString()
//                   }
//                 }
//               );
//             }
//           }
//         }, 20000); // Check water level every minute
//       }
//     }

//     // Respond with success message
//     reply.code(200).send({ message: `Motor ${action === "start" ? "started" : "stopped"} successfully.` });
//   } catch (err) {
//     // Handle errors
//     throw boom.boomify(err);
//   }
// };

const admin = require('firebase-admin');

// Initialize Firebase Admin SDK (make sure this is done once in your app)
// const serviceAccount = require('../waternotifications-ab81a-firebase-adminsdk-ereny-8b0bdac787.json');
const serviceAccount = require('../waternotifications-ab81a-firebase-adminsdk-ereny-8b0bdac787.json');

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
});

// // Handle motor start event
// eventEmitter.on('motorStart', async (fcmTokens) => {
//   await sendNotification(fcmTokens, 'Motor Started', 'The motor has been started successfully.');
// });

// // Handle motor stop event
// eventEmitter.on('motorStop', async (fcmTokens) => {
//   await sendNotification(fcmTokens, 'Motor Stopped', 'The motor has been stopped successfully.');
// });

// // Handle low water level event
// eventEmitter.on('lowWaterLevel', async (fcmTokens) => {
//   await sendNotification(fcmTokens, 'Low Water Level', 'The water level is below 20%.');
// });

// // Handle high water level event
// eventEmitter.on('highWaterLevel', async (fcmTokens) => {
//   await sendNotification(fcmTokens, 'High Water Level', 'The water level has reached above 90%.');
// });

// Handle motor start event with timestamp
// eventEmitter.on('motorStart', async (fcmTokens, timestamp, motorId, waterLevel) => {
//   await sendNotification(fcmTokens, 'Motor Started', `Motor ID: ${motorId} started successfully at ${timestamp}. Current Water Level: ${waterLevel} Ltrs`);
// });

// eventEmitter.on(
//   'motorStart', 
//   async (fcmTokens, timestamp, motorId, waterLevel, blockName, tankName, startTime, motorOnType, stopCriteria, manual_threshold_time) => {
//     try {
//       // Retrieve the user information
//       const users = await User.find({ fcmIds: { $in: fcmTokens } });
//       console.log("users", users);
//       const userNames = users.map(user => user.username).join(', ');
//       console.log("userNames", userNames);
//       const startMethod = motorOnType === "APP" ? "via the App" : "Manual";

//       // Prepare the message
//       const message = 
//         `🚰 Tank Name: '${tankName}'\n` +
//         `🕒 Pump started at: '${startTime}'\n` +
//         `👤 Started by : ${userNames}\n` +
//         // `Pump started by: '${motorOnType.toUpperCase()}'\n` +
//         `Mode : '${startMethod}'\n` +
//         `Will stop at after: '${manual_threshold_time}' mins`;

//       // Send the notification
//       await sendNotification(fcmTokens, 'Arminta Water Management', message);
//     } catch (error) {
//       console.error('Error in motorStart event:', error);
//     }
//   }
// );

// Event listener for motorStart
eventEmitter.on(
  'motorStart', 
  async (fcmTokens, tankName, blockName, startTime, motorOnType, manual_threshold_time, typeOfWater) => {
    try {
      // Retrieve the user information
      const users = await User.find({ fcmIds: { $in: fcmTokens } });
      console.log("users", users);
      const userNames = users.map(user => user.username).join(', ');
      console.log("userNames", userNames);
      
      const startMethod = motorOnType === "Mobile APP" ? "Mobile APP" : "Manual";

      // Generate motor name dynamically based on tank name, block name, and type of water
      const motorName = `${tankName}-${blockName}-${typeOfWater}`;

      // Get current date and time for the motor start time
      const currentDateTime = new Date();
      const formattedDate = currentDateTime.toLocaleDateString(); // Customize this format as needed
      const formattedTime = currentDateTime.toLocaleTimeString(); // Customize this format as needed

      // Prepare the message
      const message = 
        `🚰 Motor Name: ${motorName}\n` +
        `🚰 Tank Name: '${tankName}'\n` +
        `🚰 Block Name: '${blockName}'\n` +
        `👤 Started by: ${userNames}\n` +
        `📱 Mode: '${startMethod}'\n` +
        `🕒 Pump started at: ${startTime} (Time: ${formattedTime} on ${formattedDate})\n` +
        `Will stop after: '${manual_threshold_time}' mins`;

      // Send the notification
      await sendNotification(fcmTokens, 'Arminta Water Management', message);
    } catch (error) {
      console.error('Error in motorStart event:', error);
    }
  }
);

// Event listener for motorStop
eventEmitter.on(
  'motorStop',
  async (fcmTokens, tankName, blockName, stopTime, motorOnType, totalWaterPumped, typeOfWater) => {
    try {
      // Retrieve the user information
      const users = await User.find({ fcmIds: { $in: fcmTokens } });
      const userNames = users.map(user => user.username).join(', ');

      const stopMethod = motorOnType === "Mobile APP" ? "Mobile APP" : "Manual";

      // Generate motor name dynamically based on tank name, block name, and type of water
      const motorName = `${tankName}-${blockName}-${typeOfWater}`;

      // Get current date and time for the motor stop time
      const currentDateTime = new Date();
      const formattedDate = currentDateTime.toLocaleDateString(); // Customize this format as needed
      const formattedTime = currentDateTime.toLocaleTimeString(); // Customize this format as needed

      // Prepare the message
      const message = 
        `🚰 Motor Name: ${motorName}\n` +
        `🚰 Tank Name: '${tankName}'\n` +
        `🚰 Block Name: '${blockName}'\n` +
        `👤 Stopped by: ${userNames}\n` +
        `📱 Mode: '${stopMethod}'\n` +
        `🕒 Pump stopped at: ${stopTime} (Time: ${formattedTime} on ${formattedDate})\n` +
        `💧 Total water pumped: ${totalWaterPumped} liters\n`; // Ensure this line is properly terminated

      // Send the notification
      await sendNotification(fcmTokens, 'Arminta Water Management', message);
    } catch (error) {
      console.error('Error in motorStop event:', error);
    }
  }
);



// eventEmitter.on('motorStop', async (fcmTokens,  tankName,stopTime, motorOnType) => {
//   try {
//     // Retrieve the user information
//     const users = await User.find({ fcmIds: { $in: fcmTokens } });
//     console.log("users",users)
//     const userNames = users.map(user => user.username).join(', ');
//     console.log("userNames",userNames)

//     const stopMethod = motorOnType === "Mobile APP" ? "via the App" : "manual";

//     // Prepare the message
//     // const message = `Tank Name: '${tankName}', Pump stopped at '${stopTime}' by Initiated by user(s): ${userNames} '${motorOnType}'`;
//     const message = 
//     `🚰 Tank Name: '${tankName}'\n` +
//     `🕒 Pump stopped at: '${stopTime}'\n` +
//     `👤 Initiated by : ${userNames}\n` +
//     // `Motor Off Type: '${motorOnType}'`;
//     `Motor Off Type: '${stopMethod}'`;

  
//     // Send the notification
//     await sendNotification(fcmTokens, 'Arminta Water Management', message);
//   } catch (error) {
//     console.error('Error in motorStart event:', error);
//   }
// });

// Emit motor stop event with motorId
// eventEmitter.on('motorStop', async (fcmTokens, timestamp, motorId,  waterLevel, blockName, tankName,stopTime,motorOnType) => {
//   const message = `Water supply from '${blockName}' to '${tankName}' stopped at ${stopTime} by '${motorOnType}' mode. Current Water Level: ${waterLevel} Ltrs.`;
//   await sendNotification(fcmTokens, 'Motor Stopped', message);
// });

// Event listener to handle notification
// eventEmitter.on('sendLowWaterNotification', async (fcmToken, tankInfo) => {
//   const message = formatWaterLevelMessage(tankInfo, 'low');
//   sendNotification(fcmToken, message);
// });

// eventEmitter.on('sendVeryLowWaterNotification', async (fcmToken, tankInfo) => {
//   const message = formatWaterLevelMessage(tankInfo, 'very low');
//   sendNotification(fcmToken, message);
// });

// eventEmitter.on('sendCriticalLowWaterNotification', async (fcmToken, tankInfo) => {
//   const message = formatWaterLevelMessage(tankInfo, 'critically low');
//   sendNotification(fcmToken, message);
// });

// const formatWaterLevelMessage = (tankInfo, levelType) => {
//   const tankName = tankInfo.tankName;
//   const tankLocation = tankInfo.tankLocation;
//   const waterLevel = parseInt(tankInfo.waterlevel, 10);
//   const capacity = parseInt(tankInfo.capacity, 10);
//   const volumeInLitres = (capacity * waterLevel) / 100; // assuming the capacity is in litres

//   let levelDescription = '';
//   if (levelType === 'low') {
//     levelDescription = `${waterLevel}% (${volumeInLitres.toFixed(2)} L)`;
//   } else if (levelType === 'very low') {
//     levelDescription = `${waterLevel}% (${volumeInLitres.toFixed(2)} L)`;
//   } else if (levelType === 'critically low') {
//     levelDescription = `${waterLevel}% (${volumeInLitres.toFixed(2)} L)`;
//   }

//   return `Water level in '${tankName}', located at '${tankLocation}', type of water: ${tankInfo.waterType} is ${levelType} at ${levelDescription}. Action: start motor now.`;
// };

// Emit low water level event with motorId
// eventEmitter.on('lowWaterLevel', async (fcmTokens, timestamp, motorId, waterLevel) => {
//   await sendNotification(fcmTokens, 'Low Water Level', `Motor ID: ${motorId}, water level dropped below 20% at ${timestamp}. Current Water Level: ${waterLevel} Ltrs`);
// });

eventEmitter.on('sendHighWaterNotification', async (fcmTokens, tankInfo, startTime, stopTime) => {
  const message = `Attention: Water level in '${tankInfo.tankName}' located at '${tankInfo.tankLocation}' is high at ${tankInfo.waterLevel}% (${tankInfo.volumeInLitres} L). Please stop the motor. Motor running from ${startTime} to ${stopTime}.`;
  await sendNotification(fcmTokens, 'High Water Level', message, 'Stop Motor');
});

// Event listener for very high water level notification
eventEmitter.on('sendVeryHighWaterNotification', async (fcmTokens, tankInfo, startTime, stopTime) => {
  const message = `Attention: Water level in '${tankInfo.tankName}' located at '${tankInfo.tankLocation}' is very high at ${tankInfo.waterLevel}% (${tankInfo.volumeInLitres} L). Please stop the motor. Motor running from ${startTime} to ${stopTime}.`;
  await sendNotification(fcmTokens, 'Very High Water Level', message, 'Stop Motor');
});

// Event listener for critically high water level notification
eventEmitter.on('sendCriticalHighWaterNotification', async (fcmTokens, tankInfo, startTime, stopTime) => {
  const message = `Attention: Water level in '${tankInfo.tankName}' located at '${tankInfo.tankLocation}' is critically high at ${tankInfo.waterLevel}% (${tankInfo.volumeInLitres} L). Water may overflow. Please stop the motor. Motor running from ${startTime} to ${stopTime}.`;
  await sendNotification(fcmTokens, 'Critical High Water Level', message, 'Stop Motor');
});
// Emit high water level event with motorId
// eventEmitter.on('highWaterLevel', async (fcmTokens, timestamp, motorId, waterLevel) => {
//   await sendNotification(fcmTokens, 'High Water Level', `Motor ID: ${motorId}, water level reached above 90% at ${timestamp}. Current Water Level: ${waterLevel} Ltrs`);
// });

eventEmitter.on('sendThresholdTimeNotification', async (fcmTokens, message) => {
  try {
    await sendNotification(fcmTokens, 'Threshold Time Reached', message, 'Motor Alert');
    console.log("Threshold time notification sent successfully.");
  } catch (error) {
    console.error("Error sending threshold time notification:", error);
  }
});

// eventEmitter.on(
//   'sendMotorStartNotification',
//   async (fcmTokens, motorId, waterLevel, blockName, tankName, motorOnType, stopCriteria, manual_threshold_time) => {
//     try {
//       // Get the latest timestamp
//       const startTime = new Date().toLocaleString('en-IN', { timeZone: 'Asia/Kolkata' });

//       // Retrieve the user information
//       const users = await User.find({ fcmIds: { $in: fcmTokens } });
//       const userNames = users.map(user => user.username).join(', ');
//       const startMethod = motorOnType.toUpperCase() === "Forced Manual";

//       // Prepare the message
//       const message =
//         `🚰 Tank Name: '${tankName}'\n` +
//         `🕒 Pump started at: '${startTime}'\n` +
//         `👤 Initiated by: ${userNames}\n` +
//         `🔄 Pump started by: '${startMethod}'`;

//       // Send the notification
//       await sendNotification(fcmTokens, 'Motor Started 🚀', message);
//       console.log('Motor start notification sent successfully!');
//     } catch (error) {
//       console.error('Error in sendMotorStartNotification event:', error);
//     }
//   }
// );

eventEmitter.on(
  'sendMotorStartNotification',
  async (
    fcmTokens,
    blockName,
    tankName,
    motorOnType,
    stopCriteria,
    typeOfWater,
    highThreshold // Add the high threshold as a parameter
  ) => {
    try {
      // Get the latest timestamp
      const currentDateTime = new Date();
      const startTime = currentDateTime.toLocaleString('en-IN', { timeZone: 'Asia/Kolkata' });
      const formattedDate = currentDateTime.toLocaleDateString('en-IN', { timeZone: 'Asia/Kolkata' });
      const formattedTime = currentDateTime.toLocaleTimeString('en-IN', { timeZone: 'Asia/Kolkata' });

      // Retrieve the user information
      const users = await User.find({ fcmIds: { $in: fcmTokens } });
      const userNames = users.map(user => user.username).join(', ');

      // Determine the pump initiation method
      const startMethod = motorOnType ===  "Forced Manual" ? "Physically" : "Manually"

      // Dynamically generate the motor name
      const motorName = `${tankName}-${blockName}-${typeOfWater}`;

      // Determine the stop condition message
      let stopConditionMessage = "";
      if (stopCriteria === "manual") {
        stopConditionMessage = `Will stop at Manually \n`;
      } else if (stopCriteria === "highThreshold") {
        stopConditionMessage = `🚨 Pump will stop when the water level reaches the high threshold of ${highThreshold}%.\n`;
      }

      // Prepare the notification message
      const message =
        `🚰 Motor Name: ${motorName}\n` +
        `🚰 Tank Name: '${tankName}'\n` +
        `🏢 Block Name: '${blockName}'\n` +
        `👤 Started by: ${userNames}\n` +
        `📱 Mode: '${startMethod}'\n` +
        `🕒 Pump started at: ${startTime} (Time: ${formattedTime} on ${formattedDate})\n` +
        stopConditionMessage; // Add only the relevant stop condition

      // Send the notification
      await sendNotification(fcmTokens, 'Motor Started 🚀', message);
      console.log('Motor start notification with stop criteria sent successfully!');
    } catch (error) {
      console.error('Error in sendMotorStartNotification event:', error);
    }
  }
);


// eventEmitter.on(
//   'sendMotorStartNotification',
//   async (fcmTokens, motorId, waterLevel, blockName, tankName, motorOnType, stopCriteria, manual_threshold_time, typeOfWater) => {
//     try {
//       // Get the latest timestamp
//       const currentDateTime = new Date();
//       const startTime = currentDateTime.toLocaleString('en-IN', { timeZone: 'Asia/Kolkata' });
//       const formattedDate = currentDateTime.toLocaleDateString('en-IN', { timeZone: 'Asia/Kolkata' });
//       const formattedTime = currentDateTime.toLocaleTimeString('en-IN', { timeZone: 'Asia/Kolkata' });

//       // Retrieve the user information
//       const users = await User.find({ fcmIds: { $in: fcmTokens } });
//       const userNames = users.map(user => user.username).join(', ');
      
//       // Determine the pump initiation method
//       const startMethod = motorOnType === "Mobile APP" ? "Mobile APP" : "Manual";

//       // Dynamically generate the motor name
//       const motorName = `${tankName}-${blockName}-${typeOfWater}`;

//       // Prepare the notification message
//       const message =
//         `🚰 Motor Name: '${motorName}'\n` +
//         `🚰 Tank Name: '${tankName}'\n` +
//         `🏢 Block Name: '${blockName}'\n` +
//         `💧 Water Level: '${waterLevel}%'\n` +
//         `👤 Initiated by: ${userNames}\n` +
//         `📱 Pump started by: '${startMethod}'\n` +
//         `🕒 Start Time: '${startTime}'\n` +
//         `⏳ Will stop after: '${manual_threshold_time}' mins\n` +
//         `📅 Date: '${formattedDate}'\n` +
//         `⏰ Time: '${formattedTime}'`;

//       // Send the notification
//       await sendNotification(fcmTokens, 'Motor Started 🚀', message);
//       console.log('Motor start notification sent successfully!');
//     } catch (error) {
//       console.error('Error in sendMotorStartNotification event:', error);
//     }
//   }
// );


// eventEmitter.on(
//   'sendMotorStopNotification',
//   async (fcmTokens, motorId, waterLevel, blockName, tankName, motorOnType) => {
//     try {
//       // Get the latest timestamp
//       const stopTime = new Date().toLocaleString('en-IN', { timeZone: 'Asia/Kolkata' });

//       // Retrieve the user information
//       const users = await User.find({ fcmIds: { $in: fcmTokens } });
//       const userNames = users.map(user => user.username).join(', ');
//       const stopMethod = motorOnType.toUpperCase() === "Forced Manual";

//       // Prepare the message
//       const message =
//         `🚰 Tank Name: '${tankName}'\n` +
//         `🕒 Pump stopped at: '${stopTime}'\n` +
//         `👤 Initiated by: ${userNames}\n` +
//         `🔄 Pump stopped by: '${stopMethod}'\n`;

//       // Send the notification
//       await sendNotification(fcmTokens, 'Motor Stopped 🛑', message);
//       console.log('Motor stop notification sent successfully!');
//     } catch (error) {
//       console.error('Error in sendMotorStopNotification event:', error);
//     }
//   }
// );

eventEmitter.on(
  'sendMotorStopNotification',
  async (
    fcmTokens,
    blockName,
    tankName,
    motorOnType,
    typeOfWater
  ) => {
    try {
      // Get the latest timestamp
      const currentDateTime = new Date();
      const stopTime = currentDateTime.toLocaleString('en-IN', { timeZone: 'Asia/Kolkata' });
      const formattedDate = currentDateTime.toLocaleDateString('en-IN', { timeZone: 'Asia/Kolkata' });
      const formattedTime = currentDateTime.toLocaleTimeString('en-IN', { timeZone: 'Asia/Kolkata' });

      // Retrieve the user information
      const users = await User.find({ fcmIds: { $in: fcmTokens } });
      const userNames = users.map(user => user.username).join(', ');

      // Determine the pump stop method
      const stopMethod = motorOnType === "Forced Manual" ? "Physically" : "Manually";

      // Dynamically generate the motor name
      const motorName = `${tankName}-${blockName}-${typeOfWater}`;
  // Determine the stop condition message
        let stopConditionMessage = "";
        if (stopCriteria === "manual") {
          stopConditionMessage = `Stopped at Manually \n`;
        } else if (stopCriteria === "highThreshold") {
          stopConditionMessage = `🚨 Pump will stop when the water level reaches the high threshold of ${highThreshold}%.\n`;
        }
      // Prepare the notification message
      const message =
        `🚰 Motor Name: ${motorName}\n` +
        `🚰 Tank Name: '${tankName}'\n` +
        `🏢 Block Name: '${blockName}'\n` +
        `📱 Mode: '${stopMethod}'\n` +
        `🕒 Pump stopped at: ${stopTime} (Time: ${formattedTime} on ${formattedDate})\n` +
        stopConditionMessage;

      // Send the notification
      await sendNotification(fcmTokens, 'Motor Stopped 🛑', message);
      console.log('Motor stop notification sent successfully!');
    } catch (error) {
      console.error('Error in sendMotorStopNotification event:', error);
    }
  }
);

eventEmitter.on('sendLowWaterNotification', (fcmTokens, message) => {
  const notificationMessage = `Warning: Water level is low in the tank. 
  Tank Name: ${tankName}, 
  Location: ${receiverTank.location}, 
  Type of Water: ${receiverTank.typeOfWater}, 
  Current Water Level: ${currentWaterLevel} liters (${currentWaterPercentage.toFixed(2)}%), 
  Date & Time: ${new Date().toLocaleString()}`;
  
  // Send notifications using the provided FCM tokens
  sendNotification(fcmTokens, notificationMessage);
});

eventEmitter.on('sendCriticalLowWaterNotification', (fcmTokens, message) => {
  const notificationMessage = `Critical Alert: Water level is critically low in the tank. 
  Tank Name: ${tankName}, 
  Location: ${receiverTank.location}, 
  Type of Water: ${receiverTank.typeOfWater}, 
  Current Water Level: ${currentWaterLevel} liters (${currentWaterPercentage.toFixed(2)}%), 
  Date & Time: ${new Date().toLocaleString()}`;
  
  // Send notifications using the provided FCM tokens
  sendNotification(fcmTokens, notificationMessage);
});



// eventEmitter.on('sendMotorStartNotification', async (fcmTokens, message) => {
//   try {
//     await  sendNotification(fcmTokens, "Motor Started", message);
//     console.log("Manual method time notification sent successfully.");
//   } catch (error) {
//     console.error("Error sending thresmanual method time notification:", error);
//   }
// });

// eventEmitter.on('sendMotorStopNotification', async (fcmTokens, message) => {
//   try {
//     await  sendNotification(fcmTokens, "Motor Stopped", message);
//     console.log("Manual method time notification sent successfully.");
//   } catch (error) {
//     console.error("Error sending thresmanual method time notification:", error);
//   }
// });



// Function to emit events with timestamps
const emitWithTimestamp = (eventName, fcmTokens, motorId, waterLevel) => {
  const timestamp = moment().format('HH:mm:ss YYYY-MM-DD ');
  eventEmitter.emit(eventName, fcmTokens, timestamp, motorId, waterLevel);
};


// const sendNotification = async (fcmTokens, title, body) => {
//   if (!Array.isArray(fcmTokens) || fcmTokens.length === 0) {
//     console.error('No FCM tokens provided.');
//     return;
//   }

//   for (const token of fcmTokens) {
//     const message = {
//       token: token, 
//       notification: {
//         title: title,
//         body: body,
//       },
//       data: {
//         target: 'tank_levels', 
//       },
//     };

//     try {
//       const response = await admin.messaging().send(message); // Send each message individually
//       console.log('Notification sent successfully:', response);
//     } catch (error) {
//       console.error(`Failed to send notification to token ${token}:`, error);
//     }
//   }
// };

const sendNotification = async (fcmIds, title, body) => {
  try {
    if (!fcmIds || fcmIds.length === 0) {
      throw new Error('No FCM tokens provided.');
    }

    const flatTokens = fcmIds.flat();
    if (flatTokens.length === 0) {
      throw new Error('Flattened FCM token list is empty.');
    }

    // Iterate over each token and send individually
    const promises = flatTokens.map(async (token) => {
      try {
        const response = await admin.messaging().send({
          notification: { title, body },
          token,
          data: {
            'target': '/screen',  
          },
        });
        console.log(`Notification sent successfully to token: ${token}`, response);
      } catch (error) {
        console.error(`Failed to send notification to token: ${token}`, error);
        // Check for specific error indicating an invalid token
        if (error.code === 'messaging/registration-token-not-registered') {
          // Remove the invalid token from the database
          await User.updateOne(
            { fcmIds: token }, // Ensure you're targeting the right user with the invalid token
            { $pull: { fcmIds: token } } // Remove the invalid token
          );
          console.log(`Removed invalid token: ${token}`);
        }
      }
    });

    await Promise.all(promises);
  } catch (error) {
    console.error('Error sending notifications:', error);
  }
};






// const sendPushNotification = async (registrationToken, title, body) => {
//   const message = {
//     notification: {
//       title: title,
//       body: body,
//     },
//     data: {
//       title: title,
//       body: body,
//     },
//   };

//   const options = {
//     priority: "high",
//     timeToLive: 60 * 60 * 24, 
//   };

//   try {
//     const response = await admin.messaging().sendToDevice(registrationToken, message, options);
//     console.log('FCM response:', response); // Log the FCM response
//     return response; // Return the FCM response object
//   } catch (error) {
//     console.error('FCM error:', error);
//     throw error; // Throw the error to handle it further up the call stack
//   }
// };

exports. publishMotorStopStatus = async (motor_id, motor_stop_status) => {
  const payload = {
    topic: 'operation',
    object: {
      'motor-id': motor_id,
      control: motor_stop_status
    }
  };
  console.log("enetred publish")
  console.log(payload)
  client.publish('water/operation', JSON.stringify(payload));
};

const stat_stop_intervals = {};
// exports.motorAction = async (req, reply) => {
//   try {
//     const customerId = req.params.customerId;
//     const action = req.body.action;
//     const motorId = req.body.motor_id;
//     const start_instance_id = req.body.start_instance_id
//     console.log(req.body.startTime)
//     // Ensure motor_id is provided
//     if (!motorId) {
//       throw new Error("Motor ID is required.");
//     }

//     const users = await User.find({ customerId: customerId });
//     const fcmToken = users.map(user => user.fcmId).filter(fcmId => fcmId);
//     console.log(fcmToken)

//     // Determine the motor stop status based on the action
//     let motorStopStatus;
//     if (action === "start") {
//       motorStopStatus = "2"; // If action is start, set stop status to "2"
//       // eventEmitter.emit('motorStart', fcmToken); // Emit motor start event
//       emitWithTimestamp('motorStart', fcmToken); // Emit motor start event with timestamp
//       console.log(      eventEmitter.emit('motorStart', fcmToken))
//     } else if (action === "stop") {
//       motorStopStatus = "1"; // If action is stop, set stop status to "1"
//       // eventEmitter.emit('motorStop', fcmToken); // Emit motor stop event
//       emitWithTimestamp('motorStop', fcmToken); // Emit motor stop event with timestamp
//     } else {
//       throw new Error("Invalid action provided.");
//     }

//     // Update the motor stop status immediately if action is stop
//     if (action === "stop") {
//       // Update the motor stop status and other fields
//       await Tank.updateOne(
//         { customerId, "connections.inputConnections.motor_id": motorId },
//         { 
//           $set: { 
//             "connections.inputConnections.$.motor_stop_status": "1",
//             "connections.inputConnections.$.stopTime": req.body.stopTime,
//             "connections.inputConnections.$.threshold_type": null,
//             "connections.inputConnections.$.manual_threshold_time": null,
//             "connections.inputConnections.$.manual_threshold_percentage": null
//           }
//         }
//       );

//       reply.code(200).send({ message: "Motor stopped successfully." });

//       // Perform stop operations in the background
//       (async () => {
//         await delay(300000);

//         // Update the existing motor data entry with stop details
//         const motorData = await MotorData.findOne({ customerId, motor_id: motorId, start_instance_id: start_instance_id });
//         if (motorData) {
//           const receiverTank = await Tank.findOne({ customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() });
//           const receiverFinalWaterLevel = parseInt(receiverTank.waterlevel, 10);
//           const quantityDelivered = receiverFinalWaterLevel - parseInt(motorData.receiverInitialwaterlevel, 10);
//           const water_pumped_till_now = parseInt(receiverTank.total_water_added_from_midnight, 10);
//           const totalwaterpumped = quantityDelivered + water_pumped_till_now;
//           await Tank.findOneAndUpdate(
//             { customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() },
//             { $set: { total_water_added_from_midnight: totalwaterpumped } }
//           );

//           await MotorData.updateOne(
//             { customerId, motor_id: motorId, start_instance_id: start_instance_id },
//             { 
//               $set: { 
//                 stopTime: req.body.stopTime,
//                 receiverfinalwaterlevel: receiverFinalWaterLevel.toString(),
//                 quantity_delivered: quantityDelivered.toString()
//               }
//             }
//           );

//         }
//       })();

//       // Return here to ensure the rest of the code is not executed for the stop action
//       return;
//     } else {
//       // Update the motor stop status to "2" for start action
//       await Tank.updateOne(
//         { customerId, "connections.inputConnections.motor_id": motorId },
//         { $set: { "connections.inputConnections.$.motor_stop_status": "2" } }
//       );
//     }

//     // Check threshold settings if action is start
//     if (action === "start") {
//       if (req.body.threshold_type === "time") {
//         // If threshold type is time, update threshold time
//         // await Tank.updateOne(
//         //   { customerId, "connections.inputConnections.motor_id": motorId },
//         //   { $set: { "connections.inputConnections.$.manual_threshold_time": req.body.manual_threshold_time,startTime:req.body.startTime } }
//         // );
//         const receiver_tank_info7 = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() });

//         const newMotorData = new MotorData({
//           customerId: customerId,
//           motor_id: motorId,
//           start_instance_id: start_instance_id,
//           supplierTank: req.body.from,
//           receiverTank: req.body.to,
//           supplier_type: req.body.from_type,
//           receiver_type: req.body.to_type,
//           startTime: req.body.startTime,
//           receiverInitialwaterlevel:parseInt(receiver_tank_info7.waterlevel, 10)
//         });
//         await newMotorData.save();

//         for await (const tank of Tank.find({  "connections.inputConnections.motor_id": motorId })) {
//           const index = tank.connections.inputConnections.findIndex(connection => connection.motor_id === motorId);
//           if (index !== -1) {
//             await Tank.updateOne(
//               { customerId, "connections.inputConnections.motor_id": motorId },
//               { $set: { [`connections.inputConnections.${index}.manual_threshold_time`]: req.body.manual_threshold_time, [`connections.inputConnections.${index}.startTime`]: req.body.startTime,[`connections.inputConnections.${index}.start_instance_id`]: start_instance_id } }
//             );
//           }
//         }
        

//         // Start monitoring water level based on threshold time
//         const thresholdTime = moment().add(req.body.manual_threshold_time, 'minutes').toDate();
//         const intervalId = setInterval(async () => {
//           const splr_tank_info3 = await Tank.findOne({ customerId, tankName: req.body.from, tankLocation: req.body.from_type.toLowerCase() });
//           const splr_tank_info3_waterlevel = parseInt(splr_tank_info3.waterlevel, 10);
//           //console.log(splr_tank_info3_waterlevel,"splr_tank_info3_waterlevel")
//           const splr_tank_info3_capacity = parseInt(splr_tank_info3.capacity.replace(/,/g, ''), 10);
//          // const splr_tank_info3_capacity = parseInt(splr_tank_info3.capacity, 10);
//          // console.log(splr_tank_info3.capacity,splr_tank_info3_capacity,"splr_tank_info3_capacity")
//           const splr_tank_info3_percentage = (splr_tank_info3_waterlevel / splr_tank_info3_capacity) * 100;
//          // console.log(splr_tank_info3_percentage, "percentage for less than 20");

//           if (new Date() >= thresholdTime || splr_tank_info3_percentage <= 20) {
//             console.log(splr_tank_info3_percentage,)
//             await Tank.updateOne(
//               { customerId, "connections.inputConnections.motor_id": motorId },
//               {
//                 $set: {
//                   "connections.inputConnections.$.motor_stop_status": "1",
//                   "connections.inputConnections.$.threshold_type": null,
//                   "connections.inputConnections.$.manual_threshold_time": null,
//                   "connections.inputConnections.$.manual_threshold_percentage": null
//                 }
//               }
//             );
//             clearInterval(intervalId);

//             await delay(300000);

//             const motorData = await MotorData.findOne({ customerId, motor_id: motorId, start_instance_id: start_instance_id });
//             if (motorData) {
//               const receiverTank = await Tank.findOne({ customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() });
//               const receiverFinalWaterLevel = parseInt(receiverTank.waterlevel, 10);
//               const quantityDelivered = receiverFinalWaterLevel - parseInt(motorData.receiverInitialwaterlevel, 10);
//               const water_pumped_till_now = parseInt(receiverTank.total_water_added_from_midnight, 10);
//               const totalwaterpumped = quantityDelivered + water_pumped_till_now
//               await  Tank.findOneAndUpdate({customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase()}, { $set: { total_water_added_from_midnight: totalwaterpumped } })

//               const stopTime = formatDate(new Date());

//               await MotorData.updateOne(
//                 { customerId, motor_id: motorId, start_instance_id: start_instance_id },
//                 {
//                   $set: {
//                     stopTime:stopTime,
//                     receiverfinalwaterlevel: receiverFinalWaterLevel.toString(),
//                     quantity_delivered: quantityDelivered.toString()
//                   }
//                 }
//               );
//             }
//           }
//         }, 60000);
//       } else if (req.body.threshold_type === "litres") {
//         console.log("entered litres")
//         const receiver_tank_info7 = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() });

//         const newMotorData = new MotorData({
//           customerId: customerId,
//           motor_id: motorId,
//           start_instance_id: start_instance_id,
//           supplierTank: req.body.from,
//           receiverTank: req.body.to,
//           supplier_type: req.body.from_type,
//           receiver_type: req.body.to_type,
//           startTime: req.body.startTime,
//           receiverInitialwaterlevel:parseInt(receiver_tank_info7.waterlevel, 10)
//         });
//         await newMotorData.save();
//         // If threshold type is percentage, calculate percentage threshold
//         const receiver_tank_info = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() });
//         const supplier_tank_info = await Tank.findOne({ customerId, tankName: req.body.from, tankLocation: req.body.from_type.toLowerCase() });
//         if (!receiver_tank_info) {
//           throw new Error("Receiver tank not found.");
//         }
//         if (!supplier_tank_info) {
//           throw new Error("Supplierr tank not found.");
//         }
//         const supplier_capacity =  parseInt(supplier_tank_info.capacity, 10);
//         const supplier_waterLevel = parseInt(supplier_tank_info.waterlevel, 10); 

//         const capacity = parseInt(receiver_tank_info.capacity, 10);
//         const waterLevel = parseInt(receiver_tank_info.waterlevel, 10); 
//         const desired_percentage = parseInt(req.body.manual_threshold_litres.replace(/,/g, ''), 10);

//         console.log(desired_percentage)
//         const threshold_water_level = waterLevel+desired_percentage;

//         const supplier_threshold = supplier_waterLevel-desired_percentage
//         console.log(supplier_threshold,"supplier_threshold")

//         for await (const tank of Tank.find({  "connections.inputConnections.motor_id": motorId })) {
//           const index = tank.connections.inputConnections.findIndex(connection => connection.motor_id === motorId);
//           if (index !== -1) {
//             await Tank.updateOne(
//               { customerId, "connections.inputConnections.motor_id": motorId },
//               { $set: { [`connections.inputConnections.${index}.manual_threshold_percentage`]: supplier_threshold.toString(), [`connections.inputConnections.${index}.startTime`]: req.body.startTime } }
//             );
//           }
//         }
        


//         // Update water level threshold
       

//         // Start monitoring water level based on threshold percentage
//         const intervalId = setInterval(async () => {
//           // Check if water level has reached the threshold percentage
//           const supplier_tank_info1 = await Tank.findOne({ customerId, tankName: req.body.from, tankLocation: req.body.from_type.toLowerCase() });
//           const current_water_level = parseInt(supplier_tank_info1.waterlevel, 10);
//           if (current_water_level <= supplier_threshold) {
//             // Stop the motor pump
//             await Tank.updateOne(
//               { customerId, "connections.inputConnections.motor_id": motorId },
//               { 
//                 $set: { 
//                   "connections.inputConnections.$.motor_stop_status": "1",
                
//                   "connections.inputConnections.$.threshold_type": null,
//                   "connections.inputConnections.$.manual_threshold_time": null,
//                   "connections.inputConnections.$.manual_threshold_percentage": null
//                 }
//               }
//             );
//             clearInterval(intervalId); // Stop monitoring water level
//             await delay(300000);

//             const motorData = await MotorData.findOne({ customerId, motor_id: motorId, start_instance_id: start_instance_id });
//             if (motorData) {
//               const receiverTank = await Tank.findOne({ customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() });
//               const receiverFinalWaterLevel = parseInt(receiverTank.waterlevel, 10);
//               const quantityDelivered = receiverFinalWaterLevel - parseInt(motorData.receiverInitialwaterlevel, 10);


//               const stopTime = formatDate(new Date());

//               await MotorData.updateOne(
//                 { customerId, motor_id: motorId, start_instance_id: start_instance_id },
//                 {
//                   $set: {
//                     stopTime:stopTime,
//                     receiverfinalwaterlevel: receiverFinalWaterLevel.toString(),
//                     quantity_delivered: quantityDelivered.toString()
//                   }
//                 }
//               );
//             }
//           }
//         }, 20000); // Check water level every minute
//       }
//     }

//     // Respond with success message
//     reply.code(200).send({ message: `Motor ${action === "start" ? "started" : "stopped"} successfully.` });
//   } catch (err) {
//     // Handle errors
//     throw boom.boomify(err);
//   }
// };

const notificationSentStatus = {
  motorStart: false,
  motorStop: false,
  lowWater: false,
  veryLowWater: false,
  criticallyLowWater: false,
  highWater: false,
  veryHighWater: false,
  criticallyHighWater: false,
};

let waterLevelCheckInterval; // To hold the interval ID

const checkWaterLevel = async (customerId, motorId, fcmToken, receiverTank) => {
  const currentWaterLevel = parseInt(receiverTank.waterlevel, 10);
  const tankCapacity = parseInt(receiverTank.capacity.replace(/,/g, ''), 10);
  const currentWaterPercentage = (currentWaterLevel / tankCapacity) * 100;

  // Check for low water levels
  if (currentWaterPercentage <= 20 && !notificationSentStatus.lowWater) {
    eventEmitter.emit('sendLowWaterNotification', fcmToken, `Water level has dropped below 20%.`);
    notificationSentStatus.lowWater = true; 
  }

  // Check for critically low water levels
  if (currentWaterPercentage <= 10 && !notificationSentStatus.criticallyLowWater) {
    eventEmitter.emit('sendCriticalLowWaterNotification', fcmToken, `Water level has dropped below 10%.`);
    notificationSentStatus.criticallyLowWater = true; 
  }
};
// const checkWaterLevelsAndNotify = async (customerId, tankName, tankLocation, fcmTokens) => {
//   try {
//     // Fetch the tank details from the database
//     const tank = await Tank.findOne({ customerId, tankName, tankLocation });

//     if (!tank) {
//       console.error(`Tank not found: ${tankName} at location ${tankLocation}`);
//       return;
//     }

//     // Extract the current water level and capacity
//     const currentWaterLevel = parseInt(tank.waterlevel, 10);
//     const capacity = parseInt(tank.capacity.replace(/,/g, ''), 10);

//     // Calculate the water level percentage
//     const waterLevelPercentage = (currentWaterLevel / capacity) * 100;

//     // Thresholds for notifications
//     const thresholds = {
//       criticallyLow: 10,
//       veryLow: 20,
//       low: 30,
//       high: 70,
//       veryHigh: 80,
//       criticallyHigh: 85,
//     };

//     // Check water levels and send notifications
//     if (waterLevelPercentage <= thresholds.criticallyLow && !notificationSentStatus.criticallyLowWater) {
//       eventEmitter.emit('sendCriticalLowWaterNotification', fcmTokens, tank);
//       notificationSentStatus.criticallyLowWater = true;
//       await Tank.updateOne({ customerId, tankName: tank.tankName }, { $set: { notificationSentCritical: true } });
//     } else if (waterLevelPercentage <= thresholds.veryLow && !notificationSentStatus.veryLowWater) {
//       eventEmitter.emit('sendVeryLowWaterNotification', fcmTokens, tank);
//       notificationSentStatus.veryLowWater = true;
//       await Tank.updateOne({ customerId, tankName: tank.tankName }, { $set: { notificationSentVeryLow: true } });
//     } else if (waterLevelPercentage <= thresholds.low && !notificationSentStatus.lowWater) {
//       eventEmitter.emit('sendLowWaterNotification', fcmTokens, tank);
//       notificationSentStatus.lowWater = true;
//       await Tank.updateOne({ customerId, tankName: tank.tankName }, { $set: { notificationSentLow: true } });
//     }
//     // if (waterLevelPercentage <= thresholds.criticallyLow) {
//     //   eventEmitter.emit('sendCriticalLowWaterNotification', fcmTokens, tank);
//     //   await Tank.updateOne({ customerId, tankName: tank.tankName }, { $set: { notificationSentCritical: true } });
//     // } else if (waterLevelPercentage <= thresholds.veryLow) {
//     //   eventEmitter.emit('sendVeryLowWaterNotification', fcmTokens, tank);
//     //   await Tank.updateOne({ customerId, tankName: tank.tankName }, { $set: { notificationSentVeryLow: true } });
//     // } else if (waterLevelPercentage <= thresholds.low) {
//     //   eventEmitter.emit('sendLowWaterNotification', fcmTokens, tank);
//     //   await Tank.updateOne({ customerId, tankName: tank.tankName }, { $set: { notificationSentLow: true } });
//     // }
//     //  else if (waterLevelPercentage >= thresholds.criticallyHigh) {
//     //   eventEmitter.emit('sendCriticalHighWaterNotification', fcmTokens, tank);
//     //   await Tank.updateOne({ customerId, tankName: tank.tankName }, { $set: { notificationSentCriticalHigh: true } });
//     // } else if (waterLevelPercentage >= thresholds.veryHigh) {
//     //   eventEmitter.emit('sendVeryHighWaterNotification', fcmTokens, tank);
//     //   await Tank.updateOne({ customerId, tankName: tank.tankName }, { $set: { notificationSentVeryHigh: true } });
//     // } else if (waterLevelPercentage >= thresholds.high) {
//     //   eventEmitter.emit('sendHighWaterNotification', fcmTokens, tank);
//     //   await Tank.updateOne({ customerId, tankName: tank.tankName }, { $set: { notificationSentHigh: true } });
//     // }
//   } catch (error) {
//     console.error(`Error checking water levels for tank ${tankName}:`, error);
//   }
// };


const monitorWaterLevels = async () => {
  try {
    const tanks = await Tank.find({});

    // Iterate through each tank
    for (const tank of tanks) {
      // Fetch users associated with the customerId of the tank
      const users = await User.find({ customerId: tank.customerId });
      const fcmTokens = users
        .map(user => user.fcmIds)
        .filter(fcmIds => fcmIds)
        .flat(); // Flatten if there are multiple fcmIds for each user

      // Ensure that fcmTokens exist before proceeding
      if (fcmTokens.length > 0) {
        const customerId = tank.customerId;
        const tankName = tank.tankName;  // Assuming tank has a 'name' field
        const tankLocation = tank.tankLocation; // Assuming tank has a 'location' field

        // Call the function to check water levels and send notifications
        await checkWaterLevelsAndNotify(customerId, tankName, tankLocation, fcmTokens);
      } else {
        //console.log(`No FCM tokens found for customerId ${tank.customerId}`);
      }
    } 
  } catch (error) {
    console.error('Error monitoring water levels:', error);
  }
};

// Schedule the task to run every 30 minutes
setInterval(monitorWaterLevels, 30 * 60 * 1000);

const motorIntervals = {};
async function calculateTotalPumpedWater(customerId, motorId, start_instance_id) {
  const motorData = await MotorData.findOne({ customerId, motor_id: motorId, start_instance_id: start_instance_id });
  if (motorData) {
      const receiverTank = await Tank.findOne({ customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() });
      const receiverFinalWaterLevel = parseInt(receiverTank.waterlevel, 10);
      const quantityDelivered = receiverFinalWaterLevel - parseInt(motorData.receiverInitialwaterlevel, 10);
      const waterPumpedTillNow = parseInt(receiverTank.total_water_added_from_midnight, 10);
      return quantityDelivered + waterPumpedTillNow; // Total water pumped
  }
  return 0; // Return 0 if no data found
}
exports.motorAction = async (req, reply) => {
  try {
    const customerId = req.params.customerId;
    const action = req.body.action;
    const motorId = req.body.motor_id;
    const start_instance_id = req.body.start_instance_id;

    // Define thresholds for water levels
    const lowWaterThreshold = 5; // Low water level percentage threshold
    //const highWaterThreshold = 90; // High water level percentage threshold
    const highWaterThreshold = 70; // High water level percentage threshold
    const veryHighWaterThreshold = 80; // Very High water level percentage threshold
    const criticalHighWaterThreshold = 85; 
    // Ensure motor_id is provided
    if (!motorId) {
      throw new Error("Motor ID is required.");
    }

    // Get user FCM tokens
    const users = await User.find({ customerId });
    const fcmToken = users.map(user => user.fcmIds).filter(fcmIds => fcmIds);
    console.log(fcmToken)
    const receiverTank = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() });
    console.log(receiverTank)
    const currentWaterLevel = parseInt(receiverTank.waterlevel, 10);
    const waterLevelThresholds = { low: 30, veryLow: 20, criticallyLow: 10 };
    const typeOfWater = receiverTank.typeOfWater;
    console.log(typeOfWater,"typeOfWater")
  
    // Determine the motor stop status based on the action
    let motorStopStatus;
    const blockName = req.body.from || "Unknown Block"; // Provide a fallback if `from` is missing
    const tankName = req.body.to || "Unknown Tank"; // Provide a fallback if `to` is missing
    const stopTime = req.body.stopTime 
    const motorOnType = "manual";
   const  manual_threshold_time = req.body.manual_threshold_time;
   let hasNotifiedStart = false;
    let hasNotifiedStop = false;
    if (action === "start") {

      motorStopStatus = "2";
      const startTime = req.body.startTime;
     
      await Tank.updateOne(
        { customerId, "connections.inputConnections.motor_id": motorId },
        { $set: { "connections.inputConnections.$.motor_stop_status": motorStopStatus } }
      );

      const thresholdTimeMs = req.body.manual_threshold_time * 60 * 1000; // Convert minutes to milliseconds
      const stopCriteria =
        motorOnType === "time"
          ? `${req.body.manual_threshold_time} minutes`
          : `${req.body.manual_threshold_litres} litres`;

          // await checkWaterLevelsAndNotify(customerId, tankName, receiverTank.tankLocation, fcmToken);
  
      if (!notificationSentStatus.motorStart) {
        eventEmitter.emit(
          'motorStart', 
          fcmToken, 
          tankName, 
          blockName, 
          startTime, 
          "Mobile APP", 
          manual_threshold_time,
          typeOfWater
        );
       
        notificationSentStatus.motorStart = true; // Set flag to true to prevent duplicate notifications
      }
       // Start checking water level every 30 minutes
       if (!waterLevelCheckInterval) {
        waterLevelCheckInterval = setInterval(async () => {
          await checkWaterLevel(customerId, motorId, fcmToken, receiverTank);
        }, 30 * 60 * 1000); // 30 minutes
      }
      await Tank.updateOne(
        { customerId, "connections.inputConnections.motor_id": motorId },
        { $set: { "connections.inputConnections.$.motor_stop_status": "2",
        "connections.inputConnections.$.manual_threshold_time": manual_threshold_time,
        "connections.inputConnections.$.threshold_type": "time",
        "connections.inputConnections.$.motor_on_type": "manual" } }
      );
     
      reply.code(200).send({ message: "Motor started successfully." });

    } else if (action === "stop") {
      motorStopStatus = "1"; // If action is stop, set stop status to "1"
      
      if (!notificationSentStatus.motorStop) {

        // Emit motorStop event
        const totalWaterPumped = await calculateTotalPumpedWater(customerId, motorId, start_instance_id); // A function to calculate total water pumped
        eventEmitter.emit(
            'motorStop', 
            fcmToken,             
            tankName,            
            blockName,            
            stopTime,             
            "Mobile APP",               
            totalWaterPumped, // Include total water pumped
            typeOfWater           
        );
        notificationSentStatus.motorStop = true; // Set flag to true to prevent duplicate notifications
      }
      await Tank.updateOne(
        { customerId, "connections.inputConnections.motor_id": motorId },
        {
          $set: {
            "connections.inputConnections.$.motor_stop_status": "1",
            "connections.inputConnections.$.motor_on_type": motorOnType          }
        }
      );
     // Clear the interval when the motor is stopped
     if (waterLevelCheckInterval) {
      clearInterval(waterLevelCheckInterval);
      waterLevelCheckInterval = null; // Reset the interval ID
    }
    } else {
      throw new Error("Invalid action provided.");
    }

    // If action is stop, immediately update motor status and perform stop operations
    if (action === "stop") {
      console.log("enterted stop")
      await Tank.updateOne(
        { customerId, "connections.inputConnections.motor_id": motorId },
        { 
          $set: { 
            "connections.inputConnections.$.motor_stop_status": "1",
            "connections.inputConnections.$.motor_on_type": "manual",
            "connections.inputConnections.$.stopTime": req.body.stopTime,
            "connections.inputConnections.$.threshold_type": null,
            "connections.inputConnections.$.manual_threshold_time": null,
            "connections.inputConnections.$.manual_threshold_percentage": null
          }
        }
      );
      if (motorIntervals[motorId]) {
        console.log(motorIntervals[motorId],"deleted")
        clearInterval(motorIntervals[motorId]); // Clear the interval
        delete motorIntervals[motorId]; // Remove the interval from the object
      }
      this.publishMotorStopStatus(motorId, motorStopStatus);
     
      // Send immediate response to the client
      reply.code(200).send({ message: "Motor stopped successfully." });

      // Perform stop operations in the background
      (async () => {
        await delay(300000);

        const motorData = await MotorData.findOne({ customerId, motor_id: motorId, start_instance_id: start_instance_id });
        if (motorData) {
          const receiverTank = await Tank.findOne({ customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() });
          const receiverFinalWaterLevel = parseInt(receiverTank.waterlevel, 10);
          const quantityDelivered = receiverFinalWaterLevel - parseInt(motorData.receiverInitialwaterlevel, 10);
          const water_pumped_till_now = parseInt(receiverTank.total_water_added_from_midnight, 10);
          const totalwaterpumped = quantityDelivered + water_pumped_till_now;

          await Tank.findOneAndUpdate(
            { customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() },
            { $set: { total_water_added_from_midnight: totalwaterpumped } }
          );

          await MotorData.updateOne(
            { customerId, motor_id: motorId, start_instance_id: start_instance_id },
            { 
              $set: { 
                stopTime: req.body.stopTime,
                receiverfinalwaterlevel: receiverFinalWaterLevel.toString(),
                quantity_delivered: quantityDelivered.toString()
              }
            }
          );
        }
      })();

      return; // Return early to avoid executing the start logic
    } else {
      await Tank.updateOne(
        { customerId, "connections.inputConnections.motor_id": motorId },
        { $set: { "connections.inputConnections.$.motor_stop_status": "2" } }
      );
    }

    // Check threshold settings if action is start
    if (action === "start") {
      if (req.body.threshold_type === "time") {
        // Create a new MotorData entry
        const receiverTank = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() });
        const newMotorData = new MotorData({
          customerId,
          motor_id: motorId,
          start_instance_id: start_instance_id,
          supplierTank: req.body.from,
          receiverTank: req.body.to,
          supplier_type: req.body.from_type,
          receiver_type: req.body.to_type,
          startTime: req.body.startTime,
          receiverInitialwaterlevel: parseInt(receiverTank.waterlevel, 10)
        });
        await newMotorData.save();

        // Update the tank connections with start time and threshold time
        for await (const tank of Tank.find({ "connections.inputConnections.motor_id": motorId })) {
        this.publishMotorStopStatus(motorId, motorStopStatus);
        for await (const tank of Tank.find({  "connections.inputConnections.motor_id": motorId })) {
          const index = tank.connections.inputConnections.findIndex(connection => connection.motor_id === motorId);
          if (index !== -1) {
            await Tank.updateOne(
              { customerId, "connections.inputConnections.motor_id": motorId },
              { 
                $set: { 
                  [`connections.inputConnections.${index}.manual_threshold_time`]: req.body.manual_threshold_time,
                  [`connections.inputConnections.${index}.threshold_type`]: "time",
                  [`connections.inputConnections.${index}.startTime`]: req.body.startTime,
                  [`connections.inputConnections.${index}.start_instance_id`]: start_instance_id
                } 
              }
            );
          }
        }

        const thresholdTime = new Date(new Date().getTime() + req.body.manual_threshold_time * 60000);
        motorIntervals[motorId]  = setInterval(async () => {
          const supplierTank = await Tank.findOne({ customerId, tankName: req.body.from, tankLocation: req.body.from_type.toLowerCase() });
          const currentWaterLevel = parseInt(supplierTank.waterlevel, 10);
          const currentWaterPercentage = (currentWaterLevel / parseInt(supplierTank.capacity.replace(/,/g, ''), 10)) * 100;

          if (new Date() >= thresholdTime || currentWaterPercentage <= lowWaterThreshold) {
            console.log(new Date(),"new date")
            console.log(thresholdTime,"thresholdTime")
            console.log("motor stopping because it entered this condition")
            // Emit the threshold time notification
    eventEmitter.emit(
      "sendThresholdTimeNotification",
      fcmToken,
      `Motor has reached its time threshold of ${req.body.manual_threshold_time} minutes and will stop.`
    );

            await Tank.updateOne(
              { customerId, "connections.inputConnections.motor_id": motorId },
              { 
                $set: {
                  "connections.inputConnections.$.motor_stop_status": "1",
                  
                  "connections.inputConnections.$.threshold_type": null,
                  "connections.inputConnections.$.manual_threshold_time": null,
                  "connections.inputConnections.$.manual_threshold_percentage": null
                }
              }
            );
            // eventEmitter.emit('sendLowWaterNotification', fcmToken, receiverTank);
            // console.log(motorIntervals[motorId],"deleted automatically") // Emit low water level notification
            // clearInterval(motorIntervals[motorId]); // Clear interval
            // delete motorIntervals[motorId]; 

           // await checkWaterLevelsAndNotify(customerId, tankName, supplierTank.tankLocation, fcmToken);
            // if (currentWaterPercentage >= highWaterThreshold && !notificationSentStatus.highWater) {
            //   eventEmitter.emit('sendHighWaterNotification', fcmToken, `Water level has reached high levels.`);
            //   notificationSentStatus.highWater = true; // Set flag to true to prevent duplicate notifications
            // }
          
            // if (currentWaterPercentage >= veryHighWaterThreshold && !notificationSentStatus.veryHighWater) {
            //   eventEmitter.emit('sendVeryHighWaterNotification', fcmToken, `Water level has reached very high levels.`);
            //   notificationSentStatus.veryHighWater = true; // Set flag to true to prevent duplicate notifications
            // }
          
            // if (currentWaterPercentage >= criticalHighWaterThreshold && !notificationSentStatus.criticallyHighWater) {
            //   eventEmitter.emit('sendCriticalHighWaterNotification', fcmToken, `Water level has reached critically high levels.`);
            //   notificationSentStatus.criticallyHighWater = true; // Set flag to true to prevent duplicate notifications
            // }
            clearInterval(motorIntervals[motorId]); // Stop the motor if condition met
            delete motorIntervals[motorId]; // Remove from interval object
           
            this.publishMotorStopStatus(motorId, "1");
            await delay(300000);
            const motorData = await MotorData.findOne({ customerId, motor_id: motorId, start_instance_id: start_instance_id });
            if (motorData) {
              const receiverTank = await Tank.findOne({ customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() });
              const receiverFinalWaterLevel = parseInt(receiverTank.waterlevel, 10);
              const quantityDelivered = receiverFinalWaterLevel - parseInt(motorData.receiverInitialwaterlevel, 10);
              const water_pumped_till_now = parseInt(receiverTank.total_water_added_from_midnight, 10);
              const totalwaterpumped = quantityDelivered + water_pumped_till_now;

              await Tank.findOneAndUpdate(
                { customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() },
                { $set: { total_water_added_from_midnight: totalwaterpumped } }
              );

              await MotorData.updateOne(
                { customerId, motor_id: motorId, start_instance_id: start_instance_id },
                {
                  $set: {
                    stopTime: req.body.stopTime,
                    receiverfinalwaterlevel: receiverFinalWaterLevel.toString(),
                    quantity_delivered: quantityDelivered.toString()
                  }
                }
              );
            }
          }

          // Check for high water level and send notification
          // if (currentWaterPercentage >= highWaterThreshold) {
          //   // eventEmitter.emit('sendHighWaterNotification', fcmToken, receiverTank);
          //   await checkWaterLevelsAndNotify(customerId, tankName, supplierTank.tankLocation, fcmToken);

          // }

        }, 30000); // Check every minute
      }
      }else if (req.body.threshold_type === "litres") {
        console.log("entered litres")
        const receiver_tank_info7 = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() });
        const supplier_tank_info7 = await Tank.findOne({ customerId, tankName: req.body.from, tankLocation: req.body.from_type.toLowerCase() });

        const newMotorData = new MotorData({
          customerId: customerId,
          motor_id: motorId,
          start_instance_id: start_instance_id,
          supplierTank: req.body.from,
          receiverTank: req.body.to,
          supplier_type: req.body.from_type,
          receiver_type: req.body.to_type,
          startTime: req.body.startTime,
          receiverInitialwaterlevel:parseInt(receiver_tank_info7.waterlevel, 10),
          supplierInitialwaterlevel:parseInt(supplier_tank_info7.waterlevel, 10)
        });
        await newMotorData.save();
        // If threshold type is percentage, calculate percentage threshold
        const receiver_tank_info = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() });
        const supplier_tank_info = await Tank.findOne({ customerId, tankName: req.body.from, tankLocation: req.body.from_type.toLowerCase() });
        if (!receiver_tank_info) {
          throw new Error("Receiver tank not found.");
        }
        if (!supplier_tank_info) {
          throw new Error("Supplierr tank not found.");
        }
        const supplier_capacity =  parseInt(supplier_tank_info.capacity, 10);
        const supplier_waterLevel = parseInt(supplier_tank_info.waterlevel, 10); 

        const capacity = parseInt(receiver_tank_info.capacity, 10);
        const waterLevel = parseInt(receiver_tank_info.waterlevel, 10); 
        const desired_percentage = parseInt(req.body.manual_threshold_litres.replace(/,/g, ''), 10);

        console.log(desired_percentage)
        const threshold_water_level = waterLevel+desired_percentage;

        const supplier_threshold = supplier_waterLevel-desired_percentage
        console.log(supplier_threshold,"supplier_threshold")
        for await (const tank of Tank.find({ "connections.inputConnections.motor_id": motorId })) {
          this.publishMotorStopStatus(motorId, motorStopStatus);
        for await (const tank of Tank.find({  "connections.inputConnections.motor_id": motorId })) {
          const index = tank.connections.inputConnections.findIndex(connection => connection.motor_id === motorId);
          if (index !== -1) {
            await Tank.updateOne(
              { customerId, "connections.inputConnections.motor_id": motorId },
              { $set: { [`connections.inputConnections.${index}.manual_threshold_percentage`]: supplier_threshold.toString(), [`connections.inputConnections.${index}.startTime`]: req.body.startTime } }
            );
          }
        }
        


        // Update water level threshold
       

        // Start monitoring water level based on threshold percentage
        motorIntervals[motorId] = setInterval(async () => {
          // Check if water level has reached the threshold percentage
          const supplier_tank_info1 = await Tank.findOne({ customerId, tankName: req.body.from, tankLocation: req.body.from_type.toLowerCase() });
          const current_water_level = parseInt(supplier_tank_info1.waterlevel, 10);
          if (current_water_level <= supplier_threshold) {
            // Stop the motor pump
            await Tank.updateOne(
              { customerId, "connections.inputConnections.motor_id": motorId },
              { 
                $set: { 
                  "connections.inputConnections.$.motor_stop_status": "1",
                
                  "connections.inputConnections.$.threshold_type": null,
                  "connections.inputConnections.$.manual_threshold_time": null,
                  "connections.inputConnections.$.manual_threshold_percentage": null
                }
              }
            );
            clearInterval(motorIntervals[motorId]); // Clear interval
            delete motorIntervals[motorId]; 
           
            this.publishMotorStopStatus(motorId, "1");
            await delay(300000);

            const motorData = await MotorData.findOne({ customerId, motor_id: motorId, start_instance_id: start_instance_id });
            if (motorData) {
              const receiverTank = await Tank.findOne({ customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() });
              const receiverFinalWaterLevel = parseInt(receiverTank.waterlevel, 10);
              const quantityDelivered = receiverFinalWaterLevel - parseInt(motorData.receiverInitialwaterlevel, 10);


              const stopTime = formatDate(new Date());

              await MotorData.updateOne(
                { customerId, motor_id: motorId, start_instance_id: start_instance_id },
                {
                  $set: {
                    stopTime:stopTime,
                    receiverfinalwaterlevel: receiverFinalWaterLevel.toString(),
                    quantity_delivered: quantityDelivered.toString()
                  }
                }
              );
            }
          }
        }, 20000); 
      }
      
    }


    }
    // Respond with success message
    reply.code(200).send({ message: `Motor ${action === "start" ? "started" : "stopped"} successfully.` });

  } catch (err) {
    throw boom.boomify(err);
  }
};



// exports.motorAction = async (req, reply) => {
//   try {
//     const customerId = req.params.customerId;
//     const action = req.body.action;
//     const motorId = req.body.motor_id;
//     const start_instance_id = req.body.start_instance_id
//     console.log(req.body.startTime)
//     // Ensure motor_id is provided
//     if (!motorId) {
//       throw new Error("Motor ID is required.");
//     }

//     // Determine the motor stop status based on the action
//     let motorStopStatus;
//     if (action === "start") {
//       motorStopStatus = "2"; // If action is start, set stop status to "2"
//     } else if (action === "stop") {
//       motorStopStatus = "1"; // If action is stop, set stop status to "1"
//     } else {
//       throw new Error("Invalid action provided.");
//     }

//     // Update the motor stop status immediately if action is stop
//     if (action === "stop") {
//       // Update the motor stop status and other fields
//       await Tank.updateOne(
//         { customerId, "connections.inputConnections.motor_id": motorId },
//         { 
//           $set: { 
//             "connections.inputConnections.$.motor_stop_status": "1",
//             "connections.inputConnections.$.stopTime": req.body.stopTime,
//             "connections.inputConnections.$.threshold_type": null,
//             "connections.inputConnections.$.manual_threshold_time": null,
//             "connections.inputConnections.$.manual_threshold_percentage": null
//           }
//         }
//       );

//       // Send immediate response to the client
//       reply.code(200).send({ message: "Motor stopped successfully." });

//       // Perform stop operations in the background
//       (async () => {
//         await delay(300000);

//         // Update the existing motor data entry with stop details
//         const motorData = await MotorData.findOne({ customerId, motor_id: motorId, start_instance_id: start_instance_id });
//         if (motorData) {
//           const receiverTank = await Tank.findOne({ customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() });
//           const receiverFinalWaterLevel = parseInt(receiverTank.waterlevel, 10);
//           const quantityDelivered = receiverFinalWaterLevel - parseInt(motorData.receiverInitialwaterlevel, 10);
//           const water_pumped_till_now = parseInt(receiverTank.total_water_added_from_midnight, 10);
//           const totalwaterpumped = quantityDelivered + water_pumped_till_now;
//           await Tank.findOneAndUpdate(
//             { customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() },
//             { $set: { total_water_added_from_midnight: totalwaterpumped } }
//           );

//           await MotorData.updateOne(
//             { customerId, motor_id: motorId, start_instance_id: start_instance_id },
//             { 
//               $set: { 
//                 stopTime: req.body.stopTime,
//                 receiverfinalwaterlevel: receiverFinalWaterLevel.toString(),
//                 quantity_delivered: quantityDelivered.toString()
//               }
//             }
//           );
//         }
//       })();

//       // Return here to ensure the rest of the code is not executed for the stop action
//       return;
//     } else {
//       // Update the motor stop status to "2" for start action
//       await Tank.updateOne(
//         { customerId, "connections.inputConnections.motor_id": motorId },
//         { $set: { "connections.inputConnections.$.motor_stop_status": "2" } }
//       );
//     }

//     // Check threshold settings if action is start
//     if (action === "start") {
//       if (req.body.threshold_type === "time") {
//         // If threshold type is time, update threshold time
//         // await Tank.updateOne(
//         //   { customerId, "connections.inputConnections.motor_id": motorId },
//         //   { $set: { "connections.inputConnections.$.manual_threshold_time": req.body.manual_threshold_time,startTime:req.body.startTime } }
//         // );
//         const receiver_tank_info7 = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() });

//         const newMotorData = new MotorData({
//           customerId: customerId,
//           motor_id: motorId,
//           start_instance_id: start_instance_id,
//           supplierTank: req.body.from,
//           receiverTank: req.body.to,
//           supplier_type: req.body.from_type,
//           receiver_type: req.body.to_type,
//           startTime: req.body.startTime,
//           receiverInitialwaterlevel:parseInt(receiver_tank_info7.waterlevel, 10)
//         });
//         await newMotorData.save();

//         for await (const tank of Tank.find({  "connections.inputConnections.motor_id": motorId })) {
//           const index = tank.connections.inputConnections.findIndex(connection => connection.motor_id === motorId);
//           if (index !== -1) {
//             await Tank.updateOne(
//               { customerId, "connections.inputConnections.motor_id": motorId },
//               { $set: { [`connections.inputConnections.${index}.manual_threshold_time`]: req.body.manual_threshold_time, [`connections.inputConnections.${index}.startTime`]: req.body.startTime,[`connections.inputConnections.${index}.start_instance_id`]: start_instance_id } }
//             );
//           }
//         }
        

//         // Start monitoring water level based on threshold time
//         const thresholdTime = moment().add(req.body.manual_threshold_time, 'minutes').toDate();
//         const intervalId = setInterval(async () => {
//           const splr_tank_info3 = await Tank.findOne({ customerId, tankName: req.body.from, tankLocation: req.body.from_type.toLowerCase() });
//           const splr_tank_info3_waterlevel = parseInt(splr_tank_info3.waterlevel, 10);
//           //console.log(splr_tank_info3_waterlevel,"splr_tank_info3_waterlevel")
//           const splr_tank_info3_capacity = parseInt(splr_tank_info3.capacity.replace(/,/g, ''), 10);
//          // const splr_tank_info3_capacity = parseInt(splr_tank_info3.capacity, 10);
//          // console.log(splr_tank_info3.capacity,splr_tank_info3_capacity,"splr_tank_info3_capacity")
//           const splr_tank_info3_percentage = (splr_tank_info3_waterlevel / splr_tank_info3_capacity) * 100;
//          // console.log(splr_tank_info3_percentage, "percentage for less than 20");

//           if (new Date() >= thresholdTime || splr_tank_info3_percentage <= 20) {
//             console.log(splr_tank_info3_percentage,)
//             await Tank.updateOne(
//               { customerId, "connections.inputConnections.motor_id": motorId },
//               {
//                 $set: {
//                   "connections.inputConnections.$.motor_stop_status": "1",
//                   "connections.inputConnections.$.threshold_type": null,
//                   "connections.inputConnections.$.manual_threshold_time": null,
//                   "connections.inputConnections.$.manual_threshold_percentage": null
//                 }
//               }
//             );
//             clearInterval(intervalId);

//             await delay(300000);

//             const motorData = await MotorData.findOne({ customerId, motor_id: motorId, start_instance_id: start_instance_id });
//             if (motorData) {
//               const receiverTank = await Tank.findOne({ customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() });
//               const receiverFinalWaterLevel = parseInt(receiverTank.waterlevel, 10);
//               const quantityDelivered = receiverFinalWaterLevel - parseInt(motorData.receiverInitialwaterlevel, 10);
//               const water_pumped_till_now = parseInt(receiverTank.total_water_added_from_midnight, 10);
//               const totalwaterpumped = quantityDelivered + water_pumped_till_now
//               await  Tank.findOneAndUpdate({customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase()}, { $set: { total_water_added_from_midnight: totalwaterpumped } })

//               const stopTime = formatDate(new Date());

//               await MotorData.updateOne(
//                 { customerId, motor_id: motorId, start_instance_id: start_instance_id },
//                 {
//                   $set: {
//                     stopTime:stopTime,
//                     receiverfinalwaterlevel: receiverFinalWaterLevel.toString(),
//                     quantity_delivered: quantityDelivered.toString()
//                   }
//                 }
//               );
//             }
//           }
//         }, 60000);
//       } else if (req.body.threshold_type === "litres") {
//         console.log("entered litres")
//         const receiver_tank_info7 = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() });

//         const newMotorData = new MotorData({
//           customerId: customerId,
//           motor_id: motorId,
//           start_instance_id: start_instance_id,
//           supplierTank: req.body.from,
//           receiverTank: req.body.to,
//           supplier_type: req.body.from_type,
//           receiver_type: req.body.to_type,
//           startTime: req.body.startTime,
//           receiverInitialwaterlevel:parseInt(receiver_tank_info7.waterlevel, 10)
//         });
//         await newMotorData.save();
//         // If threshold type is percentage, calculate percentage threshold
//         const receiver_tank_info = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() });
//         const supplier_tank_info = await Tank.findOne({ customerId, tankName: req.body.from, tankLocation: req.body.from_type.toLowerCase() });
//         if (!receiver_tank_info) {
//           throw new Error("Receiver tank not found.");
//         }
//         if (!supplier_tank_info) {
//           throw new Error("Supplierr tank not found.");
//         }
//         const supplier_capacity =  parseInt(supplier_tank_info.capacity, 10);
//         const supplier_waterLevel = parseInt(supplier_tank_info.waterlevel, 10); 

//         const capacity = parseInt(receiver_tank_info.capacity, 10);
//         const waterLevel = parseInt(receiver_tank_info.waterlevel, 10); 
//         const desired_percentage = parseInt(req.body.manual_threshold_litres.replace(/,/g, ''), 10);

//         console.log(desired_percentage)
//         const threshold_water_level = waterLevel+desired_percentage;

//         const supplier_threshold = supplier_waterLevel-desired_percentage
//         console.log(supplier_threshold,"supplier_threshold")

//         for await (const tank of Tank.find({  "connections.inputConnections.motor_id": motorId })) {
//           const index = tank.connections.inputConnections.findIndex(connection => connection.motor_id === motorId);
//           if (index !== -1) {
//             await Tank.updateOne(
//               { customerId, "connections.inputConnections.motor_id": motorId },
//               { $set: { [`connections.inputConnections.${index}.manual_threshold_percentage`]: supplier_threshold.toString(), [`connections.inputConnections.${index}.startTime`]: req.body.startTime } }
//             );
//           }
//         }
        


//         // Update water level threshold
       

//         // Start monitoring water level based on threshold percentage
//         const intervalId = setInterval(async () => {
//           // Check if water level has reached the threshold percentage
//           const supplier_tank_info1 = await Tank.findOne({ customerId, tankName: req.body.from, tankLocation: req.body.from_type.toLowerCase() });
//           const current_water_level = parseInt(supplier_tank_info1.waterlevel, 10);
//           if (current_water_level <= supplier_threshold) {
//             // Stop the motor pump
//             await Tank.updateOne(
//               { customerId, "connections.inputConnections.motor_id": motorId },
//               { 
//                 $set: { 
//                   "connections.inputConnections.$.motor_stop_status": "1",
                
//                   "connections.inputConnections.$.threshold_type": null,
//                   "connections.inputConnections.$.manual_threshold_time": null,
//                   "connections.inputConnections.$.manual_threshold_percentage": null
//                 }
//               }
//             );
//             clearInterval(intervalId); // Stop monitoring water level
//             await delay(300000);

//             const motorData = await MotorData.findOne({ customerId, motor_id: motorId, start_instance_id: start_instance_id });
//             if (motorData) {
//               const receiverTank = await Tank.findOne({ customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() });
//               const receiverFinalWaterLevel = parseInt(receiverTank.waterlevel, 10);
//               const quantityDelivered = receiverFinalWaterLevel - parseInt(motorData.receiverInitialwaterlevel, 10);


//               const stopTime = formatDate(new Date());

//               await MotorData.updateOne(
//                 { customerId, motor_id: motorId, start_instance_id: start_instance_id },
//                 {
//                   $set: {
//                     stopTime:stopTime,
//                     receiverfinalwaterlevel: receiverFinalWaterLevel.toString(),
//                     quantity_delivered: quantityDelivered.toString()
//                   }
//                 }
//               );
//             }
//           }
//         }, 20000); // Check water level every minute
//       }
//     }

//     // Respond with success message
//     reply.code(200).send({ message: `Motor ${action === "start" ? "started" : "stopped"} successfully.` });
//   } catch (err) {
//     // Handle errors
//     throw boom.boomify(err);
//   }
// };




// exports.motorAction = async (req, reply) => {
//   try {
//     const customerId = req.params.customerId;
//     const action = req.body.action;
//     const motorId = req.body.motor_id;
//     const start_instance_id = req.body.start_instance_id;
//     //const fcmIds = req.body.fcmIds; // Assume this is provided in the request to notify users

//     // Ensure motor_id is provided
//     if (!motorId) {
//       throw new Error("Motor ID is required.");
//     }

//     // Determine the motor stop status based on the action
//     let motorStopStatus;
//     if (action === "start") {
//       motorStopStatus = "2"; // If action is start, set stop status to "2"
//     } else if (action === "stop") {
//       motorStopStatus = "1"; // If action is stop, set stop status to "1"
//     } else {
//       throw new Error("Invalid action provided.");
//     }
//     const users = await User.find({ customerId: customerId });
//     const fcmIds = users.map(user => user.fcmId).filter(fcmId => fcmId);

//     // Handle motor stop action
//     if (action === "stop") {
//       // Update the motor stop status and other fields
//       await Tank.updateOne(
//         { customerId, "connections.inputConnections.motor_id": motorId },
//         { 
//           $set: { 
//             "connections.inputConnections.$.motor_stop_status": "1",
//             "connections.inputConnections.$.stopTime": req.body.stopTime,
//             "connections.inputConnections.$.threshold_type": null,
//             "connections.inputConnections.$.manual_threshold_time": null,
//             "connections.inputConnections.$.manual_threshold_percentage": null
//           }
//         }
//       );

//       // Send immediate response to the client
//       reply.code(200).send({ message: "Motor stopped successfully." });

//       // Send notification for motor stop
//       for (const fcmId of fcmIds) {
//         try {
//           const response = await sendPushNotification(fcmId, 'Motor Stopped', `Motor has stopped at ${req.body.stopTime}.`);
//           console.log('Notification sent successfully:', response);

//           if (response.results[0].error === 'NotRegistered') {
//             await User.updateOne({ fcmId: fcmId }, { $unset: { fcmId: "" } });
//             console.log(`Removed unregistered FCM ID: ${fcmId}`);
//           }
//         } catch (error) {
//           console.error('Error sending notification:', error);
//         }
//       }

//       // Perform stop operations in the background
//       (async () => {
//         await delay(300000);

//         // Update the existing motor data entry with stop details
//         const motorData = await MotorData.findOne({ customerId, motor_id: motorId, start_instance_id: start_instance_id });
//         if (motorData) {
//           const receiverTank = await Tank.findOne({ customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() });
//           const receiverFinalWaterLevel = parseInt(receiverTank.waterlevel, 10);
//           const quantityDelivered = receiverFinalWaterLevel - parseInt(motorData.receiverInitialwaterlevel, 10);
//           const water_pumped_till_now = parseInt(receiverTank.total_water_added_from_midnight, 10);
//           const totalwaterpumped = quantityDelivered + water_pumped_till_now;
//           await Tank.findOneAndUpdate(
//             { customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() },
//             { $set: { total_water_added_from_midnight: totalwaterpumped } }
//           );

//           await MotorData.updateOne(
//             { customerId, motor_id: motorId, start_instance_id: start_instance_id },
//             { 
//               $set: { 
//                 stopTime: req.body.stopTime,
//                 receiverfinalwaterlevel: receiverFinalWaterLevel.toString(),
//                 quantity_delivered: quantityDelivered.toString()
//               }
//             }
//           );
//         }
//       })();

//       // Return here to ensure the rest of the code is not executed for the stop action
//       return;
//     } else {
//       // Update the motor stop status to "2" for start action
//       await Tank.updateOne(
//         { customerId, "connections.inputConnections.motor_id": motorId },
//         { $set: { "connections.inputConnections.$.motor_stop_status": "2" } }
//       );

//       // Send notification for motor start
//       for (const fcmId of fcmIds) {
//         try {
//           const response = await sendPushNotification(fcmId, 'Motor Started', `Motor has started at ${req.body.startTime}.`);
//           console.log('Notification sent successfully:', response);

//           if (response.results[0].error === 'NotRegistered') {
//             await User.updateOne({ fcmId: fcmId }, { $unset: { fcmId: "" } });
//             console.log(`Removed unregistered FCM ID: ${fcmId}`);
//           }
//         } catch (error) {
//           console.error('Error sending notification:', error);
//         }
//       }
//     }

//     // Check threshold settings if action is start
//     if (action === "start") {
//       if (req.body.threshold_type === "time") {
//         const receiver_tank_info7 = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() });

//         const newMotorData = new MotorData({
//           customerId: customerId,
//           motor_id: motorId,
//           start_instance_id: start_instance_id,
//           supplierTank: req.body.from,
//           receiverTank: req.body.to,
//           supplier_type: req.body.from_type,
//           receiver_type: req.body.to_type,
//           startTime: req.body.startTime,
//           receiverInitialwaterlevel: parseInt(receiver_tank_info7.waterlevel, 10)
//         });
//         await newMotorData.save();

//         for await (const tank of Tank.find({ "connections.inputConnections.motor_id": motorId })) {
//           const index = tank.connections.inputConnections.findIndex(connection => connection.motor_id === motorId);
//           if (index !== -1) {
//             await Tank.updateOne(
//               { customerId, "connections.inputConnections.motor_id": motorId },
//               { $set: { [`connections.inputConnections.${index}.manual_threshold_time`]: req.body.manual_threshold_time, [`connections.inputConnections.${index}.startTime`]: req.body.startTime, [`connections.inputConnections.${index}.start_instance_id`]: start_instance_id } }
//             );
//           }
//         }

//         // Start monitoring water level based on threshold time
//         const thresholdTime = moment().add(req.body.manual_threshold_time, 'minutes').toDate();
//         const intervalId = setInterval(async () => {
//           const splr_tank_info3 = await Tank.findOne({ customerId, tankName: req.body.from, tankLocation: req.body.from_type.toLowerCase() });
//           const splr_tank_info3_waterlevel = parseInt(splr_tank_info3.waterlevel, 10);
//           const splr_tank_info3_capacity = parseInt(splr_tank_info3.capacity.replace(/,/g, ''), 10);
//           const splr_tank_info3_percentage = (splr_tank_info3_waterlevel / splr_tank_info3_capacity) * 100;

//           if (new Date() >= thresholdTime || splr_tank_info3_percentage <= 20) {
//             // Send notification for low supplier tank percentage
//             for (const fcmId of fcmIds) {
//               try {
//                 const response = await sendPushNotification(fcmId, 'Low Water Level Alert', `Supplier tank water level is below 20% (${splr_tank_info3_percentage.toFixed(2)}%).`);
//                 console.log('Notification sent successfully:', response);

//                 if (response.results[0].error === 'NotRegistered') {
//                   await User.updateOne({ fcmId: fcmId }, { $unset: { fcmId: "" } });
//                   console.log(`Removed unregistered FCM ID: ${fcmId}`);
//                 }
//               } catch (error) {
//                 console.error('Error sending notification:', error);
//               }
//             }

//             await Tank.updateOne(
//               { customerId, "connections.inputConnections.motor_id": motorId },
//               {
//                 $set: {
//                   "connections.inputConnections.$.motor_stop_status": "1",
//                   "connections.inputConnections.$.threshold_type": null,
//                   "connections.inputConnections.$.manual_threshold_time": null,
//                   "connections.inputConnections.$.manual_threshold_percentage": null
//                 }
//               }
//             );
//             clearInterval(intervalId);

//             await delay(300000);

//             const motorData = await MotorData.findOne({ customerId, motor_id: motorId, start_instance_id: start_instance_id });
//             if (motorData) {
//               const receiverTank = await Tank.findOne({ customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() });
//               const receiverFinalWaterLevel = parseInt(receiverTank.waterlevel, 10);
//               const quantityDelivered = receiverFinalWaterLevel - parseInt(motorData.receiverInitialwaterlevel, 10);
//               const water_pumped_till_now = parseInt(receiverTank.total_water_added_from_midnight, 10);
//               const totalwaterpumped = quantityDelivered + water_pumped_till_now;
//               await Tank.findOneAndUpdate(
//                 { customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() },
//                 { $set: { total_water_added_from_midnight: totalwaterpumped } }
//               );

//               await MotorData.updateOne(
//                 { customerId, motor_id: motorId, start_instance_id: start_instance_id },
//                 {
//                   $set: {
//                     stopTime: req.body.stopTime,
//                     receiverfinalwaterlevel: receiverFinalWaterLevel.toString(),
//                     quantity_delivered: quantityDelivered.toString()
//                   }
//                 }
//               );
//             }
//           }
//         }, 60000); // Check every minute
//       }  else if (req.body.threshold_type === "litres") {
//         console.log("entered litres")
//         const receiver_tank_info7 = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() });

//         const newMotorData = new MotorData({
//           customerId: customerId,
//           motor_id: motorId,
//           start_instance_id: start_instance_id,
//           supplierTank: req.body.from,
//           receiverTank: req.body.to,
//           supplier_type: req.body.from_type,
//           receiver_type: req.body.to_type,
//           startTime: req.body.startTime,
//           receiverInitialwaterlevel:parseInt(receiver_tank_info7.waterlevel, 10)
//         });
//         await newMotorData.save();
//         // If threshold type is percentage, calculate percentage threshold
//         const receiver_tank_info = await Tank.findOne({ customerId, tankName: req.body.to, tankLocation: req.body.to_type.toLowerCase() });
//         const supplier_tank_info = await Tank.findOne({ customerId, tankName: req.body.from, tankLocation: req.body.from_type.toLowerCase() });
//         if (!receiver_tank_info) {
//           throw new Error("Receiver tank not found.");
//         }
//         if (!supplier_tank_info) {
//           throw new Error("Supplierr tank not found.");
//         }
//         const supplier_capacity =  parseInt(supplier_tank_info.capacity, 10);
//         const supplier_waterLevel = parseInt(supplier_tank_info.waterlevel, 10); 

//         const capacity = parseInt(receiver_tank_info.capacity, 10);
//         const waterLevel = parseInt(receiver_tank_info.waterlevel, 10); 
//         const desired_percentage = parseInt(req.body.manual_threshold_litres.replace(/,/g, ''), 10);

//         console.log(desired_percentage)
//         const threshold_water_level = waterLevel+desired_percentage;

//         const supplier_threshold = supplier_waterLevel-desired_percentage
//         console.log(supplier_threshold,"supplier_threshold")

//         for await (const tank of Tank.find({  "connections.inputConnections.motor_id": motorId })) {
//           const index = tank.connections.inputConnections.findIndex(connection => connection.motor_id === motorId);
//           if (index !== -1) {
//             await Tank.updateOne(
//               { customerId, "connections.inputConnections.motor_id": motorId },
//               { $set: { [`connections.inputConnections.${index}.manual_threshold_percentage`]: supplier_threshold.toString(), [`connections.inputConnections.${index}.startTime`]: req.body.startTime } }
//             );
//           }
//         }
        


       

//         // Start monitoring water level based on threshold percentage
//         const intervalId = setInterval(async () => {
//           // Check if water level has reached the threshold percentage
//           const supplier_tank_info1 = await Tank.findOne({ customerId, tankName: req.body.from, tankLocation: req.body.from_type.toLowerCase() });
//           const current_water_level = parseInt(supplier_tank_info1.waterlevel, 10);
//           if (current_water_level <= supplier_threshold) {
//             // Stop the motor pump
//             await Tank.updateOne(
//               { customerId, "connections.inputConnections.motor_id": motorId },
//               { 
//                 $set: { 
//                   "connections.inputConnections.$.motor_stop_status": "1",
                
//                   "connections.inputConnections.$.threshold_type": null,
//                   "connections.inputConnections.$.manual_threshold_time": null,
//                   "connections.inputConnections.$.manual_threshold_percentage": null
//                 }
//               }
//             );
//             clearInterval(intervalId); // Stop monitoring water level
//             await delay(300000);

//             const motorData = await MotorData.findOne({ customerId, motor_id: motorId, start_instance_id: start_instance_id });
//             if (motorData) {
//               const receiverTank = await Tank.findOne({ customerId, tankName: motorData.receiverTank, tankLocation: motorData.receiver_type.toLowerCase() });
//               const receiverFinalWaterLevel = parseInt(receiverTank.waterlevel, 10);
//               const quantityDelivered = receiverFinalWaterLevel - parseInt(motorData.receiverInitialwaterlevel, 10);


//               const stopTime = formatDate(new Date());

//               await MotorData.updateOne(
//                 { customerId, motor_id: motorId, start_instance_id: start_instance_id },
//                 {
//                   $set: {
//                     stopTime:stopTime,
//                     receiverfinalwaterlevel: receiverFinalWaterLevel.toString(),
//                     quantity_delivered: quantityDelivered.toString()
//                   }
//                 }
//               );
//             }
//           }
//         }, 20000); 
//       }
//     }

//     reply.code(200).send({ message: `Motor ${action === "start" ? "started" : "stopped"} successfully.` });
//   } catch (err) {
//     // Handle errors
//     throw boom.boomify(err);
//   }
// };

const motorActionAuto = async (req, reply) => {
  try {
    const customerId = req.params.customerId;
    const action = req.body.action;
    const motorId = req.body.motor_id;
    const motor_on_type = req.body.motor_on_type

    if (!motorId) {
      throw new Error("Motor ID is required.");
    }

    let motorStopStatus;

    if (action === "start") {
      await Tank.updateOne(
        { customerId, "connections.inputConnections.motor_id": motorId },
        {
          $set: {
            "connections.inputConnections.$.motor_stop_status": "2",
            "connections.inputConnections.$.startTime": req.body.startTime,
            "connections.inputConnections.$.motor_on_type": "auto",
          
          }
        }
      );

     ;
    } 

    if (action === "stop") {
      await Tank.updateOne(
        { customerId, "connections.inputConnections.motor_id": motorId },
        {
          $set: {
            "connections.inputConnections.$.motor_stop_status": "1",
            "connections.inputConnections.$.stopTime": req.body.stopTime,
            "connections.inputConnections.$.motor_on_type": null,
          }
        }
      );
    } 

 

    reply.code(200).send({ message: `Motor ${action === "start" ? "started" : "stopped"} successfully.` });
  } catch (err) {
    console.error("Error in motorActionAuto:", err);
    reply.code(500).send({ error: err.message });
  }
};


const checkAutoMode = async () => {
  try {
    const tanks = await Tank.find();

    for (const tank of tanks) {
      for (const inputConnection of tank.connections.inputConnections) {
        if (inputConnection.auto_mode === "active") {
          console.log("This is automation for tank: " + tank.tankName);
          const waterLevel = parseFloat(tank.waterlevel.replace(/,/g, ''));
          const capacity = parseFloat(tank.capacity.replace(/,/g, ''));
          const autoMinPercentage = parseFloat(tank.auto_min_percentage);
          const autoMaxPercentage = parseFloat(tank.auto_max_percentage);
          console.log(waterLevel,capacity,autoMinPercentage,autoMaxPercentage)

          if (isNaN(waterLevel) || isNaN(capacity) || capacity === 0) {
            console.error(`Invalid water level or capacity for tank: ${tank.tankName}`);
            continue; // Skip this tank if the values are not valid
          }

          const currentPercentage = (waterLevel / capacity) * 100;
          console.log("This is automation percentage: " + currentPercentage);
          const now = moment().format('DD-MMM-YYYY - HH:mm');
          console.log(now)
          if (currentPercentage <= autoMinPercentage) {
            await motorActionAuto({
              params: { customerId: tank.customerId },
              body: {
                action: "start",
                motor_id: inputConnection.motor_id,
                motor_on_type: "auto",
                startTime: now
              }
            }, {
              code: (statusCode) => ({ send: (response) => console.log(response) })
            });
          } else if (currentPercentage >= autoMaxPercentage && inputConnection.motor_on_type === "auto") {
            await motorActionAuto({
              params: { customerId: tank.customerId },
              body: {
                action: "stop",
                motor_id: inputConnection.motor_id,
                motor_on_type: "auto",
                stopTime: now
              }
            }, {
              code: (statusCode) => ({ send: (response) => console.log(response) })
            });
          }
        }
      }
    }
  } catch (err) {
    console.error("Error checking auto mode:", err);
  }
};

// Set the interval to check every 15 seconds (15000 milliseconds)
setInterval(checkAutoMode, 15000);







// exports.calculateCapacity = async (req, reply) => {
//   try {
//     const shape = req.body.shape
//     if(shape==="rectangle"){
//         const { length, width, height } = req.body

//        // Ensure all parameters are valid numbers
//         if (isNaN(length) || isNaN(width) || isNaN(height)) {
//         reply.code(400).send('Invalid input parameters')
//         return
//   }

//         // Calculate the capacity of the water tank in liters
//         const capacity = length * width * height * 1000

//         reply.send({ status_code: 200, capacity: capacity});


//         return { message: 'success' };

//     }
//     if(shape==="cylinder"){
//       console.log("hii1")
//       const { length,diameter } = req.body

//      // Ensure all parameters are valid numbers
//       if (isNaN(length) || isNaN(diameter)) {
//       reply.code(400).send('Invalid input parameters')
//       return
//         }

//       // Calculate the capacity of the water tank in liters
//       const radius = diameter / 2
//       const volume = Math.PI * Math.pow(radius, 2) * length
//       const capacity = volume * 1000
     
//       reply.send({ status_code: 200, capacity: capacity});


//       return { message: 'success' };

//   }
 
// //   if(shape==="oval"){
// //     console.log("hii3")
// //     const { length, width, height } = req.body

// //     // Ensure all parameters are valid numbers
// //     if (isNaN(length) || isNaN(width) || isNaN(height)) {
// //       reply.code(400).send('Invalid input parameters')
// //       return
// //     }
  
// //     // Calculate the capacity of the water tank in liters
// //     const radius = height / 2
// //   const a = width - height
// //   const area = Math.PI * radius * radius + 2 * radius * a
// //   const volume = area * length
// //   const capacity = volume * 1000

// //   // Format the result with two decimal places and comma-separated thousands
// //   const formattedCapacity = capacity.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,')
  
// //     reply.send({ status_code: 200, capacity: formattedCapacity});


// //     return { message: 'success' };

// // }


// // if(shape==="horizontalellipse"){


// //   const { length, width, height } = req.body

// //   // Ensure all parameters are valid numbers
// //   if (isNaN(length) || isNaN(width) || isNaN(height)) {
// //     reply.code(400).send('Invalid input parameters')
// //     return
// //   }

// //   // Calculate the capacity of the water tank in liters
// //   const radius1 = length / 2
// //   const radius2 = width / 2
// //   const volume = Math.PI * radius1 * radius2 * height
// //   const capacity = volume * 1000
// //   reply.send({ status_code: 200, capacity: capacity});


// //   return { message: 'success' };

// // }
// if(shape==="userdefined"){
//   const capacity = req.body

//   reply.send({ status_code: 200, capacity: capacity});


//   return { message: 'success' };

// }


//     }

//    catch (err) {
//     throw boom.boomify(err);
//   }
// };


// exports.calculateCapacity = async (req, reply) => {
//   try {
//     const shape = req.body.shape;
//     if (shape === "rectangle") {
//       const { length, width, height } = req.body;

//       // Convert input units from feet to meters
//       const length_m = length * 0.3048;
//       const width_m = width * 0.3048;
//       const height_m = height * 0.3048;
//       console.log(length_m,width_m,height_m)
//       // Ensure all parameters are valid numbers
//       if (isNaN(length_m) || isNaN(width_m) || isNaN(height_m)) {
//         reply.code(400).send("Invalid input parameters");
//         return;
//       }

//       // Calculate the capacity of the water tank in liters
//       const capacity = length_m * width_m * height_m * 1000;

//       reply.send({ status_code: 200, capacity: capacity });

//       return { message: "success" };
//     }
//     if (shape === "cylinder") {
//       console.log("hii1");
//       const { length, diameter } = req.body;

//       // Convert input units from feet to meters
//       const length_m = length * 0.3048;
//       const diameter_m = diameter * 0.3048;

//       // Ensure all parameters are valid numbers
//       if (isNaN(length_m) || isNaN(diameter_m)) {
//         reply.code(400).send("Invalid input parameters");
//         return;
//       }

//       // Calculate the capacity of the water tank in liters
//       const radius = diameter_m / 2;
//       const volume = Math.PI * Math.pow(radius, 2) * length_m;
//       const capacity = volume * 1000;

//       reply.send({ status_code: 200, capacity: capacity });

//       return { message: "success" };
//     }

//     // Add similar conversions for other shapes if necessary

//     if (shape === "userdefined") {
//       const capacity = req.body;

//       reply.send({ status_code: 200, capacity: capacity });

//       return { message: "success" };
//     }
//   } catch (err) {
//     throw boom.boomify(err);
//   }
// };

exports.calculateCapacity = async (req, reply) => {
  try {
    const shape = req.body.shape;
    if (shape === "rectangle") {
      const { length, width, height } = req.body;

      // Convert input units from feet to meters
      const length_m = length * 0.3048;
      const width_m = width * 0.3048;
      const height_m = height * 0.3048;

      // Ensure all parameters are valid numbers
      if (isNaN(length_m) || isNaN(width_m) || isNaN(height_m)) {
        reply.code(400).send("Invalid input parameters");
        return;
      }

      // Calculate the capacity of the water tank in liters
      const capacity = length_m * width_m * height_m * 1000;

      // Calculate the water capacity for a 1 centimeter height
      const waterCapacityPerCm = length_m * width_m * 0.01 * 1000;

      reply.send({ status_code: 200, capacity: capacity, waterCapacityPerCm: waterCapacityPerCm });

      return { message: "success" };
    }
    if (shape === "cylinder") {
      const { length, diameter } = req.body;

      // Convert input units from feet to meters
      const length_m = length * 0.3048;
      const diameter_m = diameter * 0.3048;

      // Ensure all parameters are valid numbers
      if (isNaN(length_m) || isNaN(diameter_m)) {
        reply.code(400).send("Invalid input parameters");
        return;
      }

      // Calculate the capacity of the water tank in liters
      const radius = diameter_m / 2;
      const volume = Math.PI * Math.pow(radius, 2) * length_m;
      const capacity = volume * 1000;

      // Calculate the water capacity for a 1 centimeter height
      const waterCapacityPerCm = Math.PI * Math.pow(radius, 2) * 0.01 * 1000;

      reply.send({ status_code: 200, capacity: capacity, waterCapacityPerCm: waterCapacityPerCm });

      return { message: "success" };
    }

    // Add similar conversions for other shapes if necessary

    if (shape === "userdefined") {
      const capacity = req.body.capacity; // Assuming capacity is provided directly

      // Calculate the water capacity for a 1 centimeter height
      const waterCapacityPerCm = capacity / req.body.height; // Assuming height of the shape is provided

      reply.send({ status_code: 200, capacity: capacity, waterCapacityPerCm: waterCapacityPerCm });

      return { message: "success" };
    }
  } catch (err) {
    throw boom.boomify(err);
  }
};

// exports.IotDevice = async (req, reply) => {
//   try {
//     const { hardwareId, mode, tanks } = req.body;

//     // create a new tank document with the current date and time
//     const currentDate = new Date();
//     const date = currentDate.toISOString(); // save the date as an ISO string
//     const time = currentDate.toLocaleTimeString('en-IN', { hour12: false, timeZone: 'Asia/Kolkata' });

//     // Create an array of tank documents
//     const tankDocuments = tanks.map(tank => ({
//       tankhardwareId: tank.tankhardwareId,
//       tankHeight: tank.tankHeight,
//       maxLevel: tank.maxLevel,
//       minLevel: tank.minLevel,
//       date: date,
//       time: time
//     }));


//     // create a new IotData document with the provided data
//     const ottank = new IotData({ hardwareId, mode, tanks: tankDocuments, date, time });

//     // save the document to MongoDB
//     await ottank.save();

//     // delete previous records except the three latest ones
//     const previousRecords = await IotData.find({ hardwareId })
//       .sort({ date: -1, time: -1 })
//       .skip(3); // skip the three latest documents

//     for (const record of previousRecords) {
//       await record.remove();
//     }

//     // get the latest three documents sorted in descending order of date and time
//     const latestOttanks = await IotData.find({ hardwareId })
//       .sort({ date: -1, time: -1 })
//       .limit(3);

//     // send the latest documents
//     reply.code(200).send({ latestOttanks });
//   } catch (err) {
//     // send an error response
//     reply.code(500).send({ error: err.message });
//   }
// };



exports.IotDevice = async (req, reply) => {
  try {
    const { hardwareId, mode, tanks } = req.body;

    // create a new tank document with the current date and time
    const currentDate = new Date();
    const date = currentDate.toISOString(); // save the date as an ISO string
    const time = currentDate.toLocaleTimeString('en-IN', { hour12: false, timeZone: 'Asia/Kolkata' });

    // Create an array of tank documents
    const tankDocuments = tanks.map(tank => ({
      tankhardwareId: tank.tankhardwareId,
      tankHeight: tank.tankHeight,
      maxLevel: tank.maxLevel,
      minLevel: tank.minLevel,
      date: date,
      time: time
    }));

    // create a new IotData document with the provided data
    const ottank = new IotData({ hardwareId, mode, tanks: tankDocuments, date, time });

    // save the document to MongoDB
    await ottank.save();

    // Delete excess records (keep only the latest three records)
    const recordsToKeep = 3;
    const recordsToDelete = await IotData.find({ hardwareId })
      .sort({ date: -1, time: -1 })
      .skip(recordsToKeep);

    for (const record of recordsToDelete) {
      await record.remove();
    }

    // Update waterlevel in tanksSchema for each tank
    for (const tank of tanks) {
      const { tankhardwareId, tankHeight } = tank;

      // Find the corresponding tank in tanksSchema
      const existingTank = await Tank.findOne({ hardwareId, tankhardwareId });
      if (!existingTank) {
        continue; // Skip to the next tank if not found
      }

      const customerId = existingTank.customerId;
      const tank_name = existingTank.tankName;

      // Update the waterlevel using the tankHeight value
      const tank_height1 = (parseInt(existingTank.height.replace(/,/g, ''), 10)) * 30.48;
      const tank_height = parseInt(tank_height1.toFixed(0), 10); // Ensure it's an integer
      const water_level_height = tank_height - tankHeight;
      const waterCapacityPerCm = parseInt(existingTank.waterCapacityPerCm.replace(/,/g, ''), 10);
      
      const water_level = parseInt(water_level_height * waterCapacityPerCm, 10);

      if (water_level >= 0) {
        existingTank.waterlevel = water_level;
      
        // Save the updated tank document
        await existingTank.save();
      
        // Update linked tanks
        for (const outputConnection of existingTank.connections.outputConnections) {
          const linkedTank = await Tank.findOne({ customerId, tankName: outputConnection.outputConnections, tankLocation: outputConnection.output_type });
          if (linkedTank) {
            for (const inputConnection of linkedTank.connections.inputConnections) {
              if (inputConnection.inputConnections === tank_name) {
                inputConnection.water_level = water_level;
                await linkedTank.save();
              }
            }
          }
        }
      }
      
    }

    // Send the latest three documents
    const latestOttanks = await IotData.find({ hardwareId })
      .sort({ date: -1, time: -1 });

    reply.code(200).send({ latestOttanks });
  } catch (err) {
    // send an error response
    reply.code(500).send({ error: err.message });
  }
};

console.log("this is for testing push")

exports.IotDeviceforstandalonedevice = async (req, reply) => {
  try {
    console.log("entered post for iotstandalone")
    const { hardwareId, Motor_status, tanks } = req.body;

    // create a new tank document with the current date and time
    const currentDate = new Date();
    const date = currentDate.toISOString(); // save the date as an ISO string
    const time = currentDate.toLocaleTimeString('en-IN', { hour12: false, timeZone: 'Asia/Kolkata' });

    // Create an array of tank documents
    const tankDocuments = tanks.map(tank => ({
      tankhardwareId: tank.tankhardwareId,
      tankHeight: tank.tankHeight,
      date: date,
      time: time
    }));

    // create a new IotData document with the provided data
    const ottank = new IotData({ hardwareId, Motor_status, tanks: tankDocuments, date, time });

    // save the document to MongoDB
    await ottank.save();


    // Delete excess records (keep only the latest three records)
    const recordsToKeep = 3;
    const recordsToDelete = await IotData.find({ hardwareId })
      .sort({ date: -1, time: -1 })
      .skip(recordsToKeep);

    for (const record of recordsToDelete) {
      await record.remove();
    }

    // Update waterlevel in tanksSchema for each tank
    for (const tank of tanks) {
      const { tankhardwareId, tankHeight } = tank;

      // Find the corresponding tank in tanksSchema
      const existingTank = await Tank.findOne({ hardwareId, tankhardwareId });
      if (!existingTank) {
        continue; // Skip to the next tank if not found
      }

      const customerId = existingTank.customerId;
      const tank_name = existingTank.tankName;

      // Update the waterlevel using the tankHeight value
      const tank_height1 = (parseInt(existingTank.height.replace(/,/g, ''), 10)) * 30.48;
      const tank_height = parseInt(tank_height1.toFixed(0), 10); // Ensure it's an integer
      const water_level_height = tank_height - tankHeight;
      const waterCapacityPerCm = parseInt(existingTank.waterCapacityPerCm.replace(/,/g, ''), 10);
      
      const water_level = parseInt(water_level_height * waterCapacityPerCm, 10);

      if (water_level >= 0) {
        existingTank.waterlevel = water_level;
      
        // Save the updated tank document
        await existingTank.save();
      
        // Update linked tanks
        for (const outputConnection of existingTank.connections.outputConnections) {
          const linkedTank = await Tank.findOne({ customerId, tankName: outputConnection.outputConnections, tankLocation: outputConnection.output_type });
          if (linkedTank) {
            for (const inputConnection of linkedTank.connections.inputConnections) {
              if (inputConnection.inputConnections === tank_name) {
                inputConnection.water_level = water_level;
                await linkedTank.save();
              }
            }
          }
        }
      }
      
    }
    const status = req.body.Motor_status;
    

    // Find the tank that contains the specified motor_id in its inputConnections
    const tank = await Tank.findOne({ "connections.inputConnections.motor_id": hardwareId });

    if (!tank) {
      return reply.status(404).send({
        status_code: 404,
        message: 'Motor not found for the specified motor_id'
      });
    }
    console.log(hardwareId,"hardwareId")
    console.log(status,"status")
    // Find the inputConnection with the specified motor_id
    const inputConnection = tank.connections.inputConnections.find(conn => conn.motor_id === hardwareId);

if (inputConnection) {
    // Update the motor_status of the inputConnection
    inputConnection.motor_status = status;
    console.log(inputConnection)


    // Check if motor_stop_status is "1" and status is "2"
    if (inputConnection.motor_stop_status === "1" && status === "2") {
      console.log("got into forced manual")
      console.log(inputConnection.motor_on_type,"before if motor on type")
      // Check if motor_on_type is not already "forced_manual"
      if (inputConnection.motor_on_type !== "forced_manual") {
          inputConnection.motor_on_type = "forced_manual";
          console.log("entered forced manual of if")
          inputConnection.motor_stop_status = "2";
          // Update startTime to the current time in the specified format
          const currentTime = new Date();
          const formattedTime = currentTime.toLocaleString('en-GB', {
              day: '2-digit',
              month: 'short',
              year: 'numeric',
              hour: '2-digit',
              minute: '2-digit',
              hour12: false,
          }).replace(',', '');
          inputConnection.startTime = formattedTime;
      }
  }
      // Check if motor_stop_status is "1" and status is "2"
      if (inputConnection.motor_stop_status === "2" && status === "1") {
        console.log("got into forced manual stop")
        console.log(inputConnection.motor_on_type,"before if motor on type stop")
        // Check if motor_on_type is not already "forced_manual"
        if (inputConnection.motor_on_type = "forced_manual") {
            inputConnection.motor_on_type = "manual";
            console.log("entered forced manual of if of stop")
    
            // Update startTime to the current time in the specified format
           
           
            inputConnection.motor_stop_status = "1";
        }
    }
  
}


    // Save the updated tank
    await tank.save();


    // Send the latest three documents
    const latestOttanks = await IotData.find({ hardwareId })
      .sort({ date: -1, time: -1 });

    reply.code(200).send({ latestOttanks });
  } catch (err) {
    // send an error response
    reply.code(500).send({ error: err.message });
  }
};


    




// exports.IotDevice3 = async (req, reply) => { 
//   try { 
//   const { hardwareId, mode, tanks } = req.body; 
  
//   // create a new tank document with the current date and time 
//   const currentDate = new Date(); 
//   const date = currentDate.toISOString(); // save the date as an ISO string 
//   const time = currentDate.toLocaleTimeString('en-IN', { hour12: false, timeZone: 'Asia/Kolkata' }); 
  
//   // Create an array of tank documents 
//   const tankDocuments = tanks.map(tank => ({ 
//   tankhardwareId: tank.tankhardwareId, 
//   tankHeight: tank.tankHeight, 
//   maxLevel: tank.maxLevel, 
//   minLevel: tank.minLevel, 
//   date: date, 
//   time: time 
//   })); 
  
//   // create a new IotData document with the provided data 
//   const ottank = new IotData({ hardwareId, mode, tanks: tankDocuments, date, time }); 
  
//   // save the document to MongoDB 
//   await ottank.save(); 
  
//   // Delete excess records (keep only the latest three records) 
//   const recordsToKeep = 3; 
//   const recordsToDelete = await IotData.find({ hardwareId }) 
//   .sort({ date: -1, time: -1 }) 
//   .skip(recordsToKeep); 
  
//   for (const record of recordsToDelete) { 
//   await record.remove(); 
//   } 
  
//   // Update waterlevel in tanksSchema for each tank 
//   for (const tank of tanks) { 
//   const { tankhardwareId, tankHeight } = tank; 
  
//   // Find the corresponding tank in tanksSchema 
//   const existingTank = await Tank.findOne({ hardwareId, tankhardwareId }); 
  
  
//   if (existingTank) { 
//   // Update the waterlevel using the tankHeight value 
  
//   const tank_height1 = (parseInt(existingTank.height.replace(/,/g, ''), 10)) * 30.48; 
//   console.log(tank_height1, 25); 
  
//   // The value of tank_height1 is a number, not a string, so you cannot use replace on it. 
//   // If you want to format it with commas, you can create a function to add commas to a number. 
//   function numberWithCommas(x) { 
//   return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); 
//   } 
  
//   // Now you can use the function to format the tank_height1 value with commas. 
//   const formatted_tank_height1 = numberWithCommas(tank_height1); 
//   console.log(formatted_tank_height1, 25); 
  
//   const tank_height = parseInt(formatted_tank_height1.replace(/,/g, ''), 10); 
//   console.log(tank_height); 
//   // console.log(tank_height,1) 
//   const water_level_height = tank_height - tankHeight 
//   console.log(water_level_height,2) 
  
//   const waterCapacityPerCm = parseInt(existingTank.waterCapacityPerCm.replace(/,/g, ''), 10) 
//   console.log(waterCapacityPerCm,3) 
//   const water_level = water_level_height * waterCapacityPerCm; 
//   console.log(water_level, 4); 
  
//   // Function to add commas to a number 
//   function numberWithCommas(x) { 
//   return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); 
//   } 
  
//   const formatted_water_level = numberWithCommas(water_level); 
//   console.log(formatted_water_level, 4); 
  
//   existingTank.waterlevel = parseInt(formatted_water_level.replace(/,/g, ''), 10); 
//   console.log(existingTank.waterlevel); 
  
  
  
//   // Save the updated tank document 
//   await existingTank.save();
// for (const outputConnection of existingTank.connections.outputConnections) {
//   const linkedTank = await Tank.findOne({ customerId: customerId, tankName: outputConnection.outputConnections, tankLocation: outputConnection.output_type });
//   if (linkedTank) {
//    // linkedTank.waterlevel = existingTank.waterlevel;
//     //await linkedTank.save();

//     // Update water level of tanks linked through input connections of the linked tank
//     for (const inputConnection of linkedTank.connections.inputConnections) {
//       if (inputConnection.inputConnections === tank_name) {
//         inputConnection.water_level = water_level.toString();
//         await linkedTank.save();
//       }
//     }
//   }
// } 
//   } 
//   } 
  
//   // Send the latest three documents 
//   const latestOttanks = await IotData.find({ hardwareId }) 
//   .sort({ date: -1, time: -1 }); 
  
//   reply.code(200).send({ latestOttanks }); 
//   } catch (err) { 
//   // send an error response 
//   reply.code(500).send({ error: err.message }); 
//   } 
//   }; 

// exports.IotDevice1 = async (req, reply) => {
//   try {
//     const { hardwareId, mode, tanks } = req.body;
    

//     // create a new tank document with the current date and time
//     const currentDate = new Date();
//     const date = currentDate.toISOString(); // save the date as an ISO string
//     const time = currentDate.toLocaleTimeString('en-IN', { hour12: false, timeZone: 'Asia/Kolkata' });

//     // Create an array of tank documents
//     const tankDocuments = tanks.map(tank => ({
//       tankhardwareId: tank.tankhardwareId,
//       tankHeight: tank.tankHeight,
//       maxLevel: tank.maxLevel,
//       minLevel: tank.minLevel,
//       date: date,
//       time: time
//     }));

//     // create a new IotData document with the provided data
//     const ottank = new IotData({ hardwareId, mode, tanks: tankDocuments, date, time });

//     // save the document to MongoDB
//     await ottank.save();

//     // Delete excess records (keep only the latest three records)
//     const recordsToKeep = 3;
//     const recordsToDelete = await IotData.find({ hardwareId })
//       .sort({ date: -1, time: -1 })
//       .skip(recordsToKeep);

//     for (const record of recordsToDelete) {
//       await record.remove();
//     }
//     console.log(tanks)
//     // Update waterlevel in tanksSchema for each tank
//     for (const tank of tanks) {
//       console.log(tank)
//       const { tankhardwareId, tankHeight } = tank;
//       console.log(hardwareId,tankhardwareId)
//       // Find the corresponding tank in tanksSchema
//       const existingTank = await Tank.findOne({ hardwareId, tankhardwareId });
//       if (!existingTank) {
//         console.log(`No tank found for tankhardwareId '${tankhardwareId}'. Skipping.`);
//         continue; // Skip to the next iteration
//       }
//       console.log(existingTank,"existing tank")
//       if (existingTank) {
//         // Update the waterlevel using the tankHeight value
        
//         const tank_height1 = (parseInt(existingTank.height.replace(/,/g, ''), 10)) * 30.48;
//         console.log(tank_height1, 25);
        
//         // The value of tank_height1 is a number, not a string, so you cannot use replace on it.
//         // If you want to format it with commas, you can create a function to add commas to a number.
//         function numberWithCommas(x) {
//           return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
//         }
        
//         // Now you can use the function to format the tank_height1 value with commas.
//         const formatted_tank_height1 = numberWithCommas(tank_height1);
//         console.log(formatted_tank_height1, 25);
        
//         const tank_height = parseInt(formatted_tank_height1.replace(/,/g, ''), 10);
//         console.log(tank_height);
//      // console.log(tank_height,1)
//       const water_level_height = tank_height - tankHeight
//       console.log(water_level_height,2)
      
//       const waterCapacityPerCm = parseInt(existingTank.waterCapacityPerCm.replace(/,/g, ''), 10)
//       console.log(waterCapacityPerCm,3)
//       const water_level = water_level_height * waterCapacityPerCm;
// console.log(water_level, 4);

// // Function to add commas to a number
// function numberWithCommas(x) {
//   return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
// }

// const formatted_water_level = numberWithCommas(water_level);
// console.log(formatted_water_level, 4);

// existingTank.waterlevel = parseInt(formatted_water_level.replace(/,/g, ''), 10);
// console.log(existingTank.waterlevel);



//         // Save the updated tank document
//         await existingTank.save();
//         for (const outputConnection of existingTank.connections.outputConnections) {
//           const linkedTank = await Tank.findOne({ customerId: customerId, tankName: outputConnection.outputConnections, tankLocation: outputConnection.output_type });
//           if (linkedTank) {
//            // linkedTank.waterlevel = existingTank.waterlevel;
//             //await linkedTank.save();

//             // Update water level of tanks linked through input connections of the linked tank
//             for (const inputConnection of linkedTank.connections.inputConnections) {
//               if (inputConnection.inputConnections === tank_name) {
//                 inputConnection.water_level = water_level.toString();
//                 await linkedTank.save();
//               }
//             }
//           }
//         }
//       }
//     }

//     // Send the latest three documents
//     const latestOttanks = await IotData.find({ hardwareId })
//       .sort({ date: -1, time: -1 });

//     reply.code(200).send({ latestOttanks });
//   } catch (err) {
//     // send an error response
//     reply.code(500).send({ error: err.message });
//   }
// };


// exports.IotDevice1 = async (req, reply) => {
//   try {
//     const { hardwareId, mode, tanks } = req.body;

//     // create a new tank document with the current date and time
//     const currentDate = new Date();
//     const date = currentDate.toISOString(); // save the date as an ISO string
//     const time = currentDate.toLocaleTimeString('en-IN', { hour12: false, timeZone: 'Asia/Kolkata' });

//     // Create an array of tank documents
//     const tankDocuments = tanks.map(tank => ({
//       tankhardwareId: tank.tankhardwareId,
//       tankHeight: tank.tankHeight,
//       maxLevel: tank.maxLevel,
//       minLevel: tank.minLevel,
//       date: date,
//       time: time
//     }));

//     // create a new IotData document with the provided data
//     const ottank = new IotData({ hardwareId, mode, tanks: tankDocuments, date, time });

//     // save the document to MongoDB
//     await ottank.save();

//     // Delete excess records (keep only the latest three records)
//     const recordsToKeep = 3;
//     const recordsToDelete = await IotData.find({ hardwareId })
//       .sort({ date: -1, time: -1 })
//       .skip(recordsToKeep);

//     for (const record of recordsToDelete) {
//       await record.remove();
//     }

//     // Update waterlevel in tanksSchema for each tank
//     for (const tank of tanks) {
//       const { tankhardwareId, tankHeight } = tank;

//       if (tankHeight === null || tankHeight === undefined) {
//         continue; // Skip this iteration and move to the next tank
//       }
//       // Find the corresponding tank in tanksSchema
//       const existingTank = await Tank.findOne({ hardwareId, tankhardwareId });
      
//       if (existingTank) {
//         // Update the waterlevel using the tankHeight value
//         const tank_height = parseInt(existingTank.height.replace(/,/g, ''), 10) * 30.48;
//         const water_level_height = tank_height - tankHeight;
//         const customerId = existingTank.customerId;
//         const waterCapacityPerCm = parseInt(existingTank.waterCapacityPerCm.replace(/,/g, ''), 10);
//         let water_level = water_level_height * waterCapacityPerCm;
//         water_level = Math.round(water_level); // Round to nearest whole number
//         existingTank.waterlevel = water_level.toString(); // Convert to string as per schema definition
//         const tank_name = existingTank.tankName;
//         // Save the updated tank document
//         await existingTank.save();

//         // Update water level of tanks linked through output connections
//         for (const outputConnection of existingTank.connections.outputConnections) {
//           const linkedTank = await Tank.findOne({ customerId: customerId, tankName: outputConnection.outputConnections, tankLocation: outputConnection.output_type });
//           if (linkedTank) {
//            // linkedTank.waterlevel = existingTank.waterlevel;
//             //await linkedTank.save();

//             // Update water level of tanks linked through input connections of the linked tank
//             for (const inputConnection of linkedTank.connections.inputConnections) {
//               if (inputConnection.inputConnections === tank_name) {
//                 inputConnection.water_level = water_level.toString();
//                 await linkedTank.save();
//               }
//             }
//           }
//         }
//       }
//     }

//     // Send the latest three documents
//     const latestOttanks = await IotData.find({ hardwareId })
//       .sort({ date: -1, time: -1 });

//     reply.code(200).send({ latestOttanks });
//   } catch (err) {
//     // send an error response
//     reply.code(500).send({ error: err.message });
//   }
// };




// exports.getIotD = async(req, reply) => {
//   try {
//     await IotData.find({hardwareId: req.query.hardwareId})
//       .exec()
//       .then((docs) => {
//         reply.send({ status_code: 200, data: docs, count: docs.length });
//       })
//       .catch((err) => {
//         console.log(err);
//         reply.send({ error: err });
//       });
//   } catch (err) {
//     throw boom.boomify(err);
//   }
// }


exports.getIotD = async (req, reply) => {
  try {
    const latestRecords = await IotData.find({ hardwareId: req.query.hardwareId })
      .sort({ date: -1, time: -1 }) // Sort by date and time in descending order
      .limit(3) // Limit the result to 3 records
      .exec();

    reply.send({ status_code: 200, data: latestRecords, count: latestRecords.length });
  } catch (err) {
    console.error(err);
    throw boom.boomify(err);
  }
};


exports.getLatestData = async (req, reply) => {
  try {
    const hardwareId = req.params.hardwareId;

    // get the latest two tank documents for the current hardwareId sorted in descending order of date and time
    const latestTanks = await IotData.find({ hardwareId }).sort({ date: -1, time: -1 }).limit(2);

    // if the number of documents for the current hardwareId is less than two, return an error response
    if (latestTanks.length < 2) {
      return reply.code(404).send({ error: 'Not enough data' });
    }

    // calculate the time difference between the latest and previous documents
    const latestDate = new Date(latestTanks[0].date);
    const previousDate = new Date(latestTanks[1].date);
    const latestTime = latestTanks[0].time.split('.')[0]; // remove milliseconds
    const previousTime = latestTanks[1].time.split('.')[0]; // remove milliseconds
    latestDate.setHours(parseInt(latestTime.substring(0, 2)), parseInt(latestTime.substring(3, 5)), parseInt(latestTime.substring(6, 8)));
    previousDate.setHours(parseInt(previousTime.substring(0, 2)), parseInt(previousTime.substring(3, 5)), parseInt(previousTime.substring(6, 8)));
    const timeDiff = (latestDate.getTime() - previousDate.getTime()) / 1000; // convert from milliseconds to seconds
    console.log(latestDate,previousDate,latestTime,previousTime,timeDiff)
    reply.code(200).send({ timeDiff });
  
  } catch (err) {
    // send an error response
    reply.code(500).send({ error: err.message });
  }
};

exports.changesurveystatus = async (req, reply) => {
  try {
    const customerId = req.params.customerId;

   
           const result = await User.findOneAndUpdate(
          { customerId: customerId },
          { $set: { survey_status: req.body.survey_status } },
          { new: true } 
        );


   
    reply.code(200).send({ result });
  
  } catch (err) {
    // send an error response
    reply.code(500).send({ error: err.message });
  }
};



exports.checkStatusofIot = async (req, reply) => {
  try {
    // get a list of unique hardware IDs in the collection
    const hardwareIds = await IotData.distinct('hardwareId');

    // create an empty object to store the time differences for each hardware ID
    const timeDiffs = {};

    // loop over each hardware ID and calculate the time difference between the latest two records
    for (const hardwareId of hardwareIds) {
      // get the latest two records for the current hardware ID
      const latestTanks = await IotData.find({ hardwareId }).sort({ date: -1, time: -1 }).limit(2);

      // if the number of records for the current hardware ID is less than two, skip to the next ID
      if (latestTanks.length < 2) {
        continue;
      }

      // calculate the time difference between the latest and previous records for the current hardware ID
      const latestDate = new Date(latestTanks[0].date);
      const previousDate = new Date(latestTanks[1].date);
      const latestTime = latestTanks[0].time.split('.')[0]; // remove milliseconds
      const previousTime = latestTanks[1].time.split('.')[0]; // remove milliseconds
      latestDate.setHours(parseInt(latestTime.substring(0, 2)), parseInt(latestTime.substring(3, 5)), parseInt(latestTime.substring(6, 8)));
      previousDate.setHours(parseInt(previousTime.substring(0, 2)), parseInt(previousTime.substring(3, 5)), parseInt(previousTime.substring(6, 8)));
      const timeDiff = (latestDate.getTime() - previousDate.getTime()) / 1000; // convert from milliseconds to seconds

      // store the time difference for the current hardware ID
      timeDiffs[hardwareId] = timeDiff;
    }

    // send the time differences for all hardware IDs
    reply.code(200).send({ timeDiffs });
  
  } catch (err) {
    // send an error response
    reply.code(500).send({ error: err.message });
  }
};

exports.totalwaterLevelSum = async (request, reply) => {
  const { tankLocation, typeOfWater } = request.query;

  const waterlevelSum = await Tank.aggregate([
    {
      $match: { tankLocation, typeOfWater }
    },
    {
      $group: {
        _id: null,
        totalWaterlevel: { $sum: { $toInt: '$waterlevel' } }
      }
    }
  ]);

  const result = waterlevelSum[0]?totalWaterlevel : 0;

  reply.send({ waterlevelSum: result });
}


exports.startUpdateLoop = async (request, reply) => {
  const updateInterval = 5000;

  setInterval(async () => {
    try {
      const iotTank = await IotData.findOne({ hardwareId: request.body.hardwareId });
      if (!iotTank) {
        console.log(`IOTtank not found for hardwareId ${request.body.hardwareId}`);
        return;
      }
      
      const currentWaterlevel = Number(iotTank.tankHeight) * 200;
      const tank = await Tank.findOne({ hardwareId: iotTank.hardwareId });
      
      let combinedWaterlevel;
      if (tank) {
        combinedWaterlevel = currentWaterlevel + Number(tank.waterlevel);
      } else {
        combinedWaterlevel = currentWaterlevel;
      }
      
      await Tank.updateOne({ hardwareId: iotTank.hardwareId }, { $set: { waterlevel: combinedWaterlevel } });
      
      console.log(`Waterlevel updated successfully for hardwareId ${iotTank.hardwareId}`);
      console.log(`Previous waterlevel: ${tank ? tank.waterlevel : 0}`);
      console.log(`Current waterlevel: ${currentWaterlevel}`);
      console.log(`Combined waterlevel: ${combinedWaterlevel}`);
    } catch (err) {
      console.error(err);
    }
  }, updateInterval);
};




const updatewaterlevelsatmidnight = async () => {
  console.log('Cron job triggered at:', moment().tz('Asia/Kolkata').format());

  try {
    const tanks = await Tank.find({});
    for (const tank of tanks) {
      tank.waterlevel_at_midnight = tank.waterlevel;
      tank.total_water_added_from_midnight = "0";
      await tank.save();
      console.log(`Updated tank ${tank._id} waterlevel_at_midnight to ${tank.waterlevel}`);
    }
    console.log('Waterlevel noted in waterlevel_at_midnight');
  } catch (error) {
    console.error('Error occurred:', error);
  }
};

// Schedule the task to run every day at 13:49 IST (1:49 PM IST)
cron.schedule('0 0 * * *', updatewaterlevelsatmidnight, {
  timezone: "Asia/Kolkata"
});


let consumptionTask;

// Function to clear the specific scheduled task
const clearConsumptionSchedule = () => {
  if (consumptionTask) {
    consumptionTask.stop(); // Stop the existing task if it exists
    consumptionTask = null; // Clear the reference
  }
};

// Function to update total consumption till midnight
const updatetotalConsumptiontillmidnight = async () => { 
  console.log('Cron job triggered at:', moment().tz('Asia/Kolkata').format());

  try {
    const tanks = await Tank.find({});
    for (const tank of tanks) {
      const waterlevel_at_midnight = parseInt((tank.waterlevel_at_midnight).replace(/,/g, ''), 10);
      const total_water_added_from_midnight = parseInt((tank.total_water_added_from_midnight).replace(/,/g, ''), 10);
      const waterlevel = parseInt((tank.waterlevel).replace(/,/g, ''), 10);
      const capacity = parseInt((tank.capacity).replace(/,/g, ''), 10);
      console.log(waterlevel_at_midnight,total_water_added_from_midnight,waterlevel)
      const totalconsumption = (waterlevel_at_midnight + total_water_added_from_midnight) - waterlevel;
     // const available_capacity = total_water_added_from_midnight + waterlevel;
      const consumed_percentage = ((totalconsumption / capacity) * 100).toFixed(2);
      console.log(totalconsumption,tank.tankName)

      // Format the date in the desired format
      const formattedDate = moment().tz('Asia/Kolkata').format('DD-MMM-YYYY - HH:mm');

      // Check if the record already exists
      const existingRecord = await TankConsumptionOriginalSchema.findOne({
        customerId: tank.customerId,
        tankName: tank.tankName,
        tankLocation: tank.tankLocation,
        time: formattedDate
      });

      if (!existingRecord) {
        // Create and save the new document if it doesn't exist
        const newTankConsumption = new TankConsumptionOriginalSchema({
          customerId: tank.customerId,
          tankName: tank.tankName,
          tankLocation: tank.tankLocation,
          available_capacity: (tank.capacity).toString(),
          consumption: totalconsumption.toString(),
          consumed_percentage: consumed_percentage.toString(),  
          time: formattedDate, // Save the formatted date
          block:tank.blockName,
          typeofwater:tank.typeOfWater
        });

        await newTankConsumption.save();
        console.log(`Created new record for tank ${tank.tankName} at ${formattedDate}`);
      } else {
        console.log(`Record already exists for tank ${tank.tankName} at ${formattedDate}`);
      }
    }
    console.log('Waterlevel noted in waterlevel_at_midnight');
  } catch (error) {
    console.error('Error occurred:', error);
  }
};

// Clear the existing schedule for this task before creating a new one
clearConsumptionSchedule();

// Schedule the task to run every day at 12:49 PM IST and store the reference
consumptionTask = cron.schedule('50 23 * * *', updatetotalConsumptiontillmidnight, {
  timezone: "Asia/Kolkata"
});

console.log('Scheduled task to update total consumption till midnight.');








exports.deletemotordatarecordsbefore7days = async (req, reply) => {
  try {
    // Schedule the task to run every day at 10 seconds past the minute
    cron.schedule('0 0 * * *', async () => {
      try {
       // Run the deletion task once a day
            setInterval(async () => {
              await deleteOldRecords();
            }, 24 * 60 * 60 * 1000); // 24 hours in milliseconds

      } catch (error) {
        console.error('Error occurred:', error);
      }
    });

   
  } catch (err) {
    throw boom.boomify(err);
  }
};


exports.motorstatus = async (req, reply) => {

  try {
    const motor_id = req.params.motor_id;
    console.log(motor_id)
    
    const motorInfo = await Tank.findOne({ motor_id: motor_id });

  console.log(motorInfo)
    

    //return update;
      
    reply.send({ status_code: 200,status:motorInfo.motor_status});



  } 
  catch (err) {
    throw boom.boomify(err);
  }
};



exports.readMotorStatus = async (req, reply) => {
  try {
    const motor_id = req.query.motor_id;
    console.log("entered read api for iot")

    // Perform any necessary logic based on action (1: Start, 2: Stop)

    // For example, you can update a database or trigger an action

    const tanks = await Tank.find({});

    let motor_stop_status = null;

    for (let tank of tanks) {
      const inputConnections = tank.connections.inputConnections;
      const motorConnection = inputConnections.find(conn => conn.motor_id === motor_id);
      if (motorConnection) {
        // Check if motor_on_type is "forced_manual" and motor_stop_status is "1"
        if (motorConnection.motor_on_type === "forced_manual" && motorConnection.motor_stop_status === "1") {
            motor_stop_status = "2"; // Send motor_stop_status as "2"
        } else {
            motor_stop_status = motorConnection.motor_stop_status; // Otherwise, assign its original value
        }
    
        break;
    }
    
    }

    if (!motor_stop_status) {
      return reply.status(404).send({
        status_code: 404,
        message: 'Motor not found for the specified motor_id'
      });
    }

    reply.send({
      status_code: 200,
      motor_stop_status: motor_stop_status
    });
  } catch (err) {
    throw boom.boomify(err);
  }
};


exports.readMotorStatusFromIot = async (req, reply) => {
  try {
    const motor_id = req.query.motor_id;
    console.log(motor_id)

    // Find the tank that contains the specified motor_id in its inputConnections
    const tank = await Tank.findOne({ "connections.inputConnections.motor_id": motor_id });

    if (!tank) {
      return reply.status(404).send({
        status_code: 404,
        message: 'Motor not found for the specified motor_id'
      });
    }

    // Find the inputConnection with the specified motor_id
    const inputConnection = tank.connections.inputConnections.find(conn => conn.motor_id === motor_id);

    // Extract motor_status and motor_stop_status from the inputConnection
    const motor_status = inputConnection.motor_status;
    const motor_stop_status = inputConnection.motor_stop_status;

    // Send the response with motor_status and motor_stop_status
    reply.send({
      status_code: 200,
      motor_status: motor_status,
      motor_stop_status: motor_stop_status
    });
  } catch (err) {
    throw boom.boomify(err);
  }
};



exports.writeMotorStatus = async (req, reply) => {
  try {
    const motor_id = req.body.motor_id;
    const status = req.body.status;

    // Find the tank that contains the specified motor_id in its inputConnections
    const tank = await Tank.findOne({ "connections.inputConnections.motor_id": motor_id });

    if (!tank) {
      return reply.status(404).send({
        status_code: 404,
        message: 'Motor not found for the specified motor_id'
      });
    }

    // Find the inputConnection with the specified motor_id
    const inputConnection = tank.connections.inputConnections.find(conn => conn.motor_id === motor_id);
    
    // Update the motor_status of the inputConnection
    inputConnection.motor_status = status;
     

    // Save the updated tank
    await tank.save();

    // Send the response with the updated motor_status
    reply.send({
      status_code: 200,
      motor_status: status
    });
  } catch (err) {
    throw boom.boomify(err);
  }
};




exports.changeMotorStatus = async (req, reply) => {
  try {
    const motor_id = req.body.motor_id;
    const action = req.body.action;

    // Perform any necessary logic to handle motor status update from the device

    // For example, update a database with the new status, current, and temp values

    await Tank.updateOne(
      {  "connections.inputConnections.motor_id": motor_id },
      { 
        $set: { 
          "connections.inputConnections.$.motor_stop_status":action ,
         
        }
      }
    );

    // Send immediat

    // Fetch the motor_status for the given motor_id
   

    // Send the response with motor_stop_status and motor_status
    reply.send({
      status_code: 200,
      motor_stop_status: action,
     // motor_status: updatedMotor.motor_status  // Assuming motor_status is a field in your Tank model
    });

    
  } catch (err) {
    throw boom.boomify(err);
  }
};




exports.motortemperature = async (req, reply) => {

  try {
    const motor_id = req.params.motor_id;
    console.log(motor_id)
    
    const motorInfo = await Tank.findOne({ motor_id: motor_id });

  console.log(motorInfo)
    

    //return update;
      
    reply.send({ status_code: 200,temperature:motorInfo.motor_temperfature});



  } 
  catch (err) {
    throw boom.boomify(err);
  }
};

exports.update_auto_mode = async (req, reply) => {
  try {
    const customerId = req.params.customerId;
    const { motor_id, auto_mode } = req.body;

    // Update inputConnections' auto_mode
    await Tank.updateOne(
      { customerId: customerId, "connections.inputConnections.motor_id": motor_id },
      { $set: { "connections.inputConnections.$.auto_mode": auto_mode } }
    );

   

    reply.send({ status_code: 200, message: "Auto mode and percentages updated successfully." });
  } catch (error) {
    throw boom.boomify(error);
  }
};

exports.update_auto_percentage = async (req, reply) => {
  try {
    const customerId = req.params.customerId;
    const { tankName,tankLocation, auto_min_percentage, auto_max_percentage } = req.body;

    // Update inputConnections' auto_mode
   

    // Update auto_min_percentage and auto_max_percentage
    await Tank.updateOne(
      { customerId: customerId,tankLocation, tankName},
      {
        $set: {
          "auto_min_percentage": auto_min_percentage,
          "auto_max_percentage": auto_max_percentage
        }
      }
    );

    reply.send({ status_code: 200, message: "Auto mode and percentages updated successfully." });
  } catch (error) {
    throw boom.boomify(error);
  }
};


//storing water level for every 15 minutes

const getFormattedISTTime = () => {
  return moment().tz('Asia/Kolkata').format('DD-MM-YYYY hh:mm:ss A');
};

const storeWaterLevels = async () => {
  try {
    const tanks = await Tank.find({});
    const currentTime = getFormattedISTTime();
    
    const waterLevelRecords = tanks.map(tank => ({
      customerId: tank.customerId,
      tankName: tank.tankName,
      tankLocation: tank.tankLocation,
      waterlevel: tank.waterlevel,
      time: currentTime
    }));
    
    await TankWaterLevel.insertMany(waterLevelRecords);
    console.log('Water levels stored successfully');
  } catch (error) {
    console.error('Error storing water levels:', error);
  }
};

setInterval(storeWaterLevels, 15 * 60 * 1000); 




console.log('Cron job scheduled to update water levels at midnight');


exports.getBlockData = async (req, reply) => {
  try {
    const customerId = req.params.customerId;

    // Get all tank documents for the current customerId
    const tanks = await Tank.find({ customerId });

    // Extract the blockName from each tank
    const blockNames = tanks.map(tank => tank.blockName);

    // Remove duplicates by converting the array to a Set and then back to an array
    const uniqueBlockNames = [...new Set(blockNames)];

    // Add "all" and "nduku sneha antha kopam" to the block names
    uniqueBlockNames.unshift("All");

    // Send the unique blockNames in the response
    reply.code(200).send({ blockNames: uniqueBlockNames });

  } catch (err) {
    // Log the error for debugging purposes
    console.error(err);

    // Send an error response
    reply.code(500).send({ error: err.message });
  }
};



// const mqtt = require('mqtt');
// // const moment = require('moment-timezone');
// // const IotData = require('./models/IotData'); // Replace with your actual model
// // const Tank = require('./models/Tank'); // Replace with your actual model

// // A map to keep track of MQTT clients by hw_Id
// const mqttClients = new Map();

// // Function to create a new MQTT client for a specific hw_Id
// function createMqttClient(hw_Id) {
//   const client = mqtt.connect('mqtt://35.207.198.4:1883'); // Connect to the MQTT broker

//   client.on('connect', () => {
//     console.log(`Client for hw_Id ${hw_Id} connected to MQTT broker`);
//     client.subscribe('water/iot-data', (err) => {
//       if (err) {
//         console.error(`Error subscribing to topic for hw_Id ${hw_Id}:`, err);
//       } else {
//         console.log(`Client for hw_Id ${hw_Id} subscribed to water/iot-data topic`);
//       }
//     });
//   });

//   client.on('message', async (topic, message) => {
//     if (topic === 'water/iot-data') {
//       try {
//         const data = JSON.parse(message.toString());
//         const { hw_Id: receivedHwId, Motor_status, tanks } = data.objects;

//         // Ensure we process data only for the current client
//         if (receivedHwId !== hw_Id) return;

//         // Get the current date and time
//         const currentDate = new Date();
//         const date = currentDate.toISOString(); // ISO string for date
//         const time = currentDate.toLocaleTimeString('en-IN', { hour12: false, timeZone: 'Asia/Kolkata' }); // Time in 'HH:MM:SS'

//         // Create tank documents for the received tanks
//         const tankDocuments = tanks.map(tank => ({
//           tankhardwareId: tank.Id,
//           tankHeight: tank.level,
//           date,
//           time
//         }));

//         // Save IoT data
//         const iotTankData = new IotData({
//           hardwareId: receivedHwId,
//           Motor_status,
//           tanks: tankDocuments,
//           date,
//           time
//         });
//         await iotTankData.save();

//         // Delete excess records (keep only the latest three)
//         const recordsToKeep = 3;
//         const recordsToDelete = await IotData.find({ hardwareId: receivedHwId })
//           .sort({ date: -1, time: -1 })
//           .skip(recordsToKeep);

//         for (const record of recordsToDelete) {
//           await record.remove();
//         }

//         // Process tanks
//         for (const tank of tanks) {
//           const { Id: tankhardwareId, level: tankHeight } = tank;
//           const existingTank = await Tank.findOne({ hardwareId: receivedHwId, tankhardwareId });
//           if (!existingTank) continue;

//           const customerId = existingTank.customerId;
//           const tank_name = existingTank.tankName;

//           const tankHeightInCm = (parseInt(existingTank.height.replace(/,/g, ''), 10)) * 30.48;
//           const tank_height = parseInt(tankHeightInCm.toFixed(0), 10);
//           const waterLevelHeight = tank_height - tankHeight;
//           const waterCapacityPerCm = parseInt(existingTank.waterCapacityPerCm.replace(/,/g, ''), 10);

//           const waterLevel = parseInt(waterLevelHeight * waterCapacityPerCm, 10);

//           if (tankHeight > 0 && waterLevel >= 0) {
//             existingTank.waterlevel = waterLevel;
//             await existingTank.save();

//             for (const outputConnection of existingTank.connections.outputConnections) {
//               const linkedTank = await Tank.findOne({
//                 customerId,
//                 tankName: outputConnection.outputConnections,
//                 tankLocation: outputConnection.output_type
//               });
//               if (linkedTank) {
//                 for (const inputConnection of linkedTank.connections.inputConnections) {
//                   if (inputConnection.inputConnections === tank_name) {
//                     inputConnection.water_level = waterLevel;
//                     await linkedTank.save();
//                   }
//                 }
//               }
//             }
//           }
//         }

//         // Update motor status
//         const status = Motor_status;
//         const motorTank = await Tank.findOne({ "connections.inputConnections.motor_id": receivedHwId });

//         if (motorTank) {
//           const inputConnection = motorTank.connections.inputConnections.find(conn => conn.motor_id === receivedHwId);
//           if (inputConnection) {
//             inputConnection.motor_status = status;
//             if (inputConnection.motor_stop_status === "1" && status === 2 && inputConnection.motor_on_type !== "forced_manual") {
//               const currentTime = moment().tz('Asia/Kolkata').format('DD-MMM-YYYY - HH:mm');
//               inputConnection.motor_stop_status = "2";
//               inputConnection.motor_on_type = "forced_manual";
//               inputConnection.startTime = currentTime;
//             }

//             if (inputConnection.motor_stop_status === "2" && status === 1) {
//               inputConnection.motor_stop_status = "1";
//             }

//             await motorTank.save();
//           }
//         }

//         console.log(`Data processed successfully for hw_Id: ${receivedHwId}`);
//       } catch (err) {
//         console.error(`Error processing message for hw_Id ${hw_Id}:`, err.message);
//       }
//     }
//   });

//   return client;
// }

// // Handle incoming MQTT messages for water/iot-data topic
// const mainClient = mqtt.connect('mqtt://35.207.198.4:1883');
// mainClient.on('connect', () => {
//   console.log('Main client connected to MQTT broker');
//   mainClient.subscribe('water/iot-data', (err) => {
//     if (err) {
//       console.error('Error subscribing to water/iot-data topic:', err);
//     }
//   });
// });

// mainClient.on('message', (topic, message) => {
//   if (topic === 'water/iot-data') {
//     try {
//       const data = JSON.parse(message.toString());
//       const { hw_Id } = data.objects;

//       if (!mqttClients.has(hw_Id)) {
//         const client = createMqttClient(hw_Id);
//         mqttClients.set(hw_Id, client);
//       }
//     } catch (err) {
//       console.error('Error handling message in main client:', err.message);
//     }
//   }
// });


const mqtt = require('mqtt');
const { setMaxIdleHTTPParsers } = require('http');
const client = mqtt.connect('mqtt://35.207.198.4:1883'); // Connect to MQTT broker

client.on('connect', () => {
  console.log('Connected to MQTT broker');
  client.subscribe('water/iot-data', (err) => {
    if (err) {
      console.error('Error subscribing to topic:', err);
    } else {
      console.log('Subscribed to water/iot-data topic');
    }
  });
});

// Handling incoming MQTT messages
client.on('message', async (topic, message) => {
  console.log(`Message received on topic ${topic}:`, message.toString());

  if (topic === 'water/iot-data') {
    try {
      const data = JSON.parse(message.toString());
      const { hw_Id, Motor_status, tanks } = data.objects; // Updated variable names according to new format

      // Get the current date and time in the required format
      const currentDate = new Date();
      const date = currentDate.toISOString(); // ISO string for date
      const time = currentDate.toLocaleTimeString('en-IN', { hour12: false, timeZone: 'Asia/Kolkata' }); // Time in 'HH:MM:SS'

      // Create array of tank documents with current date and time
      const tankDocuments = tanks.map(tank => ({
        tankhardwareId: tank.Id, // Updated to match the new format
        tankHeight: tank.level,   // Updated to match the new format
        date,
        time
      }));

      

      // Save IoT data for the received tanks
      const iotTankData = new IotData({
        hardwareId: hw_Id,       // Updated variable name
        Motor_status,
        tanks: tankDocuments,
        date,
        time
      });
      await iotTankData.save();

      // Delete excess records (keep only the latest three records)
      const recordsToKeep = 3;
      const recordsToDelete = await IotData.find({ hardwareId: hw_Id }) // Updated variable name
        .sort({ date: -1, time: -1 })
        .skip(recordsToKeep);

      for (const record of recordsToDelete) {
        await record.remove();
      }

      // Process each tank to update water level and connections
      for (const tank of tanks) {
        const { Id: tankhardwareId, level: tankHeight } = tank; // Updated to match the new format
        // Find the corresponding tank in the Tank schema using hardwareId and tankhardwareId
        const existingTank = await Tank.findOne({ hardwareId: hw_Id, tankhardwareId }); // Updated variable name
        if (!existingTank) continue;

        const customerId = existingTank.customerId;
        const tank_name = existingTank.tankName;

        // Calculate water level using tank height and capacity
        const tankHeightInCm = (parseInt(existingTank.height.replace(/,/g, ''), 10)) * 30.48; // Convert height to cm
        const tank_height = parseInt(tankHeightInCm.toFixed(0), 10);
        const waterLevelHeight = tank_height - tankHeight;
        const waterCapacityPerCm = parseInt(existingTank.waterCapacityPerCm.replace(/,/g, ''), 10);

        const waterLevel = parseInt(waterLevelHeight * waterCapacityPerCm, 10); // Calculated water level

        // Update water level in the existing tank
        console.log(tankHeight,"this is located in tank controllers at iot-data mqtt sub ")
        if (tankHeight>0 && waterLevel >= 0) {
          existingTank.waterlevel = waterLevel;
          await existingTank.save();

          // Update linked tanks (input/output connections)
          for (const outputConnection of existingTank.connections.outputConnections) {
            const linkedTank = await Tank.findOne({ customerId, tankName: outputConnection.outputConnections, tankLocation: outputConnection.output_type });
            if (linkedTank) {
              for (const inputConnection of linkedTank.connections.inputConnections) {
                if (inputConnection.inputConnections === tank_name) {
                  inputConnection.water_level = waterLevel; // Update water level for linked tank
                  await linkedTank.save(); // Save updated linked tank
                }
              }
            }
          }
        }
      }

      // Update motor status
      const status = Motor_status;
      const motorTank = await Tank.findOne({ "connections.inputConnections.motor_id": hw_Id }); // Updated variable name

      if (!motorTank) {
        console.log('Motor not found for the specified motor_id');
        return;
      }

      // Find the inputConnection for the motor and update motor status
      const inputConnection = motorTank.connections.inputConnections.find(conn => conn.motor_id === hw_Id); // Updated variable name
      if (inputConnection) {
        inputConnection.motor_status = status; // Update motor status
        const tankName = motorTank.tankName;
        if (inputConnection.motor_stop_status === "1" && status === 2 && inputConnection.motor_on_type !== "forced_manual") {
          const currentTime = moment().tz('Asia/Kolkata').format('DD-MMM-YYYY - HH:mm'); 
          inputConnection.motor_stop_status = "2";
          inputConnection.motor_on_type = "forced_manual";
          inputConnection.startTime = currentTime;
             // Emit motor start notification with tankName
          // eventEmitter.emit(
          //   "sendMotorStartNotification",
          //   fcmToken,        // FCM tokens
          //   hw_Id,           // Motor ID
          //   inputConnection.water_level || 0, // Water level
          //   motorTank.blockName || "N/A",     // Block name
          //   tankName,        // Tank name
          //   inputConnection.motor_on_type,   // Motor on type
          //   "threshold",     // Stop criteria
          //   manual_threshold_time // Threshold time in mins
          // );

          // Define logic to determine stopCriteria
                let stopCriteria = ""; 
                let highThreshold = 90; // Example high threshold value

                let stopConditionMessage = "";
                if (stopCriteria === "manual") {
                  stopConditionMessage = `Will stop at Manually \n`;
                } else if (stopCriteria === "highThreshold") {
                  stopConditionMessage = `🚨 Pump will stop when the water level reaches the high threshold of ${highThreshold}%.\n`;
                }

                // Emit the event
                try {
                  eventEmitter.emit("sendMotorStartNotification", 
                    fcmToken,
                    motorTank.blockName || "N/A",
                    motorTank.tankName,
                    "Forced Manual",
                    stopCriteria,
                    motorTank.typeOfWater || "Drinking Water",
                    highThreshold
                  );
                } catch (error) {
                  console.error('Error emitting motor start notification:', error);
                }
         
        }
        
        if (inputConnection.motor_stop_status === "2" && status === 1) {
          inputConnection.motor_stop_status = "1";

          // Emit motor stop notification with tankName
          try {
            eventEmitter.emit("sendMotorStopNotification", 
              fcmToken,
              motorTank.blockName || "N/A",
              motorTank.tankName,
              "Forced Manual",
              motorTank.typeOfWater || "Drinking Water"
            );
          } catch (error) {
            console.error('Error emitting motor stop notification:', error);
          }
        }
        
        await motorTank.save(); 
      }

      console.log('Data processed successfully for hardwareId:', hw_Id); // Updated variable name

    } catch (err) {
      console.error('Error processing message:', err.message);
    }
  }
});




exports.getPendingAndCompletedsurveyOfparticularInstaller = async (request, reply) => {
  try {
    const { installationId } = request.params;
    const survey_status = request.body;

    
    const surveydata = await User.find({
      installationId,
      survey_status,
     
    });


    // Send the response, including both total consumption and filtered consumption records
    reply.send({
      status_code: 200,
      surveydata,
    
    });
  } catch (err) {
    throw boom.boomify(err);
  }
};





exports.consumptionofparticulartank = async (request, reply) => {
  try {
    const { customerId } = request.params;
    const { startDate, stopDate, tankName, tankLocation, block } = request.body;

    // Convert input dates into proper JavaScript Date objects for comparison
    const start = moment(startDate, "DD-MMM-YYYY - HH:mm").toDate();
    const end = moment(stopDate, "DD-MMM-YYYY - HH:mm").toDate();

    // Find the tank by customerId, tankLocation, and tankName
    const tank = await Tank.findOne({
      customerId,
      tankLocation: tankLocation || "overhead", // Default to "overhead" if not provided
      tankName,
    });

    if (!tank) {
      return reply.status(404).send({
        status_code: 404,
        message: "Tank not found",
      });
    }

    const waterlevel_at_midnight = parseInt(tank.waterlevel_at_midnight.replace(/,/g, ""), 10);
    const total_water_added_from_midnight = parseInt(tank.total_water_added_from_midnight.replace(/,/g, ""), 10);
    const waterlevel = parseInt(tank.waterlevel.replace(/,/g, ""), 10);

    // Fetch all records for the tank (no date filtering yet)
    const tankConsumptions = await TankConsumptionOriginalSchema.find({
      customerId,
      tankName,
      tankLocation: tankLocation,
    });

    // Filter records in JavaScript by comparing the 'time' field after converting to Date
    const filteredConsumptions = tankConsumptions.filter((record) => {
      const recordTime = moment(record.time, "DD-MMM-YYYY - HH:mm").toDate();
      return recordTime >= start && recordTime <= end;
    });

    // Sort filtered records by date (ascending)
    filteredConsumptions.sort((a, b) => {
      const dateA = moment(a.time, "DD-MMM-YYYY - HH:mm").toDate();
      const dateB = moment(b.time, "DD-MMM-YYYY - HH:mm").toDate();
      return dateA - dateB; // Sort in ascending order
    });

    // Calculate total consumption from filtered records
    const total_consumption_from_records = filteredConsumptions.reduce((acc, record) => {
      return acc + parseInt(record.consumption, 10);
    }, 0);

    // Calculate final consumption
    const consumption = (waterlevel_at_midnight + total_water_added_from_midnight) - waterlevel + total_consumption_from_records;

    // Prepare response data
    const tankData = {
      tankname: tank.tankName,
      totalConsumption: consumption,
      block: tank.blockName,
      TypeofWater: tank.typeOfWater,
      location: tank.tankLocation,
      capacity: tank.capacity,
      waterlevel: tank.waterlevel,
    };

    // Send the response, including both total consumption and filtered consumption records
    reply.send({
      status_code: 200,
      tankData,
      totalConsumption: consumption,
      consumptionRecords: filteredConsumptions,
    });
  } catch (err) {
    throw boom.boomify(err);
  }
};


// // Set start and end dates
// const startDate = new Date("2024-08-20T00:00:00Z");
// const endDate = new Date("2024-11-04T00:00:00Z");

// // Tank names array with respective blocks
// const tanks = [
//     { tankName: "REAL TANK OH", block: "A" },
//     { tankName: "DUMMY TANK OH1", block: "BLOCK C" },
//     { tankName: "DUMMY TANK OH2", block: "BLOCK D" },
//     { tankName: "DUMMY TANK OH3", block: "BLOCK C" },
//     { tankName: "DUMMY TANK OH4", block: "BLOCK C" },
//     { tankName: "DUMMY TANK OH5", block: "BLOCK C" },
//     { tankName: "DUMMY TANK OH6", block: "BLOCK C" }
// ];

// const customerId = "AWSUSKY4";
// const tankLocation = "overhead";
// const typeofwater = "Bore Water";

// // Function to format date to "DD-MMM-YYYY - HH:mm"
// function formatDateCustom(date) {
//     const options = { day: '2-digit', month: 'short', year: 'numeric' };
//     return date.toLocaleDateString('en-GB', options).replace(/ /g, '-') + " - 23:55";
// }

// // Main function to generate data
// async function generateData() {
//     for (let date = new Date(startDate); date <= endDate; date.setDate(date.getDate() + 1)) {
//         const formattedDate = formatDateCustom(date); // Format date to "DD-MMM-YYYY - 23:55"

//         for (const { tankName, block } of tanks) {
//             try {
//                 const existingRecord = await TankConsumptionOriginalSchema.findOne({
//                     customerId: customerId,
//                     tankName: tankName,
//                     tankLocation: tankLocation,
//                     time: formattedDate
//                 }).exec();

//                 console.log(`Checking record for ${tankName} on ${formattedDate}: ${existingRecord ? 'Exists' : 'Does not exist'}`);

//                 if (!existingRecord) {
//                     // Random consumption between 7000 and 8000
//                     const randomConsumption = Math.floor(Math.random() * (8000 - 7000 + 1)) + 7000;

//                     // Create a new document and save it
//                     const newRecord = new TankConsumptionOriginalSchema({
//                         customerId: customerId,
//                         tankName: tankName,
//                         tankLocation: tankLocation,
//                         consumption: randomConsumption.toString(),
//                         time: formattedDate,
//                         block: block,
//                         typeofwater: typeofwater,
//                         __v: 0
//                     });
//                     await newRecord.save(); // Use .save() method to insert the record
//                     console.log(`Inserted record for ${tankName} on ${formattedDate}`);
//                 }
//             } catch (error) {
//                 console.error(`Failed to check or insert record for ${tankName} on ${formattedDate}:`, error);
//             }
//         }
//     }
//     console.log("Data generation complete.");
// }

// // Run the data generation function
// generateData();


async function removeDuplicates () {
  try {
      // Step 1: Find duplicates, considering time and ignoring case for typeofwater
      const duplicates = await TankConsumptionOriginalSchema.aggregate([
          {
              $group: {
                  _id: {
                      customerId: "$customerId",
                      tankName: "$tankName",
                      time: "$time"
                  },
                  count: { $sum: 1 },
                  ids: { $push: "$_id" }, // Store the _id values for further processing
                  latestConsumption: { $max: { $toInt: "$consumption" } }, // Get the max consumption
                  latestTypeofwater: { $last: "$typeofwater" } // Get the last typeofwater value
              }
          },
          {
              $match: {
                  count: { $gt: 1 } // Only keep groups with more than one occurrence
              }
          }
      ]);

      console.log(`Found ${duplicates.length} groups of duplicates.`);

      // Step 2: Prepare delete operations
      for (const duplicateGroup of duplicates) {
          // Filter the ids based on the maximum time to keep the latest entry
          const idsToDelete = duplicateGroup.ids.filter(id => {
              return id !== duplicateGroup.ids[0]; // Keep the first, delete the rest
          });

          for (const id of idsToDelete) {
              try {
                  await TankConsumptionOriginalSchema.deleteOne({ _id: id });
                  console.log(`Deleted duplicate record with ID: ${id}`);
              } catch (deleteError) {
                  console.error(`Failed to delete record with ID ${id}:`, deleteError);
              }
          }
      }

      console.log("Duplicate removal complete.");
  } catch (error) {
      console.error("Failed to remove duplicates:", error);
  }
}

// Run the remove duplicates function
// removeDuplicates();
console.log("this is for testing autopush,line located in tankscontroller")



// const calculateDailyConsumptionAndNotify = async () => {
//   try {
//     const today = moment().startOf("day");
//     const yesterday = moment(today).subtract(1, "days");

//     // Fetch all active users
//     const activeUsers = await User.find({  });

//     for (const user of activeUsers) {
//       const { customerId, fcmIds } = user;

//       // Fetch daily consumption for the customer
//       const consumptions = await TankConsumptionOriginalSchema.find({
//         customerId,
//         time: {
//           $gte: yesterday.format("DD-MMM-YYYY - HH:mm"),
//           $lt: today.format("DD-MMM-YYYY - HH:mm"),
//         },
//       });

//       // Calculate total consumption
//       const totalConsumption = consumptions.reduce((total, record) => {
//         return total + parseInt(record.consumption, 10);
//       }, 0);

//       // Prepare tank-wise consumption details
//       const tankDetails = consumptions.map((record) => ({
//         tankName: record.tankName,
//         consumption: record.consumption,
//       }));

//       // Send notification
//       const notificationTitle = "Daily Water Consumption Report";
//       const notificationBody = `
//         Total Consumption: ${totalConsumption} liters
//         Tank Details: ${tankDetails
//           .map((tank) => `${tank.tankName}: ${tank.consumption} liters`)
//           .join(", ")}
//       `;

//       if (fcmIds && fcmIds.length > 0) {
//         await sendNotification(fcmIds, notificationTitle, notificationBody);
//       }
//     }

//     console.log("Daily consumption notifications sent successfully.");
//   } catch (err) {
//     console.error("Error sending daily consumption notifications:", err);
//   }
// };


// cron.schedule("0 11:57 * * *", async () => {
//   console.log("Starting daily consumption notification task...");
//   await calculateDailyConsumptionAndNotify();
// });

// cron.schedule(
//   "0 9 * * *",
//   async () => {
//     console.log("Starting daily consumption notification task...");
//     await calculateDailyConsumptionAndNotify();
//   },
//   {
//     timezone: "Asia/Kolkata", // Specify the timezone
//   }
// );

// const calculateDailyConsumptionAndNotify = async () => {
//   try {
//     const today = moment().startOf("day");
//     const yesterday = moment(today).subtract(1, "days");

//     // Fetch all active users
//     const activeUsers = await User.find({});

//     for (const user of activeUsers) {
//       const { customerId, fcmIds } = user;

//       // Fetch daily consumption for the customer
//       const consumptions = await TankConsumptionOriginalSchema.find({
//         customerId,
//         time: {
//           $gte: yesterday.format("DD-MMM-YYYY - HH:mm"),
//           $lt: today.format("DD-MMM-YYYY - HH:mm"),
//         },
//       });

//       // Calculate total consumption by type of water and the water level percentage
//       const consumptionSummary = consumptions.reduce((acc, record) => {
//         const typeOfWater = record.typeOfWater; // Assuming this field exists
//         const consumption = parseInt(record.consumption, 10);
//         const waterLevel = parseInt(record.waterLevel, 10); // Assuming waterLevel is in percentage

//         if (!acc[typeOfWater]) {
//           acc[typeOfWater] = {
//             totalConsumption: 0,
//             tankDetails: [],
//             totalWaterLevel: 0,
//             count: 0,
//           };
//         }

//         acc[typeOfWater].totalConsumption += consumption;
//         acc[typeOfWater].totalWaterLevel += waterLevel;
//         acc[typeOfWater].count += 1;
//         acc[typeOfWater].tankDetails.push({
//           tankName: record.tankName,
//           consumption,
//           waterLevel,
//         });

//         return acc;
//       }, {});

//       // Prepare notification body
//       let notificationBody = "Daily Water Consumption Report:\n";
//       for (const type in consumptionSummary) {
//         const { totalConsumption, tankDetails, totalWaterLevel, count } = consumptionSummary[type];
//         const averageWaterLevel = (totalWaterLevel / count).toFixed(2); // Calculate average water level
//         console.log("averageWaterLevel",averageWaterLevel)
//         console.log("totalConsumption",totalConsumption)

//         notificationBody += `
//         Type of Water: ${type}
//         Total Consumption: ${totalConsumption} liters
//         Average Water Level: ${averageWaterLevel}%
//         `;
//         console.log("noti---" ,notificationBody += `
//         Type of Water: ${type}
//         Total Consumption: ${totalConsumption} liters
//         Average Water Level: ${averageWaterLevel}%
//         `)
//       }

//       if (fcmIds && fcmIds.length > 0) {
//         await sendNotification(fcmIds, "Daily Water Consumption Report", notificationBody);
//       }
//     }

//     console.log("Daily consumption notifications sent successfully.");
//   } catch (err) {
//     console.error("Error sending daily consumption notifications:", err);
//   }
// };


const calculateDailyConsumptionAndNotify = async () => {
  try {
    const today = moment().startOf("day");
    const yesterday = moment(today).subtract(1, "days");

    // Fetch all active users
    const activeUsers = await User.find({});

    for (const user of activeUsers) {
      const { customerId, fcmIds } = user;

      // Fetch daily consumption for the customer
      const consumptions = await TankConsumptionOriginalSchema.find({
        customerId,
        time: {
          $gte: yesterday.format("DD-MMM-YYYY - HH:mm"),
          $lt: today.format("DD-MMM-YYYY - HH:mm"),
        },
      });

      // Calculate total consumption and capacities based on water type
      let totalBoreConsumption = 0;
      let totalDrinkingConsumption = 0;
      let totalBoreCapacity = 0;
      let totalDrinkingCapacity = 0;

      for (const record of consumptions) {
        const typeOfWater = record.typeOfWater; // Assuming this field exists
        const consumption = parseInt(record.consumption, 10);
        const capacity = parseInt(record.capacity, 10); // Assuming capacity field exists

        if (typeOfWater === "bore" || typeOfWater === "Bore Water") {
          totalBoreConsumption += consumption;
          totalBoreCapacity += capacity;
        } else if (typeOfWater === "drinking" || typeOfWater === "Drinking Water") {
          totalDrinkingConsumption += consumption;
          totalDrinkingCapacity += capacity;
        }
      }

      // Calculate percentages
      const boreConsumptionPercentage = totalBoreCapacity
        ? ((totalBoreConsumption / totalBoreCapacity) * 100).toFixed(2)
        : 0;

      const drinkingConsumptionPercentage = totalDrinkingCapacity
        ? ((totalDrinkingConsumption / totalDrinkingCapacity) * 100).toFixed(2)
        : 0;

      // Prepare notification body
      const reportDate = yesterday.format("DD-MMM-YYYY");
      let notificationBody = `Daily Water Consumption Report for ${reportDate}:\n`;
      notificationBody += `Total Bore Consumption: ${totalBoreConsumption} liters\n`;
      notificationBody += `Bore Water Consumption Percentage: ${boreConsumptionPercentage}%\n`;
      notificationBody += `Total Drinking Consumption: ${totalDrinkingConsumption} liters\n`;
      notificationBody += `Drinking Water Consumption Percentage: ${drinkingConsumptionPercentage}%\n`;

      // Send notification if FCM IDs are present
      if (fcmIds && fcmIds.length > 0) {
        await sendNotification(fcmIds, "Daily Water Consumption Report", notificationBody);
      }
    }

    console.log("Daily consumption notifications sent successfully.");
  } catch (err) {
    console.error("Error sending daily consumption notifications:", err);
  }
};

// Schedule the cron job to run daily at 9 AM
cron.schedule(
  "0 9 * * *",
  async () => {
    console.log("Starting daily consumption notification task...");
    await calculateDailyConsumptionAndNotify();
  },
  {
    timezone: "Asia/Kolkata", // Specify the timezone
  }
);


const calculateConsumptionAndNotify = async () => {
  try {
    const now = moment(); // Current time
    const sixHoursAgo = moment(now).subtract(6, 'hours').startOf('hour'); // 6 hours ago

    // Fetch all active users
    const activeUsers = await User.find({});

    for (const user of activeUsers) {
      const { customerId, fcmIds } = user;

      // Fetch consumption records for the last 6 hours
      const consumptions = await TankConsumptionOriginalSchema.find({
        customerId,
        time: {
          $gte: sixHoursAgo.format("DD-MMM-YYYY - HH:mm"),
          $lt: now.format("DD-MMM-YYYY - HH:mm"),
        },
      });

      // Prepare notification body
      let notificationBody = `Water Consumption Report (From ${sixHoursAgo.format(
        "hh:mm A"
      )} to ${now.format("hh:mm A")}):\n`;
      const tankDetails = {};

      // Aggregate consumption data by tank
      for (const record of consumptions) {
        const tankName = record.tankName; // Assuming this field exists
        const tankLocation = record.tankLocation; // Assuming this field exists
        const consumption = parseInt(record.consumption, 10); // Liters consumed
        const typeOfWater = record.typeOfWater; // Type of water (e.g., bore, drinking)
        const tankCapacity = parseInt(record.capacity, 10); // Tank capacity in liters

        if (!tankDetails[tankName]) {
          tankDetails[tankName] = {
            tankLocation,
            totalConsumption: 0,
            typeOfWater,
            tankCapacity,
          };
        }
        tankDetails[tankName].totalConsumption += consumption;
      }

      // Format tank details for the notification
      for (const tankName in tankDetails) {
        const {
          tankLocation,
          totalConsumption,
          typeOfWater,
          tankCapacity,
        } = tankDetails[tankName];
        const consumptionPercentage = tankCapacity
          ? ((totalConsumption / tankCapacity) * 100).toFixed(2)
          : 0;

        notificationBody += 
        `Tank Name: ${tankName} \n`+
        `Location: ${tankLocation} \n`+
        `Total Consumption: ${totalConsumption} liters  ${consumptionPercentage}% \n`+
        `Type of Water: ${typeOfWater}`;
      }

      // Send notification if FCM IDs are present
      if (fcmIds && fcmIds.length > 0) {
        await sendNotification(fcmIds, "Water Consumption Report", notificationBody);
      }
    }

    console.log("Consumption notifications sent successfully.");
  } catch (err) {
    console.error("Error sending consumption notifications:", err);
  }
};

// Schedule notifications at 6 AM, 12 PM, 6 PM, and 12 AM
cron.schedule(
  "0 6,12,18,0 * * *", // Cron expression for the required times
  async () => {
    console.log("Starting scheduled consumption notification task...");
    await calculateConsumptionAndNotify();
  },
  {
    timezone: "Asia/Kolkata", // Specify the timezone
  }
);
