const userController = require("./controllers/userController");
const { User,Counter, generateBookingId,resetCounter,generateCustomerId,ProfilePicture} = require('./models/User')

//const tanksController = require("./controllers/tanksController");
const tankersController = require("./controllers/tankersController.js");
const createConnectionController = require("./controllers/createConnectionController");
const storeController = require("./controllers/storeController.js")
const boom = require("boom");
const bcrypt = require('bcrypt');
const {  ProfilePictureStore,generateinstallationId,Store, Survey} = require("./models/store");
const cors = require('fastify-cors');


//const cors = require("cors");
const swagger = require("./config/swagger");
const rawBody = require('raw-body')
const uuidv4 = require("uuid").v4;
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 Fastify = require("fastify");

fastify.register(cors, {
  origin: 'http://localhost:3001', // Allow only your frontend URL
  methods: ['GET', 'POST', 'PUT', 'DELETE'], // Allowed HTTP methods
});


// const Fastify = require("fastify");
// const server = Fastify({
//   logger: true,
//   // ajv: { plugins: [ajvPlugin] },
//   genReqId(req) {
//     // you get access to the req here if you need it - must be a synchronous function
//     return uuidv4();
//   },
// });

// fastify.register(View).ready((err) => {
//   if (err) console.error(err);

//   console.log(fastify.config.PORT); // or fastify[options.confKey]
//   // output: { PORT: 3000 }
//   engine: {
//     ejs: require('ejs'),
//   },
//   root: join(__dirname, 'views/html'),
// });


const now = () => Date.now();

const fastifyEnv = require("fastify-env");

const schema = {
  type: "object",
  required: ["PORT"],
  properties: {
    PORT: {
      type: "string",
      default: 3000,
    },
    APIVERSION: {
      type: "string",
      default: "1.0.0",
    },
  },
};

const options = {
  confKey: "config", // optional, default: 'config'
  schema: schema,
  // data: data // optional, default: process.env
};
fastify.register(fastifyEnv, options).ready((err) => {
  if (err) console.error(err);

  console.log(fastify.config.PORT); // or fastify[options.confKey]
  // output: { PORT: 3000 }
  fastify.decorate("conf", {
    port: fastify.config.PORT,
    APIVERSION: fastify.config.APIVERSION,
  });
});



const apiversion = "1.0.0";
const path = require("path");

// Using static content for swagger documentation. Generated swagger UI is not user friendly.

fastify.register(require("fastify-static"), {
  root: path.join(__dirname, "api-docs"),
  prefix: "/api-docs", // optional: default '/'
});



fastify.register(require("fastify-swagger"), swagger.options);

const customJwtAuth = require("./customAuthJwt");
fastify.register(customJwtAuth);
//login route - accept user credentials and send a token with role . "user" role is required to use the app.

// support login using application/x-www-form-urlencoded so users can login via a web form in addition to api

// fastify.register(require("fastify-formbody"));
// fastify.register(require('fastify-multipart'))
// fastify.register(require("fastify-cors"), {
//   // put your options here
//   origin: [
//     new RegExp("http://localhost"),
//     new RegExp("http://simply-backoffice.true2air.com"),
//     new RegExp("http://localhost:3000"),
//   ],
//   credentials: true,
//   optionsSuccessStatus: 200,
// });

fastify.register((fastify, opts, done) => {
  fastify.addContentTypeParser(
    "application/json",
    { parseAs: "buffer" },
    function (_req, body, done) {
      try {
        done(null, body)
      } catch (error) {
        error.statusCode = 400
        done(error, undefined)
      }
    }
  )
  
  done(null)
})




fastify.register(require('point-of-view'), {
  engine: {
    nunjucks: require('nunjucks')
  },
  root: path.join(__dirname, "views"),
  includeViewExtension: true,

});

// * This is for login user as a simply user *

