const boom = require("boom");
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken'); 
const customJwtAuth = require("../customAuthJwt");
const mongoose = require("mongoose");

const fastify = require("fastify")({
  logger: true,
  genReqId(req) {
    return uuidv4();
  },
});
const { Counter} = require('../models/User')

const {Department, Desgination, City, Deparments, Branch, Zone,IndianLocations} = require('../models/Department')
// const generateDepartmentId = async (prefix) => {
//     const result = await Counter.findOneAndUpdate(
//       { _id: 'department_id' },
//       { $inc: { seq: 1 } },
//       { upsert: true, new: true }
//     );
//     return `AW${prefix}${result.seq}`;
//   };

const generateCityId = async () => {
    var result = await Counter.findOneAndUpdate(
      { _id: 'customer_id' },
      { $inc: { seq: 1 } },
      { upsert: true, new: true }
    );
  
    return result.seq;
  };
  const generateBranchId = async () => {
    var result = await Counter.findOneAndUpdate(
      { _id: 'customer_id' },
      { $inc: { seq: 1 } },
      { upsert: true, new: true }
    );
  
    return result.seq;
  };
//   const generateDesginationId = async (prefix) => {
//     const result = await Counter.findOneAndUpdate(
//       { _id: 'desgination_id' },
//       { $inc: { seq: 1 } },
//       { upsert: true, new: true }
//     );
//     return `AW${prefix}${result.seq}`;
//   };
  
const generateDepartmentId = async (city, departmentName) => {
    const cityPrefix = city.substring(0, 2).toUpperCase(); // Extract first two letters of city
    const departmentPrefix = departmentName.substring(0, 2).toUpperCase(); // Extract first two letters of departmentName
  
    const result = await Counter.findOneAndUpdate(
      { _id: 'desgination_id' },
      { $inc: { seq: 1 } },
      { upsert: true, new: true }
    );
  
    return `AW${cityPrefix}${departmentPrefix}${result.seq}`; // Generate ID
  };
  
  exports.addCity = async (request, reply) => {
    try {
      const {
        phone,
        officeName,
        location,
        city,
        state,
        country,
        zone,
        office_address1,
        address2,
        pincode,
        createdBy,
        updatedBy,
        email
      } = request.body;
  
      // Generate unique cityId
      const c_id = await generateCityId();
      const cityId = `AWCI${c_id}`;
  
      // Check for existing records with specific fields
      const existingPhone = await City.findOne({ phone });
      if (existingPhone) {
        return reply.status(400).send({ message: 'Phone number already exists' });
      }
  
      const existingOfficeName = await City.findOne({ officeName });
      if (existingOfficeName) {
        return reply.status(400).send({ message: 'Office name already exists' });
      }
  
      const existingCityId = await City.findOne({ cityId });
      if (existingCityId) {
        return reply.status(400).send({ message: 'City ID already exists' });
      }
  
      // Create new city record
      const citys = new City({
        cityId,
        phone,
        officeName,
        location,
        city,
        office_address1,
        address2,
        state,
        zone,
        country,
        pincode,
        email,
        createdBy,
        updatedBy,
      });
  
      await citys.save();
  
      reply.send({ citys, message: 'City Created Successfully' });
    } catch (err) {
      reply.status(500).send({ message: err.message });
    }
  };
  

  exports.addBranch = async (request, reply) => {
    try {
      const {
        phone,
        land_line_number,
        officeName,
        location,
        city,
        state,
        country,
        zone,
        office_address1,
        address2,
        pincode,
        createdBy,
        updatedBy,
        email,
        nameoftheContactPerson
      } = request.body;
  
      // Generate departmentId based on departmentName
    //   const prefix = departmentName.substring(0, 2).toUpperCase(); // Extract first two letters and convert to uppercase
       const b_id = await generateBranchId();
       const branchId = `AWBR${b_id}`;

      // Check for existing department
      const existingStore = await Branch.findOne({ branchId });
      if (existingStore) {
        return reply.status(400).send({ message: 'Branch is already registered' });
      }
  
      // Create new department
      const branch = new Branch({
        branchId,
        phone,
        land_line_number,
        officeName,
        location,
        city,
        office_address1,
        address2,
        state,
        zone,
        country,
        pincode,
        email,
        nameoftheContactPerson,
       // departmentName,
        createdBy,
        updatedBy,
      });
  
      await branch.save();
  
      reply.send({ branch, message: 'Account Created Successfully' });
    } catch (err) {
      reply.status(500).send({ message: err.message });
    }
  };

  exports.addZone = async (request, reply) => {
    try {
      const {
        officeName,
        location,
        city,
        zone,
        area,
        createdBy,
        updatedBy,
      } = request.body;
  
      // Generate departmentId based on departmentName
    //   const prefix = departmentName.substring(0, 2).toUpperCase(); // Extract first two letters and convert to uppercase
       const b_id = await generateBranchId();
       const zoneId = `AWZN${b_id}`;

      // Check for existing department
      const existingStore = await Zone.findOne({ zoneId });
      if (existingStore) {
        return reply.status(400).send({ message: 'Branch is already registered' });
      }
  
      const zones = new Zone({
        zoneId,
        officeName,
        location,
        city,
        zone,
        area,
        createdBy,
        updatedBy,
      });
  
      await zones.save();
  
      reply.send({ zones, message: 'Account Created Successfully' });
    } catch (err) {
      reply.status(500).send({ message: err.message });
    }
  };
