const boom = require("boom");
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken'); 
const customJwtAuth = require("../customAuthJwt");
const { Deparments } = require("../models/Department");
const { Install, SensorStock, SensorQuotation, Order, Insensors, MasterSlaveData } = require("../models/store");
const { Counter } = require("../models/User");
const { IotData, Tank } = require("../models/tanks");
const fastify = require("fastify")({
  logger: true,
  //disableRequestLogging: true,
  genReqId(req) {
    // you get access to the req here if you need it - must be a synchronous function
    return uuidv4();
  },
});


const generateTeamMemberId = async () => {
    var result = await Counter.findOneAndUpdate(
      { _id: 'teamMemberId_id' },
      { $inc: { seq: 1 } },
      { upsert: true, new: true }
    );
  
    return result.seq;
  };


exports.createTeamMember = async (request, reply) => {
    try {
      const { departmentId, firstName, phone, password,email,alternativePhone ,status} = request.body;
  
      // Check if installation exists
      const installation = await Deparments.findOne({ departmentId });
  
      if (!installation) {
        return reply.status(404).send({
          simplydata: {
            error: true,
            message: "Installation not found",
          },
        });
      }
  
      // Check if phone number already exists in the team
      const existingMember = installation.team_member.team_member.find(
        (member) => member.phone === phone
      );
  
      if (existingMember) {
        return reply.status(400).send({
          simplydata: {
            error: true,
            message: "Phone number already exists in the team",
          },
        });
      }
  
      // Hash password
      const hashedPassword = await bcrypt.hash(password, 10);

      const c_id = await generateTeamMemberId();
      const teamMemberId = `AWTM${c_id}`;
      // Create new team member
      const newTeamMember = {
        teamMemberId,
        firstName,
        phone,
        email,
        alternativePhone,
        installationTeamMemId: departmentId,
        password: hashedPassword,
        status,
      };
  
      // Add to team members array
      installation.team_member.team_member.push(newTeamMember);
      await installation.save();
  
      return reply.send({
        simplydata: {
          error: false,
          message: "Team member created successfully",
          teamMemberId: newTeamMember.teamMemberId,
        },
      });
  
    } catch (err) {
      console.error("Error creating team member:", err);
      reply.status(500).send({
        simplydata: {
          error: true,
          message: "Internal server error",
        },
      });
    }
  };
  

  exports.getTeamMembers = async (request, reply) => {
    try {
      const { departmentId } = request.params; // ✅ Get departmentId from request params
  
      // ✅ Find the department using departmentId
      const department = await Deparments.findOne({ departmentId });
  
      if (!department) {
        return reply.status(404).send({
          simplydata: {
            error: true,
            message: "Department not found",
          },
        });
      }
  
      // ✅ Extract team members from department schema
      const teamMembers = department.team_member.team_member;
  
      return reply.send({
        simplydata: {
          error: false,
          message: "Team members retrieved successfully",
          teamMembers, // ✅ Return the list of team members
        },
      });
  
    } catch (err) {
      console.error("Error fetching team members:", err);
      reply.status(500).send({
        simplydata: {
          error: true,
          message: "Internal server error",
        },
      });
    }
  };

//   exports.assignTeamMemberToQuotation = async (request, reply) => {
//     try {
//         const { installationId } = request.params; // Get installationId from URL params
//         const { teamMemberId } = request.body; // Get teamMemberId from request body

//         if (!teamMemberId) {
//             return reply.status(400).send({
//                 simplydata: {
//                     error: true,
//                     message: "teamMemberId is required",
//                 },
//             });
//         }

//         // Find installation by installationId
//         const installation = await Install.findOne({ installationId });

//         if (!installation) {
//             return reply.status(404).send({
//                 simplydata: {
//                     error: true,
//                     message: "Installation not found",
//                 },
//             });
//         }

//         // Extract team members list
//         const teamMembers = installation.team_member.team_member;

//         // Check if provided teamMemberId exists in the installation's team
//         const assignedTeamMember = teamMembers.find(member => member.teamMemberId === teamMemberId);

//         if (!assignedTeamMember) {
//             return reply.status(404).send({
//                 simplydata: {
//                     error: true,
//                     message: "Team member not found in this installation",
//                 },
//             });
//         }