fastify.post("/api/login", {
  schema: {
    description: "This is for Login User",
    tags: ["Login"],
    summary: "This is for User Login",
    body: {
      type: "object",
      required: ["phone", "password"],
      properties: {
        phone: { type: "string" },
        password: { type: "string" },
        fcmIds: { type: "array", items: { type: "string" }, default: [] },
        deviceId: { type: "string" },
      },
    },
  },
  async handler(req, reply) {
    const { phone, password, fcmIds, deviceId } = req.body;
    console.log(password, phone);

    const loginObject = await userController.loginUser(req, fcmIds, deviceId);
    if (!loginObject.same) {
      return reply.send({
        simplydata: {
          error: true,
          code: 400,
          message: "Invalid UserId or Password supplied",
        },
      });
    }

    const user = loginObject.user;
    const phoneVerified = user.phoneVerified;
    const oneTimePasswordSetFlag = user.oneTimePasswordSetFlag;

    if (fcmIds.length > 0) {
      await User.updateOne(
        { customerId: user.customerId },
        { $addToSet: { fcmIds: { $each: fcmIds } } }
      );
    }

    if (!phoneVerified) {
      return reply.send({
        simplydata: {
          error: false,
          phoneVerified: false,
          phone: loginObject.isStaff ? loginObject.staffMember.phone : user.phone,
          oneTimePasswordSetFlag,
          message: "Please Verify your phone number",
        },
      });
    }

    if (oneTimePasswordSetFlag) {
      return reply.send({
        simplydata: {
          error: false,
          phoneVerified,
          phone: loginObject.isStaff ? loginObject.staffMember.phone : user.phone,
          oneTimePasswordSetFlag: true,
          message: "Password must be reset",
        },
      });
    }

    const tokenPayload = {
      username: loginObject.isStaff ? loginObject.staffMember.name : user.username,
      userId: user._id,
      roles: user.profile.role,
    };

    const token = fastify.jwt.sign(tokenPayload, { expiresIn: "30d" });

    const profilePicture = await ProfilePicture.findOne({ customerId: user.customerId });
    const responsePayload = {
      simplydata: {
        error: false,
        apiversion: fastify.config.APIVERSION,
        access_token: token,
        buildingName: user.buildingName,
        email: user.emails,
        phone: loginObject.isStaff ? loginObject.staffMember.phone : user.phone,
        customerId: user.customerId,
        username: loginObject.isStaff ? loginObject.staffMember.name : user.username,
        address1: user.profile.address1,
        address2: user.profile.address2,
        phoneVerified: user.phoneVerified,
        oneTimePasswordSetFlag: user.oneTimePasswordSetFlag,
        latitude: user.latitude,
        longitude: user.longitude,
        type: user.profile.role,
        loginType: loginObject.isStaff ? "staff" : "user",
      },
    };

    if (loginObject.isStaff) {
      let allMotorAccess = loginObject.staffMember.all_motor_access;
      
      // Normalize the value if it matches the given variations
      if (["view", "view only", "View", "View Only"].includes(allMotorAccess)) {
          allMotorAccess = "view";
      }
  
      responsePayload.simplydata.all_motor_access = allMotorAccess;
  }

    if (profilePicture) {
      responsePayload.simplydata.picture = profilePicture.picture;
    }

    reply.send(responsePayload);
  },
});





fastify.post("/api/installotplogin", {
  schema: {
    description: "This is for Login Otp Installation",
    tags: ["Install"],
    summary: "This is for Login Otp Installation",
    body: {
      type: "object",
      required: ["phone", "phoneVerificationCode"],
      properties: {
        phoneVerificationCode: { type: "string" },
        phone: { type: "string" },
      },
    },
  },
  async handler(req, reply) {
    try {
      const phone = req.body.phone;
      const phoneVerificationCode = req.body.phoneVerificationCode;

      const installationExists = await Install.findOne({
        phone: phone,
        phoneVerificationCode: phoneVerificationCode,
      });

      if (installationExists) {
        const filter = {
          phone: phone,
          phoneVerificationCode: phoneVerificationCode,
        };
        const update = { phoneVerified: true };
        await Install.findOneAndUpdate(filter, update);

        const loginObject = await userController.loginUserWithOTP(req);

        if (loginObject.same) {
          if (loginObject.user) {
            const { user } = loginObject;
            const phoneVerified = user.phoneVerified;
            const oneTimePasswordSetFlag = user.oneTimePasswordSetFlag;

            if (!phoneVerified) {
              reply.send({
                simplydata: {
                  error: false,
                  phoneVerified: false,
                  phone: user.phone,
                  oneTimePasswordSetFlag: oneTimePasswordSetFlag,
                  message: "Please Verify your phone number",
                },
              });
            } else if (oneTimePasswordSetFlag) {
              reply.send({
                simplydata: {
                  error: false,
                  phoneVerified: phoneVerified,
                  phone: user.phone,
                  oneTimePasswordSetFlag: true,
                  message: "Password must be reset",
                },
              });
            } else {
              const token = fastify.jwt.sign(
                {
                  firstName: user.firstName,
                },
                { expiresIn: "30d" }
              );

              const profilePicture = await ProfilePictureInstall.findOne({
                customerId: user._id,
              });
console.log(user)
              const responsePayload = {
                simplydata: {
                  error: false,
                  apiversion: fastify.config.APIVERSION,
                  access_token: token,
                  email: user.emails,
                  installationId: user.installationId,
                  phone: user.phone,
                  //name: user.name,
                  address1: user.address1,
                  address2: user.address2,
                  phoneVerified: user.phoneVerified,
                  oneTimePasswordSetFlag: user.oneTimePasswordSetFlag,
                  type: user.profile.role,
                  fcmIds: user.fcmIds,
                  team: user.team,
                  city: user.city,
                  manager: user.manager,
                  firstName: user.firstName,
                  lastName: user.lastName,
                  address: user.address,
                  alternativeNumber: user.alternativeNumber,
                },
              };

              if (profilePicture) {
                responsePayload.simplydata.picture = profilePicture.picture;
              }

              reply.send(responsePayload);
            }
          } else {
            reply.send({
              simplydata: {
                error: true,
                code: 400,
                message: "Invalid Details",
              },
            });
          }
        } else {
          reply.send({
            simplydata: {
              error: true,
              code: 400,
              message: "Invalid phone or phoneVerificationCode supplied",
            },
          });
        }
      } else {
        reply.send({
          armintatankdata: {
            error: true,
            code: 10005,
            message: "10005 - Verification code entered cannot be validated.",
          },
        });
      }
    } catch (err) {
      throw boom.boomify(err);
    }
  },
});