//   exports.getSinledepartmentData = async (req, reply) => {
//     try {
//       const { departmentId } = req.params;  
  
//       const department = await Department.findOne({ departmentId: departmentId }); 
  
//       if (!department) {
//         return reply.code(404).send({
//           success: false,
//           message: 'Department not found.'
//         });
//       }
  
//       reply.code(200).send({
//         success: true,
//         message: 'Department data retrieved successfully.',
//         data: department
//       });
//     } catch (error) {
//       console.error('Error fetching department data:', error);
//       reply.code(500).send({
//         success: false,
//         message: 'Failed to retrieve department data.',
//         error: error.message,
//       });
//     }
//   };
  
exports.getallCompanyNames = async (req, reply) => {
  try {
    await City.find()
      .select("officeName -_id") // Select only officeName and exclude _id
      .exec()
      .then((docs) => {
        const officeNames = docs.map((doc) => doc.officeName); // Extract only officeName values
        reply.send({ status_code: 200, data: officeNames, count: officeNames.length });
      })
      .catch((err) => {
        console.log(err);
        reply.send({ error: err });
      });
  } catch (err) {
    throw boom.boomify(err);
  }
};


  
// exports.getAllDepartmentsParticularFields = async (req, reply) => {
//     try {
//       const departments = await Department.find().exec();
  
//       // Grouping the data
//       const result = {
//         cities: [...new Set(departments.map((doc) => doc.city))],
//         zones: [...new Set(departments.map((doc) => doc.zone))],
//         pincodes: [...new Set(departments.map((doc) => doc.pincode))],
//         departments: [...new Set(departments.map((doc) => doc.departmentName))],
//         states: [...new Set(departments.map((doc) => doc.state))],
//         countries: [...new Set(departments.map((doc) => doc.country))],
//       };
  