//         // Here, you would save the assigned team member to the quotation (modify as needed)
//         const quotation = {
//             installationId,
//             assignedTeamMember
//         };

//         return reply.send({
//             simplydata: {
//                 error: false,
//                 message: "Team member assigned to quotation successfully",
//                 quotation
//             },
//         });

//     } catch (err) {
//         console.error("Error assigning team member to quotation:", err);
//         reply.status(500).send({
//             simplydata: {
//                 error: true,
//                 message: "Internal server error",
//             },
//         });
//     }
// };

exports.assignTeamMemberToQuotation = async (request, reply) => {
  try {
    const { installationId } = request.params;
    const { teamMemberId, quotationId } = request.body;

    if (!teamMemberId || !quotationId) {
      return reply.status(400).send({
        simplydata: {
          error: true,
          message: "Both teamMemberId and quotationId are required",
        },
      });
    }

    // 🔹 Find installation by installationId
    const installation = await Install.findOne({ installationId });

    if (!installation) {
      return reply.status(404).send({
        simplydata: {
          error: true,
          message: "Installation not found",
        },
      });
    }

    // 🔹 Extract team members list
    const teamMembers = installation.team_member?.team_member || [];

    // 🔹 Check if the provided teamMemberId exists in the installation's team
    const assignedTeamMember = teamMembers.find(
      (member) => member.teamMemberId === teamMemberId
    );

    if (!assignedTeamMember) {
      return reply.status(404).send({
        simplydata: {
          error: true,
          message: "Team member not found in this installation",
        },
      });
    }

    // 🔹 Find or create the quotation for the given installationId
    let quotation = await Order.findOne({ installationId, quatationId: quotationId });

    if (!quotation) {
      quotation = new Order({
        installationId,
        quatationId: quotationId,
        assignedTeamMembers: [], // Ensure assignedTeamMembers array is initialized
        quatation_status: "Pending", // Default status when created
      });
    }

    // 🔹 Assign the team member to the quotation
    if (!quotation.assignedTeamMembers) {
      quotation.assignedTeamMembers = [];
    }

    if (!quotation.assignedTeamMembers.includes(teamMemberId)) {
      quotation.assignedTeamMembers.push(teamMemberId);
    }

    // 🔹 Update order status when a team member is assigned
    quotation.quatation_status = "Assigned"; // Update status

    // 🔹 Save the updated quotation in the Order schema
    await quotation.save();

    // 🔹 Update Installation schema with quotationId
    installation.quatationId = quotationId;
    await installation.save();

    return reply.send({
      simplydata: {
        error: false,
        message: "Team member assigned to quotation successfully",
        quotation,
      },
    });

  } catch (err) {
    console.error("Error assigning team member to quotation:", err);
    reply.status(500).send({
      simplydata: {
        error: true,
        message: "Internal server error",
      },
    });
  }
};

  exports.getAllInstallers = async (request, reply) => {
    try {
      const { departmentName } = request.params; // Get installationId from request params
  
      // Check if installation exists
      const installationList = await Deparments.find({ departmentName });
  
      if (!installationList) {
        return reply.status(404).send({
          simplydata: {
            error: true,
            message: "Installation not found",
          },
        });
      }
  
     
  
      return reply.send({
        simplydata: {
          error: false,
          installationList, // Return the list of team members
        },
      });
  
    } catch (err) {
      console.error("Error fetching team members:", err);
      reply.status(500).send({
        simplydata: {
          error: true,
          message: "Internal server error",
        },
      });
    }
  };
  
  exports.editTeamMember = async (request, reply) => {
    try {
      const { installationId, teamMemberId } = request.params;
      const updateData = request.body;
  
      // Find the installation
      const installation = await Install.findOne({ installationId });
  
      if (!installation) {
        return reply.status(404).send({
          simplydata: {
            error: true,
            message: "Installation not found",
          },
        });
      }
  
      // Find the team member
      let teamMember = installation.team_member.team_member.find(
        (member) => member.teamMemberId === teamMemberId
      );
  
      if (!teamMember) {
        return reply.status(404).send({
          simplydata: {
            error: true,
            message: "Team member not found",
          },
        });
      }
  
      // Update fields
      Object.assign(teamMember, updateData);
  
      // Save changes
      await installation.markModified("team_member.team_member");
      await installation.save();
  
      return reply.send({
        simplydata: {
          error: false,
          message: "Team member updated successfully",
        },
      });
  
    } catch (err) {
      console.error("Error updating team member:", err);
      reply.status(500).send({
        simplydata: {
          error: true,
          message: "Internal server error",
        },
      });
    }
  };

  exports.deleteTeamMember = async (request, reply) => {
    try {
      const { installationId, teamMemberId } = request.params;
  
      // Find the installation
      const installation = await Install.findOne({ installationId });
  
      if (!installation) {
        return reply.status(404).send({
          simplydata: {
            error: true,
            message: "Installation not found",
          },
        });
      }
  
      // Find index of the team member
      const memberIndex = installation.team_member.team_member.findIndex(
        (member) => member.teamMemberId === teamMemberId
      );
  
      if (memberIndex === -1) {
        return reply.status(404).send({
          simplydata: {
            error: true,
            message: "Team member not found",
          },
        });
      }
  
      // Remove the team member from the array
      installation.team_member.team_member.splice(memberIndex, 1);
  
      // Save changes
      await installation.markModified("team_member.team_member");
      await installation.save();
  
      return reply.send({
        simplydata: {
          error: false,
          message: "Team member deleted successfully",
        },
      });
  
    } catch (err) {
      console.error("Error deleting team member:", err);
      reply.status(500).send({
        simplydata: {
          error: true,
          message: "Internal server error",
        },
      });
    }
  };
  

  exports.getQuotationsByInstallationId = async (request, reply) => {
    try {
      const { installationId } = request.params;
  
      if (!installationId) {
        return reply.status(400).send({
          simplydata: {
            error: true,
            message: "Installation ID is required",
          },
        });
      }
  
      // 🔹 Fetch quotations based on installationId
      const quotations = await Order.find({ installationId });
  
      if (!quotations || quotations.length === 0) {
        return reply.status(404).send({
          simplydata: {
            error: true,
            message: "No quotations found for this installation ID",
          },
        });
      }
  
      return reply.send({
        simplydata: {
          error: false,
          message: "Quotations fetched successfully",
          quotations,
        },
      });
    } catch (err) {
      console.error("Error fetching quotations:", err);
      reply.status(500).send({
        simplydata: {
          error: true,
          message: "Internal server error",
        },
      });
    }
  };
  
  exports.getQuotationsByInstallationAndTeamMember = async (request, reply) => {
    try {
      const { installationId, teamMemberId } = request.params;
  
      if (!installationId || !teamMemberId) {
        return reply.status(400).send({
          simplydata: {
            error: true,
            message: "Both installationId and teamMemberId are required",
          },
        });
      }
  
      // 🔹 Fetch quotations where installationId matches and teamMemberId is assigned
      const quotations = await Order.find({
        installationId,
        assignedTeamMembers: teamMemberId,
      });
  
      if (!quotations || quotations.length === 0) {
        return reply.status(404).send({
          simplydata: {
            error: true,
            message: "No quotations found for this installation and team member",
          },
        });
      }
  
      return reply.send({
        simplydata: {
          error: false,
          message: "Quotations fetched successfully",
          quotations,
        },
      });
    } catch (err) {
      console.error("Error fetching quotations:", err);
      reply.status(500).send({
        simplydata: {
          error: true,
          message: "Internal server error",
        },
      });
    }
  };

  exports.getDepartmentByFirstName = async (req, reply) => {
    try {
      let { firstName } = req.params;
  
      if (!firstName) {
        return reply.status(400).send({
          simplydata: { error: true, message: "firstName is required" },
        });
      }
  
      // Trim and convert to lowercase
      firstName = firstName.trim().toLowerCase();
      console.log("Searching for firstName:", firstName); // Debugging log
  
      // Search for the department with case-insensitive and space-tolerant regex
      const department = await Deparments.findOne({
        firstName: { $regex: `^\\s*${firstName}\\s*$`, $options: "i" }
      }).lean();
  
      console.log("Department found:", department); // Debugging log
  
      if (!department) {
        return reply.status(404).send({
          simplydata: { error: true, message: "Department not found" },
        });
      }
  
      return reply.send({
        simplydata: {
          error: false,
          message: "Department details fetched successfully",
          firstName: department.firstName,
          phone: department.phone,
        },
      });
  
    } catch (err) {
      console.error("Error fetching department details:", err);
      return reply.status(500).send({
        simplydata: { error: true, message: "Internal server error" },
      });
    }
  };


  exports.getByHardwareId = async (req, reply) => {
    try {
      const { hardwareId } = req.params;
      
      if (!hardwareId) {
        return reply.status(400).send({ error: "hardwareId is required" });
      }
  
      console.log("Fetching details for hardwareId:", hardwareId);
  
      // Fetch only required fields to reduce response size
      // const data = await Collection.findOne({ hardwareId })
      //   .select("hardwareId mode tanks date time") // Select only needed fields
      //   .lean();

      const data = await IotData.find({ hardwareId });

  
      if (!data) {
        return reply.send({ status_code: 404, message: "Data not found", data: null });
      }
  
      return reply.send({ status_code: 200, message: "Success", data });
    } catch (err) {
      console.error("Error:", err);
      return reply.status(500).send({ error: "Internal Server Error" });
    }
  };

  
  exports.getByHardwareAndTankId = async (req, reply) => {
    try {
      const { hardwareId, tankhardwareId } = req.params;
  
      if (!hardwareId || !tankhardwareId) {
        return reply.status(400).send({ error: "Both hardwareId and tankhardwareId are required" });
      }
  
      console.log("Fetching details for:", { hardwareId, tankhardwareId });
  
      // Correct query using $elemMatch
      const data = await IotData.findOne(
        { hardwareId, tanks: { $elemMatch: { tankhardwareId } } },
        { "tanks.$": 1, hardwareId: 1, mode: 1, date: 1, time: 1 } // Projection to return only matched tank
      );
  
      if (!data) {
        return reply.send({ status_code: 404, message: "Data not found", data: null });
      }
  
      return reply.send({ status_code: 200, message: "Success", data });
    } catch (err) {
      console.error("Error:", err);
      return reply.status(500).send({ error: "Internal Server Error" });
    }
  };
  
  
  