// fastify.post("/api/storelogin", {
//   schema: {
//     description: "This is for Store Login",
//     tags: ["Store-Data"],
//     summary: "This is for  Store Login",
//     body: {
//       type: "object",
//       required: ["phone", "password"],
//       properties: {
//         phone: { type: "string" },
//         password: { type: "string" },
//       },
//     },
//   },
//   async handler(request, reply) {
//     try {
//       let store = await Store.findOne({ phone: request.body.phone });
//       if (!store) {
//         return reply.code(400).send({
//           simplydata: {
//             error: true,
//             code: 400,
//             message: "Invalid Phone or Password",
//           },
//         });
//       }
  
//       const isMatch = await bcrypt.compare(request.body.password, store.services.password.bcrypt);
//       if (!isMatch) {
//         return reply.code(400).send({
//           simplydata: {
//             error: true,
//             code: 400,
//             message: "Invalid Phone or Password",
//           },
//         });
//       }
  
     

//       const token = fastify.jwt.sign(
//         {
//           storename: store.storename,
//           storeId: store._id,
//           roles: store.profile.role,
//         },
//         { expiresIn: "30d" }
//       );

  
//       var profilePicture = await ProfilePictureStore.findOne({ storeId: store.storeId });
  
//       if (!profilePicture) {
//         reply.send({
//           simplydata: {
//             error: false,
//             apiversion: fastify.config.APIVERSION,
//             access_token: token,
//             email: store.emails,
//             phone: store.phone,
//             storeId: store.storeId,
//             storename: store.storename,
//             office_address: store.profile.office_address,
//             phoneVerified: store.phoneVerified,
//             oneTimePasswordSetFlag: store.oneTimePasswordSetFlag,
//             latitude: store.latitude,
//             longitude: store.longitude,
//             description: store.description,
//             type: store.profile.role,
//             typeasobj: JSON.stringify(Object.assign({}, store.profile.role)),
//           },
//         });
//       } else {
//         reply.send({
//           simplydata: {
//             error: false,
//             apiversion: fastify.config.APIVERSION,
//             access_token: token,
//             picture: profilePicture.picture,
//             email: store.emails,
//             phone: store.phone,
//             storeId: store.storeId,
//             storename: store.storename,
//             office_address: store.profile.office_address,
//             phoneVerified: store.phoneVerified,
//             oneTimePasswordSetFlag: store.oneTimePasswordSetFlag,
//             latitude: store.latitude,
//             longitude: store.longitude,
//             description: store.description,
//             type: store.profile.role,
//             typeasobj: JSON.stringify(Object.assign({}, store.profile.role)),
//           },
//         });
//       }
//     }  catch (err) {
//       throw boom.boomify(err);
//     }
//   },
// });

fastify.get("/api/reset_token/:customerId", {
  
  schema: {
    description: "This is for Reset Token",
    tags: ["Login"],
    summary: "This is for Reset Token",
    params: {
      type: "object",
      properties: {
        customerId: {
          type: "string",
          description: "customerId",
        },
      },
    },
  },

  async handler(req, reply) {
    try {
      const customerId = req.params.customerId
      const get_user = await userController.getSingleUser(req);
      const token = fastify.jwt.sign(
        {
          customerId: get_user.customerId,
          userId: get_user._id,
          roles: get_user.profile.role,
        },
        { expiresIn: "30d" }
      );
      
      reply.send({ access_token: token, customerId: get_user.customerId });
    } catch (err) {
      console.log(err);
      error = {
        simplydata: {
          error: true,
          code: 400,
          message: "Reset Token failed",
        },
      };
      reply.status(401).send(error);
    }
  },
});



fastify.get('/testtemp', (req, reply) => {
  reply.view('layouts/main', {});
});

// const multipart = require('fastify-multipart');

// fastify.register(multipart);
//fastify-auth plugin is required so we can define routes in seperate files and verify jwt supplied in preHandlers for each request.
//const multer = require("fastify-multer");
fastify.register(require("fastify-auth"));
const dbConnection = require("./config/config");
fastify.register(dbConnection);
//fastify.register(multer.contentParser);
const { Schema } = require("mongoose");
// fastify.register(dbConnection);

fastify.register(require("./routes/usersRoute"));

fastify.register(require("./routes/tanksRoute"));
fastify.register(require("./routes/createConnectionsRoute"));
fastify.register(require("./routes/tankersRoute.js"));
fastify.register(require("./routes/supplierRoute"));
fastify.register(require("./routes/supplierOrdersRoutes"));
fastify.register(require("./routes/friendRequestRoute"));
fastify.register(require("./routes/adminRoute"));
fastify.register(require("./routes/storeRoute"));
fastify.register(require("./routes/departmentRoute.js"));
fastify.register(require("./routes/installationRoute.js"));



// Testing route allows for retrieving a user by phone so one can see what is the phone verification code sent for a given user's phone
// Also allows deletion of a user with a given phone number
fastify.register(require("./routes/forTestingRoute"));


 const fs = require('fs');


