import type { DataSource } from 'typeorm';

import { User } from '@core/identity/domain/entities/User';
import type { AuthRepository } from '@core/identity/domain/repositories/AuthRepository';
import type { EmailAddress } from '@core/identity/domain/value-objects/EmailAddress';

import { UserOrmEntity } from '../entities/UserOrmEntity';
import { UserOrmMapper } from '../mappers/UserOrmMapper';

export class TypeOrmAuthRepository implements AuthRepository {
  constructor(
    private readonly dataSource: DataSource,
    private readonly mapper: UserOrmMapper,
  ) {}

  async findByEmail(email: EmailAddress): Promise<User | null> {
    const repo = this.dataSource.getRepository(UserOrmEntity);
    const entity = await repo.findOne({ where: { email: email.value.toLowerCase() } });
    return entity ? this.mapper.toDomain(entity) : null;
  }

  async save(user: User): Promise<void> {
    const repo = this.dataSource.getRepository(UserOrmEntity);

    const id = user.getId().value;
    const email = user.getEmail();
    const passwordHash = user.getPasswordHash()?.value;

    if (!email) {
      throw new Error('Cannot persist user without email');
    }
    if (!passwordHash) {
      throw new Error('Cannot persist user without password hash');
    }

    const existing = await repo.findOne({ where: { id } });

    const entity = new UserOrmEntity();
    entity.id = id;
    entity.email = email.toLowerCase();
    entity.displayName = user.getDisplayName();
    entity.passwordHash = passwordHash;
    entity.salt = '';
    entity.primaryDriverId = user.getPrimaryDriverId() ?? null;
    entity.companyId = user.getCompanyId() ?? null;
    entity.createdAt = existing?.createdAt ?? new Date();

    await repo.save(entity);
  }
}