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 { InjectDataSource } from '@nestjs/typeorm';
import { DataSource } from 'typeorm';

const SEED_FLAG = 'SEED_PASSENGER_STAFF';
const EDR_ORG_KEY = 'edr';

const STAFF_USERS = [
  { email: 'passenger.admin@edr.local',  username: 'passenger_admin',  roleKey: 'edr_passenger_backoffice_admin' },
  { email: 'passenger.staff@edr.local',  username: 'passenger_staff',  roleKey: 'edr_passenger_backoffice_staff' },
  { email: 'passenger.agent@edr.local',  username: 'passenger_agent',  roleKey: 'edr_passenger_agent' },
  { email: 'passenger.finance@edr.local', username: 'passenger_finance', roleKey: 'edr_passenger_finance' },
] as const;

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

  constructor(@InjectDataSource() private readonly dataSource: DataSource) {}

  async run() {
    if (process.env[SEED_FLAG]?.trim().toLowerCase() !== 'true') {
      this.logger.log(`Skipping passenger 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 hashedPassword = await hashPassword(password);

      for (const staff of STAFF_USERS) {
        const role = await manager.getRepository(Role).findOne({
          where: { key: staff.roleKey },
          select: { id: true, key: true },
        });
        if (!role) throw new Error(`missing_role:${staff.roleKey}`);

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

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

        const credentialExists = await manager.getRepository(UserCredential).exists({
          where: { userId: user.id, isActive: true },
        });
        if (!credentialExists) {
          await manager.getRepository(UserCredential).insert({
            userId: user.id,
            password: hashedPassword,
            isActive: true,
          });
        }

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

        const employeeExists = await manager.getRepository(Employee).exists({
          where: { userId: user.id, organizationId: organization.id, isCurrent: true },
        });
        if (!employeeExists) {
          await manager.getRepository(Employee).insert({
            userId: user.id,
            organizationId: organization.id,
            isCurrent: true,
            name: { en: staff.username },
          });
        }
      }
    });

    this.logger.log('Ensured passenger staff users');
  }
}