const {Storage} = require('@google-cloud/storage');
const { Supplier, profilePictureSupplier } = require("./models/supplier");
const multer = require('fastify-multer');
const { ProfilePictureInstall, Install } = require("./models/store.js");
const { TeamMemberProfilePicture, CompanyProfilePicture, Deparments, IndianLocations } = require("./models/Department.js");
fastify.register(require('fastify-formbody'));
// fastify.register(multer.contentParser);
// const multipart = require('fastify-multipart');

// fastify.register(multipart);

const gc = new Storage({
  keyFilename : path.join(__dirname, "../src/arminta-tank-keyFile.json"),
  projectId : 'arminta-tank'
})

const storage = new Storage({
  keyFilename : path.join(__dirname, "../src/arminta-tank-keyFile.json"),
  projectId : 'arminta-tank'
});
// console.log(storage)
// const cloudinary = require('cloudinary').v2;
// const FormData = require('form-data');
// const mv = require('mv');

// cloudinary.config({ 
//   cloud_name: 'dalqpseol', 
//   api_key: '121595628244491', 
//   api_secret: 'jnuny_0fMYovQS0eyvIVXQTl4RY' 
// });

// Register fastify-file-upload plugin
fastify.register(require('fastify-multipart'));



// fastify.post('/upload', async (request, reply) => {
//   try {
//     const data = await request.file();

//     // Generate a unique file name
//     const fileName = `${data.filename}`;

//     const filePath = `${fileName}`;

//     // Move the file to a temporary location
//     const writeStream = fs.createWriteStream(filePath);
//     data.file.pipe(writeStream);

//     writeStream.on('close', () => {
//       // Upload the image to Cloudinary
//       cloudinary.uploader.upload(filePath, (error, result) => {
//         if (error) {
//           reply.code(500).send({ error: 'Failed to upload file to Cloudinary' });
//         } else {
//           // Get the public URL of the uploaded image
//           const publicUrl = result.secure_url;

//           // Remove the temporary file
//           fs.unlinkSync(filePath);

//           // Return the public URL
//           reply.send({ url: publicUrl });
//         }
//       });
//     });

//     writeStream.on('error', (err) => {
//       reply.code(500).send({ error: 'Failed to move file' });
//     });
//   } catch (err) {
//     reply.code(500).send({ error: 'An error occurred' });
//   }
// });


// fastify.post('/upload/:supplierId', async (request, reply) => {
//   try {
//     const supplierId = request.params.supplierId;
//     const data = await request.file();

//     // Generate a unique file name
//     const fileName = `${data.filename}`;

//     const filePath = `${fileName}`;

//     // Move the file to a temporary location
//     const writeStream = fs.createWriteStream(filePath);
//     data.file.pipe(writeStream);

//     writeStream.on('close', () => {
//       // Upload the image to Cloudinary
//       cloudinary.uploader.upload(filePath, (error, result) => {
//         if (error) {
//           reply.code(500).send({ error: 'Failed to upload file to Cloudinary' });
//         } else {
//           // Get the public URL of the uploaded image
//           const publicUrl = result.secure_url;

//           // Remove the temporary file
//           fs.unlinkSync(filePath);

//           // Store the URL in the database
//           // Assuming you have a database connection and a ProfilePictureSupplier model
//           profilePictureSupplier.findOneAndUpdate(
//             { supplierId },
//             { picture: publicUrl },
//             { new: true, upsert: true },
//             (error, picture) => {
//               if (error) {
//                 reply.code(500).send({ error: 'Failed to update database' });
//               } else {
//                 // Return the public URL
//                 reply.send({ picture: publicUrl });
//               }
//             }
//           );
//         }
//       });
//     });

//     writeStream.on('error', (err) => {
//       reply.code(500).send({ error: 'Failed to move file' });
//     });
//   } catch (err) {
//     reply.code(500).send({ error: 'An error occurred' });
//   }
// });

fastify.post('/api/uploads_team_profile/:customerId', async (request, reply) => {
  try {
    const customerId = request.params.customerId;
    const data = await request.file();

    const bucketName = 'arminta_profile_pictures';
    const filePath = `arminta_team_profiles/${data.filename}`;

    const file = storage.bucket(bucketName).file(filePath);
    const writeStream = file.createWriteStream();

    data.file.pipe(writeStream);

    await new Promise((resolve, reject) => {
      writeStream.on('finish', resolve);
      writeStream.on('error', reject);
    });

    // Make file public
    await file.makePublic();
    const publicUrl = `https://storage.googleapis.com/${bucketName}/${filePath}`;

    // Update DB with async/await
    const picture = await TeamMemberProfilePicture.findOneAndUpdate(
      { customerId },
      { picture: publicUrl },
      { new: true, upsert: true }
    );

    reply.send({ picture: publicUrl });
  } catch (err) {
    console.error(err);
    reply.code(500).send({ error: 'An error occurred', details: err.message });
  }
});