//       // Sending the response
//       reply.send({
//         status_code: 200,
//         data: result,
//         count: departments.length,
//       });
//     } catch (err) {
//       console.error(err);
//       reply.send({ error: err.message });
//     }
//   };
  
  
  exports.deletecityInfo = async (req, reply) => {
    try {
      const cityId = req.params.cityId;
     
      const department = await City.findOneAndDelete({ cityId:cityId });
  
      reply.send({ status_code: 200, message: 'Delete Sucessfully', department});
    } catch (err) {
      throw boom.boomify(err);
    }
  };

  exports.deleteBranchInfo = async (req, reply) => {
    try {
      const branchId = req.params.branchId;
     
      const branch = await Branch.findOneAndDelete({ branchId:branchId });
  
      reply.send({ status_code: 200, message: 'Delete Sucessfully', branch});
    } catch (err) {
      throw boom.boomify(err);
    }
  };
  exports.editcity = async (request, reply) => {
    try {
      const { cityId } = request.params;
      const {
        
        phone,
        city,
        state,
        country,
        zone,
        address1,
        address2,
        pincode,
        email,
        officeName

      } = request.body;
  
     
      const existing = await City.findOne({ cityId });
      if (!existing) {
        return reply.status(404).send({ message: 'City not found' });
      }
  
    //   const phoneExists = await Department.findOne({ phone, departmentId: { $ne: departmentId } });
    //   if (phoneExists) {
    //     return reply.status(400).send({ message: 'Phone is already registered to another user' });
    //   }
  
   
      existing.phone = phone || existing.phone;
      existing.city = city || existing.city;
      existing.state = state || existing.state;
      existing.country = country || existing.country;
      existing.zone = zone || existing.zone;
      existing.officeName = officeName || existing.officeName;
      existing.pincode = pincode || existing.pincode;

      existing.address1 = address1 || existing.address1;
      existing.address2 = address2 || existing.address2;
      existing.email = email || existing.email;


  
      await existing.save();
  
      reply.send({ message: 'City user updated successfully' });
    } catch (err) {
      reply.status(500).send({ message: err.message });
    }
  };

  exports.editBranch = async (request, reply) => {
    try {
      const { branchId } = request.params;
      const {
        
        phone,
        land_line_number,
        officeName,
        city,
        state,
        country,
        zone,
        address1,
        address2,
        pincode,
        email
       // departmentName

      } = request.body;
  
     
      const existing = await Branch.findOne({ branchId });
      if (!existing) {
        return reply.status(404).send({ message: 'Branch not found' });
      }
  
    //   const phoneExists = await Department.findOne({ phone, departmentId: { $ne: departmentId } });
    //   if (phoneExists) {
    //     return reply.status(400).send({ message: 'Phone is already registered to another user' });
    //   }
  
   
      existing.phone = phone || existing.phone;
      existing.land_line_number = land_line_number || existing.land_line_number;
      existing.city = city || existing.city;
      existing.state = state || existing.state;
      existing.country = country || existing.country;
      existing.zone = zone || existing.zone;
     existing.officeName = officeName || existing.officeName;
      existing.pincode = pincode || existing.pincode;

      existing.address1 = address1 || existing.address1;
      existing.address2 = address2 || existing.address2;
      existing.email = email || existing.email;


  
      await existing.save();
  
      reply.send({ message: 'Branch user updated successfully' });
    } catch (err) {
      reply.status(500).send({ message: err.message });
    }
  };


//   exports.addDesgination = async (request, reply) => {
//     try {
//       const {
//         phone,
//         city,
//         firstName,
//         lastName,
//         departmentName,
//         reportingManager,
//         email,
//         state,
//         password,
//         country,
//         zone,
//         address1,
//         address2,
//         pincode,
//         desginationName,
//         location,
//         createdBy,
//         updatedBy,
//       } = request.body;
  
//       // Generate desginationId based on desginationName
//       const prefix = departmentName.substring(0, 2).toUpperCase(); 
//       const desginationId = await generateDesginationId(prefix);
  
//       // Check if the phone is already registered
//       const existingStore = await Desgination.findOne({ phone });
//       if (existingStore) {
//         return reply.status(400).send({ message: 'Phone is already registered' });
//       }
  
//       // Hash the password
//       const hashedPassword = await bcrypt.hash(password, 10);
  
//       // Create a new designation
//       const desgination = new Desgination({
//         desginationId,
//         city,
//         firstName,
//         lastName,
//         email,
//         reportingManager,
//         departmentName,
//         phone,
//         address1,
//         address2,
//         services: { password: { bcrypt: hashedPassword } },
//         state,
//         zone,
//         country,
//         pincode,
//         desginationName,
//         location,
//         createdBy,
//         updatedBy,
//       });
  
//       await desgination.save();
  
//       reply.send({ desgination, message: 'Account Created Successfully' });
//     } catch (err) {
//       reply.status(500).send({ message: err.message });
//     }
//   };


