import { Injectable, Logger } from '@nestjs/common';
import { hashPassword } from '@tria-plc/api-common/utils/argon';
import { EUserStatus } from '@tria-plc/api-common/utils/enums/user.enum';
import {
  Employee,
  Organization,
  Role,
  User,
  UserCredential,
  UserRole,
} from '@tria-plc/iamapi-common';
import { DataSource } from 'typeorm';

const SEED_FLAG = 'SEED_FREIGHT_STAFF';
const EDR_ORG_KEY = 'edr_freight';

const STAFF_USERS = [
  { email: 'linestaff@edr.local', username: 'linestaff', roleKey: 'edr_line_staff' },
  { email: 'director@edr.local', username: 'director', roleKey: 'edr_director' },
  { email: 'ceo@edr.local', username: 'ceo', roleKey: 'edr_ceo' },
  { email: 'gl@edr.local', username: 'gl', roleKey: 'edr_global_logistics' },
] as const;

@Injectable()
export class FreightStaffUsersSeeder {
  private readonly logger = new Logger(FreightStaffUsersSeeder.name);

  constructor(private readonly dataSource: DataSource) {}

  async run() {
    if (process.env[SEED_FLAG]?.trim().toLowerCase() !== 'true') {
      this.logger.log(`Skipping freight staff seed because ${SEED_FLAG} is not enabled`);
      return;
    }

    const password =
      process.env.DEFAULT_PASSWORD?.trim() || '12345678';

    await this.dataSource.transaction(async (manager) => {
      const organization = await manager.getRepository(Organization).findOne({
        where: { key: EDR_ORG_KEY },
        select: { id: true, key: true },
      });

      if (!organization) {
        throw new Error(`missing_organization:${EDR_ORG_KEY}`);
      }

      const roleRepository = manager.getRepository(Role);
      const userRepository = manager.getRepository(User);
      const userCredentialRepository = manager.getRepository(UserCredential);
      const userRoleRepository = manager.getRepository(UserRole);
      const employeeRepository = manager.getRepository(Employee);

      const hashedPassword = await hashPassword(password);

      for (const staff of STAFF_USERS) {
        const role = await roleRepository.findOne({
          where: { key: staff.roleKey },
          select: { id: true, key: true },
        });

        if (!role) {
          throw new Error(`missing_role:${staff.roleKey}`);
        }

        let user = await userRepository.findOne({
          where: { email: staff.email },
          select: { id: true, email: true },
        });

        if (!user) {
          user = await userRepository.save(
            userRepository.create({
              email: staff.email,
              username: staff.username,
              name: { en: staff.username },
              isActive: true,
              hasSetPassword: true,
              status: EUserStatus.ACCEPTED,
            }),
          );
          this.logger.log(`Seeded freight staff user ${staff.email}`);
        }

        const activeCredentialExists = await userCredentialRepository.exists({
          where: { userId: user.id, isActive: true },
        });

        if (!activeCredentialExists) {
          await userCredentialRepository.insert({
            userId: user.id,
            password: hashedPassword,
            isActive: true,
          });
        }

        await userRoleRepository.upsert(
          {
            userId: user.id,
            roleId: role.id,
            organizationId: organization.id,
          },
          { conflictPaths: { userId: true, roleId: true } },
        );

        const employeeExists = await employeeRepository.exists({
          where: {
            userId: user.id,
            organizationId: organization.id,
            isCurrent: true,
          },
        });

        if (!employeeExists) {
          await employeeRepository.insert({
            userId: user.id,
            organizationId: organization.id,
            isCurrent: true,
            name: { en: staff.username },
          });
        }
      }
    });

    this.logger.log(
      'Ensured freight staff users (linestaff@, director@, ceo@, gl@)',
    );
  }
}