fastify.post('/api/uploads_company_profile/:customerId', async (request, reply) => {
  try {
    const customerId = request.params.customerId;
    const data = await request.file();

    const bucketName = 'arminta_profile_pictures';
    const filePath = `arminta_company_profiles/${data.filename}`;

    const file = storage.bucket(bucketName).file(filePath);
    const writeStream = file.createWriteStream();

    data.file.pipe(writeStream);

    await new Promise((resolve, reject) => {
      writeStream.on('finish', resolve);
      writeStream.on('error', reject);
    });

    // Make file public
    await file.makePublic();
    const publicUrl = `https://storage.googleapis.com/${bucketName}/${filePath}`;

    // Update DB with async/await
    const picture = await CompanyProfilePicture.findOneAndUpdate(
      { customerId },
      { picture: publicUrl },
      { new: true, upsert: true }
    );

    reply.send({ picture: publicUrl });
  } catch (err) {
    console.error(err);
    reply.code(500).send({ error: 'An error occurred', details: err.message });
  }
});


fastify.post('/api/uploads/:supplierId', async (request, reply) => {
  try {
    const supplierId = request.params.supplierId;
    const data = await request.file();

    // Generate a unique file name
    const fileName = `${data.filename}`;

    // Define the destination bucket and file path
    const bucketName = 'arminta_profile_pictures';
    const filePath = `${fileName}`;

    // Create a write stream to the destination file in the bucket
    const writeStream = storage.bucket(bucketName).file(filePath).createWriteStream();

    // Pipe the file data to the write stream
    data.file.pipe(writeStream);

    writeStream.on('finish', async () => {
      try {
        // Make the uploaded file publicly accessible
        await storage.bucket(bucketName).file(filePath).makePublic();

        const publicUrl = `https://storage.googleapis.com/${bucketName}/${filePath}`;

        profilePictureSupplier.findOneAndUpdate(
          { supplierId },
          { picture: publicUrl },
          { new: true, upsert: true },
          (error, picture) => {
            if (error) {
              reply.code(500).send({ error: 'Failed to update database' });
            } else {
              // Return the public URL
              reply.send({ picture: publicUrl });
            }
          }
        );
      } catch (error) {
        reply.code(500).send({ error: 'Failed to make file public' });
      }
    });

    writeStream.on('error', (err) => {
      reply.code(500).send({ error: 'Failed to move file' });
    });
  } catch (err) {
    reply.code(500).send({ error: 'An error occurred' });
  }
});



fastify.post('/api/uploads-user/:customerId', async (request, reply) => {
  try {
    const customerId = request.params.customerId;
    const data = await request.file();

    // Generate a unique file name
    
    const fileName = `${data.filename}`;


    // Define the destination bucket and file path
    const bucketName = 'arminta_profile_pictures';
    const filePath = `arminta_user_profiles/${fileName}`;

    // Create a write stream to the destination file in the bucket
    const writeStream = storage.bucket(bucketName).file(filePath).createWriteStream();

    // Pipe the file data to the write stream
    data.file.pipe(writeStream);

    writeStream.on('finish', async () => {
      try {
        // Make the uploaded file publicly accessible
        await storage.bucket(bucketName).file(filePath).makePublic();

        const publicUrl = `https://storage.googleapis.com/${bucketName}/${filePath}`;

        ProfilePicture.findOneAndUpdate(
          { customerId },
          { picture: publicUrl },
          { new: true, upsert: true },
          (error, picture) => {
            if (error) {
              reply.code(500).send({ error: 'Failed to update database' });
            } else {
              // Return the public URL
              reply.send({ picture: publicUrl });
            }
          }
        );
      } catch (error) {
        reply.code(500).send({ error: 'Failed to make file public' });
      }
    });


    writeStream.on('error', (err) => {
      reply.code(500).send({ error: 'Failed to move file' });
    });
  } catch (err) {
    reply.code(500).send({ error: 'An error occurred' });
  }
});

