'use strict';

const bcrypt = require('bcrypt');
const { QueryTypes } = require('sequelize');
const { v4: uuidv4 } = require('uuid');
const config = require('../../config');

const demoAccounts = [
  {
    email: 'super_admin@flatlogic.com',
    password: config.admin_pass,
    roleName: 'Super Administrator',
    firstName: 'Super',
    lastName: 'Administrator',
  },
  {
    email: 'admin@flatlogic.com',
    password: config.admin_pass,
    roleName: 'Administrator',
    firstName: 'Organization',
    lastName: 'Administrator',
  },
  {
    email: 'director.general@flatlogic.com',
    previousEmails: ['client@hello.com'],
    password: config.user_pass,
    roleName: 'Director General',
    firstName: 'Director',
    lastName: 'General',
  },
  {
    email: 'finance.director@flatlogic.com',
    previousEmails: ['john@doe.com'],
    password: config.user_pass,
    roleName: 'Finance Director',
    firstName: 'Finance',
    lastName: 'Director',
  },
  {
    email: 'procurement.lead@flatlogic.com',
    password: config.user_pass,
    roleName: 'Procurement Lead',
    firstName: 'Procurement',
    lastName: 'Lead',
  },
  {
    email: 'compliance.audit@flatlogic.com',
    password: config.user_pass,
    roleName: 'Compliance and Audit Lead',
    firstName: 'Compliance',
    lastName: 'Audit Lead',
  },
  {
    email: 'project.delivery@flatlogic.com',
    password: config.user_pass,
    roleName: 'Project Delivery Lead',
    firstName: 'Project',
    lastName: 'Delivery Lead',
  },
];

module.exports = {
  async up(queryInterface) {
    const transaction = await queryInterface.sequelize.transaction();

    try {
      for (const account of demoAccounts) {
        const role = await queryInterface.sequelize.query(
          'SELECT id FROM "roles" WHERE name = :roleName LIMIT 1',
          {
            replacements: { roleName: account.roleName },
            type: QueryTypes.SELECT,
            transaction,
          },
        );

        if (!role[0]?.id) {
          throw new Error(`Role not found for demo account: ${account.roleName}`);
        }

        let existingUser = null;

        for (const candidateEmail of [account.email, ...(account.previousEmails || [])]) {
          const user = await queryInterface.sequelize.query(
            'SELECT id, email FROM "users" WHERE email = :email LIMIT 1',
            {
              replacements: { email: candidateEmail },
              type: QueryTypes.SELECT,
              transaction,
            },
          );

          if (user[0]?.id) {
            existingUser = user[0];
            break;
          }
        }

        const passwordHash = bcrypt.hashSync(account.password, config.bcrypt.saltRounds);
        const now = new Date();

        if (existingUser?.id) {
          await queryInterface.sequelize.query(
            `UPDATE "users"
             SET "firstName" = :firstName,
                 "lastName" = :lastName,
                 "email" = :email,
                 "password" = :password,
                 "emailVerified" = true,
                 "provider" = :provider,
                 "disabled" = false,
                 "app_roleId" = :roleId,
                 "deletedAt" = NULL,
                 "updatedAt" = :updatedAt
             WHERE id = :id`,
            {
              replacements: {
                id: existingUser.id,
                firstName: account.firstName,
                lastName: account.lastName,
                email: account.email,
                password: passwordHash,
                provider: config.providers.LOCAL,
                roleId: role[0].id,
                updatedAt: now,
              },
              transaction,
            },
          );
        } else {
          await queryInterface.bulkInsert(
            'users',
            [
              {
                id: uuidv4(),
                firstName: account.firstName,
                lastName: account.lastName,
                email: account.email,
                emailVerified: true,
                provider: config.providers.LOCAL,
                password: passwordHash,
                disabled: false,
                app_roleId: role[0].id,
                createdAt: now,
                updatedAt: now,
              },
            ],
            { transaction },
          );
        }
      }

      await transaction.commit();
    } catch (error) {
      await transaction.rollback();
      console.error('Error upserting role demo users:', error);
      throw error;
    }
  },

  async down() {},
};