exports.addDepartment = async (request, reply) => {
    try {
      const {
        phone,
        officeName,
        alternativeContactNumber,
        gender,
        personalEmail,
        city,
        personal_city,
        reportingManager_mobile_number,
        reportingManager_email,
        firstName,
        lastName,
        departmentName,
        reportingManager,
        email,
        state,
        password,
        country,
        zone,
        address1,
        address2,
        pincode,
        desginationName,
        location,
        picture,
        dateOfJoin,
        createdBy,
        updatedBy,
      } = request.body;
  
      // Generate desginationId
      const departmentId = await generateDepartmentId(city, departmentName);
  
      // Check if the phone is already registered
      const existingStore = await Deparments.findOne({ phone });
      if (existingStore) {
        return reply.status(400).send({ message: 'Phone is already registered' });
      }
  
      // Hash the password
      const hashedPassword = await bcrypt.hash(password, 10);
  
      // Create a new designation
      const department = new Deparments({
        departmentId,
        alternativeContactNumber,
        officeName,
        reportingManager_mobile_number,
        reportingManager_email,
        personal_city,
        gender,
        city,
        firstName,
        lastName,
        email,
        personalEmail,
        reportingManager,
        departmentName,
        phone,
        address1,
        address2,
        services: { password: { bcrypt: hashedPassword } },
        state,
        zone,
        country,
        pincode,
        desginationName,
        location,
        picture,
        dateOfJoin,
        createdBy,
        updatedBy,
      });
  
      await department.save();
  
      reply.send({ department, message: 'Account Created Successfully' });
    } catch (err) {
      reply.status(500).send({ message: err.message });
    }
  };
  
  exports.getSinledepartmentData = async (req, reply) => {
    try {
      const { departmentId } = req.params;  
  
      const department = await Deparments.findOne({ departmentId: departmentId }); 
  
      if (!department) {
        return reply.code(404).send({
          success: false,
          message: 'Department not found.'
        });
      }
  
      reply.code(200).send({
        success: true,
        message: 'Designation data retrieved successfully.',
        data: department
      });
    } catch (error) {
      console.error('Error fetching department data:', error);
      reply.code(500).send({
        success: false,
        message: 'Failed to retrieve department data.',
        error: error.message,
      });
    }
  };
  
  exports.getalldepartments = async (req, reply) => {
    try {
      await Deparments.find()
        .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.getallCitiesData = async (req, reply) => {
    try {
      console.log("Fetching all cities..."); // Debug log
      const cities = await City.distinct('city'); // Fetch distinct city names from the database
  
      // Normalize the city names to avoid duplicates
      const normalizedCities = [...new Set(cities.map(city => city.trim().toUpperCase()))];
  
      console.log("Cities fetched:", normalizedCities); // Log the cleaned cities
      reply.send({ status_code: 200, data: normalizedCities, count: normalizedCities.length });
    } catch (err) {
      console.error("Error fetching cities:", err); // Log the error for debugging
      throw boom.boomify(err);
    }
  };
  

  exports.getallZonesData = async (req, reply) => {
    try {
      console.log("Fetching all zones..."); // Debug log
      const zones = await City.distinct('zone'); // Fetch distinct zone names from the database
  
      // Normalize the zone names to avoid duplicates
      const normalizedZones = [...new Set(zones.map(zone => zone.trim().toUpperCase()))];
  
      console.log("Zones fetched:", normalizedZones); // Log the cleaned zones
      reply.send({ status_code: 200, data: normalizedZones, count: normalizedZones.length });
    } catch (err) {
      console.error("Error fetching zones:", err); // Log the error for debugging
      throw boom.boomify(err);
    }
  };
  
  exports.getallLocationData = async (req, reply) => {
    try {
      console.log("Fetching all locations..."); // Debug log
      const locations = await City.distinct('location'); // Fetch distinct locations from the database
  
      // Normalize the location names to uppercase and remove duplicates
      const normalizedLocations = [...new Set(locations.map(location => location.trim().toUpperCase()))];
  
      console.log("Locations fetched:", normalizedLocations); // Log the cleaned locations
      reply.send({ status_code: 200, data: normalizedLocations, count: normalizedLocations.length });
    } catch (err) {
      console.error("Error fetching locations:", err); // Log the error for debugging
      throw boom.boomify(err);
    }
  };
  
  
  exports.deletedepartmentInfo = async (req, reply) => {
    try {
      const departmentId = req.params.departmentId;
     
      const department = await Deparments.findOneAndDelete({ departmentId:departmentId });
  
      reply.send({ status_code: 200, message: 'Delete Sucessfully', department});
    } catch (err) {
      throw boom.boomify(err);
    }
  };


  exports.editdepartment = async (request, reply) => {
    try {
      const { departmentId } = request.params;
      const {
        
        phone,
        alternativeContactNumber,
        gender,
        personalEmail,
        city,
        firstName,
        lastName,
        email,
        reportingManager,
        departmentName,
        state,
        country,
        zone,
        address1,
        address2,
        pincode,
        desginationName,
        personal_city,
        reportingManager_mobile_number,
        reportingManager_email,
        officeName,


      } = request.body;
  
     
      const existing = await Deparments.findOne({ departmentId });
      if (!existing) {
        return reply.status(404).send({ message: 'Department not found' });
      }
  
      const phoneExists = await Deparments.findOne({ phone, departmentId: { $ne: departmentId } });
      if (phoneExists) {
        return reply.status(400).send({ message: 'Phone is already registered to another user' });
      }
  
   
      existing.phone = phone || existing.phone;
      existing.alternativeContactNumber = alternativeContactNumber || existing.alternativeContactNumber;
      existing.personalEmail = personalEmail || existing.personalEmail;
      existing.gender = gender || existing.gender;
      existing.city = city || existing.city;
      existing.state = state || existing.state;
      existing.country = country || existing.country;
      existing.zone = zone || existing.zone;
      existing.desginationName = desginationName || existing.desginationName;
      existing.pincode = pincode || existing.pincode;

      existing.address1 = address1 || existing.address1;
      existing.address2 = address2 || existing.address2;
      
      existing.email = email || existing.email;
      existing.firstName = firstName || existing.firstName;
      existing.lastName = lastName || existing.lastName;
      existing.departmentName = departmentName || existing.departmentName;
      existing.reportingManager = reportingManager || existing.reportingManager
       existing.personal_city = personal_city || existing.personal_city;
      existing.reportingManager_mobile_number = reportingManager_mobile_number || existing.reportingManager_mobile_number;
      existing.reportingManager_email = reportingManager_email || existing.reportingManager_email;
      existing.officeName = officeName || existing.officeName
  
      await existing.save();
  
      reply.send({ message: 'Department user updated successfully' });
    } catch (err) {
      reply.status(500).send({ message: err.message });
    }
  };
//   exports.getAllDesignationsParticularFields = async (req, reply) => {
//     try {
//       const departments = await Desgination.find().exec();
  
//       // Grouping the data
//       const result = {
//         cities: [...new Set(departments.map((doc) => doc.city))],
//         zones: [...new Set(departments.map((doc) => doc.zone))],
//         pincodes: [...new Set(departments.map((doc) => doc.pincode))],
//         departments: [...new Set(departments.map((doc) => doc.departmentName))],
//         states: [...new Set(departments.map((doc) => doc.state))],
//         countries: [...new Set(departments.map((doc) => doc.country))],
//         designations: [...new Set(departments.map((doc) => doc.desginationName))],
//         reportingMangers: [...new Set(departments.map((doc) => doc.reportingManager))],

//       };
  
//       // Sending the response
//       reply.send({
//         status_code: 200,
//         data: result,
//         count: departments.length,
//       });
//     } catch (err) {
//       console.error(err);
//       reply.send({ error: err.message });
//     }
//   };

const getLocationsByCityAndZone = async (city, zone) => {
  try {
    const matchCondition = {
      city: { $regex: `^${city.trim().toLowerCase()}$`, $options: "i" },
    };

    // If a specific zone (not "ALL") is provided, filter by that zone
    if (zone.trim().toUpperCase() !== "ALL") {
      matchCondition.zone = zone.trim();
    }

    const result = await Zone.aggregate([
      {
        $project: {
          city: { $toLower: { $trim: { input: "$city" } } },
          zone: { $trim: { input: "$zone" } },
          location: 1,
        },
      },
      {
        $match: matchCondition,
      },
      {
        $group: {
          _id: "$city",
          locations: { $push: "$location" },
        },
      },
      {
        $project: {
          _id: 0,
          city: "$_id",
          locations: {
            $reduce: {
              input: "$locations",
              initialValue: [],
              in: { $concatArrays: ["$$value", "$$this"] },
            },
          },
        },
      },
    ]);

    console.log("Query Result:", result);

    if (result.length) {
      let locations = [...new Set(result[0].locations)]; // Remove duplicates

      // Ensure "ALL" is always the first element
      if (!locations.includes("ALL")) {
        locations.unshift("ALL");
      }

      return { city, locations };
    } else {
      return { city, locations: ["ALL"] }; // If no data, return only "ALL"
    }
  } catch (err) {
    console.error(err);
    throw new Error("Error fetching locations.");
  }
};

exports.getZonebasedLocations = async (req, reply) => {
  try {
    const { city, zone } = req.query;
    console.log("Received City:", `"${city}"`, "Received Zone:", `"${zone}"`);

    if (!city || !zone) {
      return reply.status(400).send({ message: "City and zone are required." });
    }

    const locations = await getLocationsByCityAndZone(city.trim(), zone.trim());

    if (!locations) {
      return reply.send({ status_code: 404, message: "No data found." });
    }

    reply.send({ status_code: 200, data: locations });
  } catch (err) {
    reply.status(500).send({ message: err.message });
  }
};


 const getLocationsByZone = async (zone) => {
  try {
    const result = await City.aggregate([
      {
        $match: {
          zone: { $regex: `^${zone}$`, $options: "i" }, // Case-insensitive match for the zone
        },
      },
      {
        $unwind: "$location" // Unwind the location field if it is an array
      },
      {
        $group: {
          _id: "$zone", // Group by zone
          locations: { 
            $addToSet: { 
              $toUpper: { $trim: { input: "$location" } } // Convert to uppercase and trim whitespace
            } 
          }, 
        },
      },
      {
        $project: {
          _id: 0, // Exclude the _id field
          zone: "$_id", // Include zone
          locations: 1 // Return locations
        },
      },
    ]);

    return result;
  } catch (err) {
    console.error(err);
    throw new Error("Error fetching locations.");
  }
};

  
  
  exports.getLocationsByZone = async (req, reply) => {
    try {
      const { zone } = req.params; // Get zone from path params
  
      if (!zone) {
        return reply.status(400).send({ message: "Zone is required." });
      }
  
      const locations = await getLocationsByZone(zone);
      reply.send({ status_code: 200, data: locations });
    } catch (err) {
      reply.status(500).send({ message: err.message });
    }
  };
  
  const getZonesByCitys = async (city) => {
    try {
      const result = await Zone.aggregate([
        {
          $project: {
            city: { $trim: { input: "$city" } }, // Trim city field in DB
            zone: 1 // Keep zone field
          }
        },
        {
          $match: {
            city: { $regex: `^${city.trim()}$`, $options: "i" }, // Trim & case-insensitive
          }
        },
        {
          $group: {
            _id: { $toUpper: "$city" }, // Normalize city name
            zones: { $addToSet: "$zone" } // Collect unique zones
          }
        },
        {
          $project: {
            _id: 0, // Exclude _id
            city: "$_id", // Return city name
            zones: 1 // Return collected zones
          }
        }
      ]);
  
      // Add "ALL" to the zones array and sort it
      result.forEach(item => {
        item.zones = ["ALL", ...new Set(item.zones)].sort((a, b) => (a === "ALL" ? -1 : a - b));
      });
  
      return result;
    } catch (err) {
      console.error("Error fetching zones:", err);
      throw new Error("Error fetching zones.");
    }
  };
  
  
  exports.getZonesByCity = async (req, reply) => {
    try {
      const { city } = req.params;
  
      if (!city || city.trim() === "") {
        return reply.status(400).send({ message: "City is required." });
      }
  
      const zones = await getZonesByCitys(city.trim()); // Trim input
  
      if (zones.length === 0) {
        return reply.status(404).send({ message: "No zones found for the specified city." });
      }
  
      reply.send({ status_code: 200, data: zones });
    } catch (err) {
      reply.status(500).send({ message: err.message });
    }
  };
  
  const getAreasByCitys = async (city) => {
    try {
      const result = await Zone.aggregate([
        {
          $project: {
            city: { $trim: { input: "$city" } }, // Trim city field in DB
            area: 1 // Keep zone field
          }
        },
        {
          $match: {
            city: { $regex: `^${city.trim()}$`, $options: "i" }, // Trim & case-insensitive
          }
        },
        {
          $group: {
            _id: { $toUpper: "$city" }, // Normalize city name
            areas: { $addToSet: "$area" } // Collect unique zones
          }
        },
        {
          $project: {
            _id: 0, // Exclude _id
            city: "$_id", // Return city name
            areas: 1 // Return collected zones
          }
        }
      ]);
  
      // Add "ALL" to the zones array and sort it
      result.forEach(item => {
        item.areas = ["ALL", ...new Set(item.areas)].sort((a, b) => (a === "ALL" ? -1 : a - b));
      });
  
      return result;
    } catch (err) {
      console.error("Error fetching areas:", err);
      throw new Error("Error fetching areas.");
    }
  };
  exports.getAreasByCity = async (req, reply) => {
    try {
      const { city } = req.params;
  
      if (!city || city.trim() === "") {
        return reply.status(400).send({ message: "City is required." });
      }
  
      const zones = await getAreasByCitys(city.trim()); // Trim input
  
      if (zones.length === 0) {
        return reply.status(404).send({ message: "No zones found for the specified city." });
      }
  
      reply.send({ status_code: 200, data: zones });
    } catch (err) {
      reply.status(500).send({ message: err.message });
    }
  };
  
  const getZonesByArea = async (area) => {
    try {
      const result = await Zone.aggregate([
        {
          $project: {
            area: { $trim: { input: "$area" } }, // Trim area field in DB
            zone: 1 // Keep zone field
          }
        },
        {
          $match: {
            area: { $regex: `^${area.trim()}$`, $options: "i" } // Case-insensitive match on area
          }
        },
        {
          $group: {
            _id: { $toUpper: "$area" }, // Normalize area name
            zones: { $addToSet: "$zone" } // Collect unique zones
          }
        },
        {
          $project: {
            _id: 0, // Exclude _id
            area: "$_id",
            zones: 1 // Return collected zones
          }
        }
      ]);
  
      // ✅ Correct sorting: "ALL" first, then other zones in ascending order
      result.forEach(item => {
        item.zones = ["ALL", ...item.zones.filter(z => z !== "ALL").sort((a, b) => a.localeCompare(b))];
      });
  
      return result;
    } catch (err) {
      console.error("Error fetching zones:", err);
      throw new Error("Error fetching zones.");
    }
  };
  
  
  // Fastify route handler to get zones based on area only
  exports.getZonesByArea = async (req, reply) => {
    try {
      const { area } = req.params;
  
      if (!area || area.trim() === "") {
        return reply.status(400).send({ message: "Area is required." });
      }
  
      const zones = await getZonesByArea(area.trim());
  
      if (zones.length === 0) {
        return reply.status(404).send({ message: "No zones found for the specified area." });
      }
  
      reply.send({ status_code: 200, data: zones });
    } catch (err) {
      reply.status(500).send({ message: err.message });
    }
  };
  
  // const getDepartmentsByName = async (departmentName, city) => {
  //   try {
  //     const result = await Deparments.find({
  //       departmentName: { $regex: `^${departmentName.trim()}$`, $options: "i" }, // Case-insensitive search
  //       city: { $regex: `^${city.trim()}$`, $options: "i" }, // Case-insensitive search
  //     }).lean(); // Convert to plain JSON
  
  //     return result;
  //   } catch (err) {
  //     console.error("Error fetching department data:", err);
  //     throw new Error("Error fetching department data.");
  //   }
  // };
  
// Updated helper function that accepts all three parameters
const getDepartmentsByName = async (officeName, city, departmentName) => { 
  try {
    // Trim all parameters
    const trimmedOfficeName = officeName.trim();
    const trimmedCity = city.trim();
    const trimmedDepartment = departmentName.trim();

    const query = {
      officeName: { $regex: trimmedOfficeName, $options: "i" },
      departmentName: { $regex: trimmedDepartment, $options: "i" },
      city: { $regex: trimmedCity, $options: "i" }
    };

    console.log("MongoDB Query:", JSON.stringify(query, null, 2));

    const result = await Deparments.find(query).lean();

    console.log("Query Result:", result);
    return result;
  } catch (err) {
    console.error("Error fetching department data:", err);
    throw new Error("Error fetching department data.");
  }
};


  // API Route
  exports.getDepartments = async (req, reply) => {
    try {
      console.log("Request Params:", req.params); // Debugging log
  
      let { departmentName, city, officeName } = req.params;
  
      if (!departmentName || !city || !officeName) {
        return reply.status(400).send({ message: "Department Name, City, and Office Name are required." });
      }
  
      departmentName = departmentName.trim();
      city = city.trim();
      officeName = officeName.trim();
  
      // Note the order: officeName, city, departmentName
      const departments = await getDepartmentsByName(officeName, city, departmentName);
  
      if (departments.length === 0) {
        return reply.status(404).send({ message: "No departments found for the specified parameters." });
      }
  
      reply.send({ status_code: 200, data: departments });
    } catch (err) {
      console.error("API Error:", err);
      reply.status(500).send({ message: err.message });
    }
  };
  
  
  

  const getDepartmentNames = async () => {
    try {
      const result = await Deparments.aggregate([
        {
          $group: {
            _id: {
              $toUpper: { $trim: { input: "$departmentName" } }, // Convert to uppercase & trim spaces
            },
          },
        },
        {
          $sort: { _id: 1 } // Sort alphabetically
        },
        {
          $group: {
            _id: null,
            departmentNames: { $addToSet: "$_id" } // Collect unique values in an array
          }
        },
        {
          $project: {
            _id: 0,
            departmentNames: 1 // Return only the array
          },
        }
      ]);
  
      return result.length > 0 ? result[0].departmentNames : []; // Return an empty array if no data
    } catch (err) {
      console.error(err);
      throw new Error("Error fetching department names.");
    }
  };
  
  // API Route
  exports.getAllDepartmentNames = async (req, reply) => {
    try {
      const departments = await getDepartmentNames();
      reply.send({ status_code: 200, data: departments });
    } catch (err) {
      reply.status(500).send({ message: err.message });
    }
  };
  

  exports.getCitiesByOfficeName = async (req, reply) => {
    try {
      let { officeName } = req.params;
  
      // Trim and normalize spaces
      officeName = officeName.trim().replace(/\s+/g, ' '); // Replace multiple spaces with one
      const regexOfficeName = new RegExp(officeName.replace(/\s+/g, '\\s*'), "i");
  
      // Debugging: Check all available office names in DB
      console.log("All Cities with Office Name:", await City.find().select("officeName city").lean());
      console.log("All Branches with Office Name:", await Branch.find().select("officeName city").lean());
  
      // Query both collections with case-insensitive regex
      const cityResults = await City.find({ officeName: { $regex: officeName, $options: "i" } }).select("city -_id").lean();
      const branchResults = await Branch.find({ officeName: { $regex: officeName, $options: "i" } }).select("city -_id").lean();
  
      // Extract and merge unique city names
      const cityNames = [...new Set([...cityResults.map(c => c.city), ...branchResults.map(b => b.city)])];
  
      console.log("Final City Results:", cityNames);
  
      reply.send({ status_code: 200, data: cityNames });
    } catch (err) {
      console.error("Error fetching cities:", err);
      reply.send({ error: err.message });
    }
  };
  

  // Helper function to fetch department names by city
  const getDepartmentNamesByCity = async (city) => {
    try {
      const trimmedCity = city.trim();
  
      // Allow for extra whitespace before or after the city value in the database
      const query = {
        city: { $regex: `^\\s*${trimmedCity}\\s*$`, $options: "i" }
      };
      console.log("MongoDB Query:", JSON.stringify(query, null, 2));
  
      const result = await Deparments.find(query)
        .select("departmentName -_id")
        .lean();
  
      // Remove duplicate department names
      return [...new Set(result.map(doc => doc.departmentName))];
    } catch (error) {
      console.error("Error fetching departments by city:", error);
      throw new Error("Error fetching departments by city.");
    }
  };
  
  // API route handler
  exports.getDepartmentsByCity = async (req, reply) => {
    try {
      const { city } = req.params;
      if (!city || city.trim() === "") {
        return reply.status(400).send({ message: "City is required." });
      }
  
      const departmentNames = await getDepartmentNamesByCity(city);
  
      if (departmentNames.length === 0) {
        return reply.status(404).send({ message: "No departments found for the specified city." });
      }
  
      reply.send({ status_code: 200, data: departmentNames });
    } catch (error) {
      console.error("API Error:", error);
      reply.status(500).send({ message: error.message });
    }
  };
  
 

  exports.getAllStates = async (req, reply) => {
    try {
      const states = await IndianLocations.find({}, "state").sort({ state: 1 }); // Sorting A to Z
      reply.send(states);
    } catch (err) {
      reply.status(500).send({ error: "Failed to fetch states" });
    }
  };
  
  exports.getStaeBasedCites = async (request, reply) => {
    try {
      const { stateName } = request.params;
      const state = await IndianLocations.findOne({ state: stateName }, "majorCities");
  
      if (!state) {
        return reply.status(404).send({ error: "State not found" });
      }
  
      reply.send(state.majorCities);
    } catch (err) {
      reply.status(500).send({ error: "Failed to fetch cities" });
    }
  };
  

  