fastify.post("/api/installLogin", {
  schema: {
    description: "This is for Login Install",
    tags: ["Installation"],
    summary: "This is for Login Install",
    body: {
      type: "object",
      required: ["type", "phone", "password"],
      properties: {
        type: { type: "string", description: "User role type (e.g., 'admin', 'manager')" },
        phone: { type: "string", description: "Registered phone number" },
        password: { type: "string", description: "Password for authentication" },
      },
    },
  },
  async handler(req, reply) {
    try {
      const { type, phone, password } = req.body;

      // Check if user exists in the Department Schema
      const user = await Deparments.findOne({ phone });

      if (!user) {
        return reply.code(400).send({ message: "User not found" });
      }

      // Verify Password
      const isMatch = await bcrypt.compare(password, user.services.password.bcrypt);

      if (!isMatch) {
        return reply.code(400).send({ message: "Invalid credentials" });
      }

      // Check if department details already exist in installation schema
      let installation = await Install.findOne({ phone });

      if (!installation) {
        // Create a new entry in installation schema with departmentId as installationId
        installation = new Install({
          phone: user.phone,
          installationId: user.departmentId, // Store departmentId in installationId
          firstName: user.firstName,
          lastName: user.lastName,
          email: user.email,
          alternativeNumber: user.alternativeContactNumber,
          departmentName: user.departmentName,
          designation: user.desginationName,
          reportingManager: user.reportingManager,
          city: user.city,
          zone: user.zone,
          address1: user.address1,
          address2: user.address2,
          profile: {
            state: user.state,
            country: user.country,
            role: type, // Store type in profile.role
          },
        });

        await installation.save();
      }

      // Ensure `type` is stored in `profile.role`
      if (!installation.profile?.role) {
        installation.profile.role = type;
        await installation.save(); // Save the updated type
      }

      // Fetch profile picture if available
      const profilePicture = await ProfilePictureInstall.findOne({ customerId: installation._id });

      // Generate JWT Token
      const token = fastify.jwt.sign(
        { userId: user._id, phone: user.phone, role: installation.profile?.role },
        "your_secret_key",
        { expiresIn: "7d" }
      );

      // Construct response payload
      const responsePayload = {
        simplydata: {
          error: false,
          apiversion: fastify.config.APIVERSION,
          access_token: token,
          email: installation.emails || [],
          installationId: installation.installationId,
          phone: installation.phone,
          address1: installation.address1,
          address2: installation.address2,
          phoneVerified: installation.phoneVerified,
          oneTimePasswordSetFlag: installation.oneTimePasswordSetFlag,
          type: installation.profile?.role || "user", // Default to "user" if not available
          fcmIds: installation.fcmId || null,
          team: installation.team,
          city: installation.city,
          manager: installation.manager,
          firstName: installation.firstName,
          lastName: installation.lastName,
          address: installation.address || "",
          alternativeNumber: installation.alternativeNumber || null,
          profilePicture: profilePicture ? profilePicture.pictureUrl : null, // Include profile picture URL if available
        },
      };

      return reply.send(responsePayload);
    } catch (error) {
      console.error("Login Error:", error);
      return reply.code(500).send({ message: "Internal server error" });
    }
  },
});


