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

const {Department, Desgination, City, Deparments} = 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 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,
      } = request.body;
  
      // Generate departmentId based on departmentName
    //   const prefix = departmentName.substring(0, 2).toUpperCase(); // Extract first two letters and convert to uppercase
       const cityId = await generateCityId();
  
      // Check for existing department
      const existingStore = await City.findOne({ cityId });
      if (existingStore) {
        return reply.status(400).send({ message: 'City is already registered' });
      }
  
      // Create new department
      const citys = new City({
        cityId,
        phone,
        officeName,
        location,
        city,
        office_address1,
        address2,
        state,
        zone,
        country,
        pincode,
       // departmentName,
        createdBy,
        updatedBy,
      });
  
      await citys.save();
  
      reply.send({ citys, 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.getallcities = async (req, reply) => {
  //   try {
  //     await City.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.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.editcity = async (request, reply) => {
    try {
      const { cityId } = request.params;
      const {
        
       // phone,
        city,
        state,
        country,
        zone,
        address1,
        address2,
        pincode,
       // departmentName

      } = 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.departmentName = departmentName || existing.departmentName;
      existing.pincode = pincode || existing.pincode;

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

  
      await existing.save();
  
      reply.send({ message: 'City 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,
        alternativeContactNumber,
        gender,
        personalEmail,
        city,
        firstName,
        lastName,
        departmentName,
        reportingManager,
        email,
        state,
        password,
        country,
        zone,
        address1,
        address2,
        pincode,
        desginationName,
        location,
        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,
        gender,
        city,
        firstName,
        lastName,
        email,
        personalEmail,
        reportingManager,
        departmentName,
        phone,
        address1,
        address2,
        services: { password: { bcrypt: hashedPassword } },
        state,
        zone,
        country,
        pincode,
        desginationName,
        location,
        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

      } = 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
      
  
      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 result = await City.aggregate([
        {
          $match: {
            city: city, // Match documents with the same city
            zone: zone, // Match documents with the same zone
          },
        },
        {
          $group: {
            _id: { city: "$city", zone: "$zone" }, // Group by city and zone
            locations: { $push: "$location" }, // Collect all location arrays
          },
        },
        {
          $project: {
            _id: 0, // Exclude the _id field
            city: "$_id.city",
            zone: "$_id.zone",
            locations: {
              $reduce: {
                input: "$locations",
                initialValue: [],
                in: { $concatArrays: ["$$value", "$$this"] }, // Flatten the location arrays
              },
            },
          },
        },
      ]);
  
      return result;
    } catch (err) {
      console.error(err);
      throw new Error("Error fetching locations.");
    }
  };
  

  exports.getZonebasedLocations = async (req, reply) => {
    try {
        const { city, zone } = req.query;
        const locations = await getLocationsByCityAndZone(city, zone);
        reply.send({ status_code: 200, data: locations });
      } catch (err) {
        reply.status(500).send({ message: err.message });
      }
  };