exports.getAllocatedSensorsByTank = async (req, reply) => {
  try {
    let { customerId, tankName } = req.params;

    if (!customerId || !tankName) {
      return reply.status(400).send({ error: "customerId and tankName are required" });
    }

    tankName = tankName.trim(); // Trim spaces

    console.log("Querying MongoDB with:", { customerId, tankName, status: "blocked" });

    const allocatedSensors = await Insensors.find({
      customerId,
      tankName: { $regex: `^${tankName}$`, $options: "i" }, // Case-insensitive search
      status: "blocked",
    }).lean();

    if (!allocatedSensors.length) {
      return reply.send({
        status_code: 200,
        message: "No allocated sensors found for this tank",
        allocatedSensors: [],
      });
    }

    return reply.send({
      status_code: 200,
      message: "Allocated sensors fetched successfully",
      allocatedSensors,
    });

  } catch (err) {
    console.error("Error fetching allocated sensors:", err);
    return reply.status(500).send({ error: "Internal server error" });
  }
};

exports.createMasterSlaveData = async (req, reply) => {
  try {
    const { installationId } = req.params; 
    const {
      type,
      hardwareId,
      batchno,
      masterId,
      tankName,
      tankLocation,
      materialRecived,
      electicityWork,
      plumbingWork,
      loraCheck
    } = req.body; 

    if (!installationId || !hardwareId || !masterId) {
      return reply.status(400).send({ message: "installationId, hardwareId, and masterId are required." });
    }

    const newData = new MasterSlaveData({
      installationId,
      type,
      hardwareId,
      batchno,
      masterId,
      tankName,
      tankLocation,
      materialRecived,
      electicityWork,
      plumbingWork,
      loraCheck
    });

    // Save to database
    await newData.save();

    reply.status(201).send({ message: "Master-Slave data created successfully", data: newData });
  } catch (err) {
    reply.status(500).send({ message: err.message });
  }
};