fastify.post("/api/teamMemberLogin", {
  schema: {
    description: "Login API for team members",
    tags: ["Installation"],
    summary: "Login as a Team Member",
    body: {
      type: "object",
      required: ["type", "phone", "password"],
      properties: {
        type: { type: "string", description: "Role type of the user (e.g., 'team_member')" },
        phone: { type: "string", description: "Registered phone number of the team member" },
        password: { type: "string", description: "Password for authentication" },
      },
    },
  },
  async handler(request, reply) {
    try {
      const { type, phone, password } = request.body;

      // ✅ Step 1: Find the team member in `Deparments`
      const department = await Deparments.findOne({
        "team_member.team_member.phone": phone
      });

      if (!department) {
        return reply.status(401).send({
          simplydata: {
            error: true,
            message: "Invalid phone number",
          },
        });
      }

      // ✅ Step 2: Find the specific team member
      const teamMember = department.team_member.team_member.find(
        (member) => member.phone === phone
      );

      if (!teamMember) {
        return reply.status(401).send({
          simplydata: {
            error: true,
            message: "Invalid phone number",
          },
        });
      }

      // ✅ Step 3: Verify password
      const isPasswordValid = await bcrypt.compare(password, teamMember.password);

      if (!isPasswordValid) {
        return reply.status(401).send({
          simplydata: {
            error: true,
            message: "Invalid phone number or password",
          },
        });
      }

      console.log("Team Member First Name:", teamMember.firstName); // ✅ Debugging

      // ✅ Step 4: Check if this team member already exists in `Install`
      let installation = await Install.findOne({
        installationId: department.departmentId
      });

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

      // Check if team member already exists in Install schema
      const existingTeamMember = installation.team_member.team_member.find(
        (member) => member.phone === phone
      );

      if (!existingTeamMember) {
        // ✅ Step 5: Add team member details to `Install` schema
        installation.team_member.team_member.push({
          teamMemberId: teamMember.teamMemberId,
          firstName: teamMember.firstName,
          phone: teamMember.phone,
          email: teamMember.email,
          alternativePhone: teamMember.alternativePhone,
          installationTeamMemId: installation.installationId,
          password: teamMember.password, // Store hashed password
          status: teamMember.status || "active",
          type: type, // Store login type
        });

        await installation.save();
      }

      // ✅ Step 6: Generate JWT token
      const token = fastify.jwt.sign(
        { phone: teamMember.phone, role: type, installationId: installation.installationId },
        "JWT_SECRET",
        { expiresIn: "1h" }
      );

      return reply.send({
        simplydata: {
          error: false,
          message: "Login successful",
          access_token: token,
          phone: teamMember.phone,
          firstName: teamMember.firstName || null,  // ✅ Now included
          teamMemberId: teamMember.teamMemberId,
          alternativePhone: teamMember.alternativePhone || null,
          email: teamMember.email || null,
          status: teamMember.status || "active",
          type: teamMember.type, 
          installationId: installation.installationId 
        },
      });

    } catch (err) {
      console.error("Error logging in:", err);
      reply.status(500).send({
        simplydata: {
          error: true,
          message: "Internal server error",
        },
      });
    }
  },
});



  fastify.post("/api/surveyLogin", {
    schema: {
      description: "This is for Login Survey",
      tags: ["Survey"],
      summary: "This is for Login Survey",
      body: {
        type: "object",
        required: [ "phone", "password"],
        properties: {
          phone: { type: "string", description: "Registered phone number" },
          password: { type: "string", description: "Password for authentication" },
        },
      },
    },
    async handler(req, reply) {
      try {
        const {  phone, password } = req.body;
  
        // Check if user exists in the Department Schema
        const user = await Deparments.findOne({ phone });
        console.log("user", user)
  
        if (!user) {
          return reply.code(400).send({ message: "User not found" });
        }
  
        // Verify Password
        const isMatch = await bcrypt.compare(password, user.services.password.bcrypt);
  
        if (!isMatch) {
          return reply.code(400).send({ message: "Invalid credentials" });
        }
  
        let survey = await Survey.findOne({ phone });
  
        if (!survey) {
          survey = new Survey({
            phone: user.phone,
            surveyId: user.departmentId, 
            firstName: user.firstName,
            lastName: user.lastName,
            email: user.email,
            alternativeNumber: user.alternativeContactNumber,
            departmentName: user.departmentName,
            designation: user.desginationName,
            reportingManager: user.reportingManager,
            city: user.city,
            zone: user.zone,
            address1: user.address1,
            address2: user.address2,
            profile: {
              state: user.state,
              country: user.country,
              //role: type, // Store type in profile.role
            },
          });
  
          await survey.save();
        }

        const token = fastify.jwt.sign(
          { phone: user.phone },
          "Scret",
          { expiresIn: "1h" }
        );

        return reply.send({
          simplydata: {
            error: false,
            message: "Login successful",
            access_token: token,
            phone: user.phone,
            surveyId: user.departmentId, 
            firstName: user.firstName,
            lastName: user.lastName,
            email: user.email,
            alternativeNumber: user.alternativeContactNumber,
            departmentName: user.departmentName,
            designation: user.desginationName,
            reportingManager: user.reportingManager,
            city: user.city,
            zone: user.zone,
            address1: user.address1,
            address2: user.address2,
            profile: {
              state: user.state,
              country: user.country,
              //role: type, // Store type in profile.role
            },
          },
        });
       // return reply.send(survey);
      } catch (error) {
        console.error("Login Error:", error);
        return reply.code(500).send({ message: "Internal server error" });
      }
    },
  });


  fastify.post("/api/storelogin", {
    schema: {
      description: "This is for Store Login",
      tags: ["Store-Data"],
      summary: "This is for Store Login",
      body: {
        type: "object",
        required: [ "phone", "password"],
        properties: {
          phone: { type: "string", description: "Registered phone number" },
          password: { type: "string", description: "Password for authentication" },
        },
      },
    },
    async handler(req, reply) {
      try {
        const {  phone, password } = req.body;
  
        // Check if user exists in the Department Schema
        const user = await Deparments.findOne({ phone });
        console.log("user", user)
  
        if (!user) {
          return reply.code(400).send({ message: "User not found" });
        }
  
        // Verify Password
        const isMatch = await bcrypt.compare(password, user.services.password.bcrypt);
  
        if (!isMatch) {
          return reply.code(400).send({ message: "Invalid credentials" });
        }
  
        let store = await Store.findOne({ phone });
  
        if (!store) {
          store = new Store({
            phone: user.phone,
            storeId: user.departmentId, 
            firstName: user.firstName,
            lastName: user.lastName,
            email: user.email,
            alternativeNumber: user.alternativeContactNumber,
            departmentName: user.departmentName,
            designation: user.desginationName,
            reportingManager: user.reportingManager,
            city: user.city,
            zone: user.zone,
            address1: user.address1,
            address2: user.address2,
            profile: {
              state: user.state,
              country: user.country,
              //role: type, // Store type in profile.role
            },
          });
  
          await store.save();
        }

        const token = fastify.jwt.sign(
          { phone: user.phone },
          "Scret",
          { expiresIn: "1h" }
        );

        return reply.send({
          simplydata: {
            error: false,
            message: "Login successful",
            access_token: token,
            phone: user.phone,
            storeId: user.departmentId, 
            firstName: user.firstName,
            lastName: user.lastName,
            email: user.email,
            alternativeNumber: user.alternativeContactNumber,
            departmentName: user.departmentName,
            designation: user.desginationName,
            reportingManager: user.reportingManager,
            city: user.city,
            zone: user.zone,
            address1: user.address1,
            address2: user.address2,
            profile: {
              state: user.state,
              country: user.country,
              //role: type, // Store type in profile.role
            },
          },
        });
       // return reply.send(survey);
      } catch (error) {
        console.error("Login Error:", error);
        return reply.code(500).send({ message: "Internal server error" });
      }
    },
  });
  
  fastify.post("/add-states", async (request, reply) => {
    try {
      const statesData = [
        {
          state: "Andhra Pradesh",
          majorCities: [
            "Adoni", "Amaravati", "Anantapur", "Chandragiri", "Chittoor",
            "Guntur", "Kadapa", "Kakinada", "Kurnool", "Machilipatnam",
            "Rajahmundry", "Tirupati", "Vijayawada", "Visakhapatnam", "Vizianagaram"
          ],
        },
        {
          state: "Arunachal Pradesh",
          majorCities: ["Itanagar", "Naharlagun", "Tawang", "Pasighat", "Ziro"],
        },
        {
          state: "Assam",
          majorCities: ["Guwahati", "Dibrugarh", "Silchar", "Jorhat", "Tezpur"],
        },
        {
          state: "Bihar",
          majorCities: ["Patna", "Gaya", "Bhagalpur", "Muzaffarpur", "Purnia"],
        },
        {
          state: "Chhattisgarh",
          majorCities: ["Raipur", "Bhilai", "Bilaspur", "Durg", "Korba"],
        },
        {
          state: "Goa",
          majorCities: ["Panaji", "Margao", "Vasco da Gama", "Mapusa"],
        },
        {
          state: "Gujarat",
          majorCities: ["Ahmedabad", "Surat", "Vadodara", "Rajkot", "Bhavnagar"],
        },
        {
          state: "Haryana",
          majorCities: ["Chandigarh", "Faridabad", "Gurugram", "Hisar", "Panipat"],
        },
        {
          state: "Himachal Pradesh",
          majorCities: ["Shimla", "Manali", "Dharamshala", "Mandi", "Solan"],
        },
        {
          state: "Jharkhand",
          majorCities: ["Ranchi", "Jamshedpur", "Dhanbad", "Bokaro", "Hazaribagh"],
        },
        {
          state: "Karnataka",
          majorCities: ["Bengaluru", "Mysuru", "Hubballi", "Mangaluru", "Belagavi"],
        },
        {
          state: "Kerala",
          majorCities: ["Thiruvananthapuram", "Kochi", "Kozhikode", "Thrissur", "Alappuzha"],
        },
        {
          state: "Madhya Pradesh",
          majorCities: ["Bhopal", "Indore", "Gwalior", "Jabalpur", "Ujjain"],
        },
        {
          state: "Maharashtra",
          majorCities: ["Mumbai", "Pune", "Nagpur", "Nashik", "Aurangabad"],
        },
        {
          state: "Manipur",
          majorCities: ["Imphal", "Bishnupur", "Thoubal", "Churachandpur"],
        },
        {
          state: "Meghalaya",
          majorCities: ["Shillong", "Tura", "Jowai", "Nongstoin"],
        },
        {
          state: "Mizoram",
          majorCities: ["Aizawl", "Lunglei", "Champhai", "Serchhip"],
        },
        {
          state: "Nagaland",
          majorCities: ["Kohima", "Dimapur", "Mokokchung", "Tuensang"],
        },
        {
          state: "Odisha",
          majorCities: ["Bhubaneswar", "Cuttack", "Rourkela", "Berhampur", "Sambalpur"],
        },
        {
          state: "Punjab",
          majorCities: ["Chandigarh", "Ludhiana", "Amritsar", "Jalandhar", "Patiala"],
        },
        {
          state: "Rajasthan",
          majorCities: ["Jaipur", "Jodhpur", "Udaipur", "Kota", "Ajmer"],
        },
        {
          state: "Sikkim",
          majorCities: ["Gangtok", "Namchi", "Mangan", "Gyalshing"],
        },
        {
          state: "Tamil Nadu",
          majorCities: ["Chennai", "Coimbatore", "Madurai", "Tiruchirappalli", "Salem"],
        },
        {
          state: "Telangana",
          majorCities: ["Hyderabad", "Warangal", "Nizamabad", "Karimnagar", "Khammam"],
        },
        {
          state: "Tripura",
          majorCities: ["Agartala", "Udaipur", "Dharmanagar", "Kailashahar"],
        },
        {
          state: "Uttar Pradesh",
          majorCities: ["Lucknow", "Kanpur", "Varanasi", "Agra", "Meerut"],
        },
        {
          state: "Uttarakhand",
          majorCities: ["Dehradun", "Haridwar", "Nainital", "Rishikesh"],
        },
        {
          state: "West Bengal",
          majorCities: ["Kolkata", "Howrah", "Durgapur", "Siliguri", "Asansol"],
        },
        {
          state: "Andaman and Nicobar Islands",
          majorCities: ["Port Blair"],
        },
        {
          state: "Chandigarh",
          majorCities: ["Chandigarh"],
        },
        {
          state: "Dadra and Nagar Haveli and Daman and Diu",
          majorCities: ["Daman", "Diu", "Silvassa"],
        },
        {
          state: "Lakshadweep",
          majorCities: ["Kavaratti"],
        },
        {
          state: "Delhi",
          majorCities: ["New Delhi"],
        },
        {
          state: "Puducherry",
          majorCities: ["Puducherry", "Karaikal", "Mahe", "Yanam"],
        },
      ];
  
      await IndianLocations.deleteMany(); 
      await IndianLocations.insertMany(statesData);
  
      reply.send({ message: "✅ All states added successfully!" });
    } catch (error) {
      reply.status(500).send({ error: "❌ Error inserting states: " + error });
    }
  });

// Run the server!
const start = async () => {

  try {
    

    await fastify.listen(3000, "0.0.0.0");
    fastify.log.info(`listening on ${fastify.server.address().port}`);
    fastify.log.info(`server listening on ${fastify.config}`);
  } catch (err) {
    fastify.log.error(err);
    process.exit(1);
  }
};
start();