/**
 * TypeORM User Repository
 *
 * Implements UserRepository interface using TypeORM
 */

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from '@domain/entities/user.entity';
import { UserRepository } from '@domain/ports/out/user.repository';
import { UserOrmEntity } from '../entities/user.orm-entity';
import { UserOrmMapper } from '../mappers/user-orm.mapper';

@Injectable()
export class TypeOrmUserRepository implements UserRepository {
  constructor(
    @InjectRepository(UserOrmEntity)
    private readonly repository: Repository<UserOrmEntity>
  ) {}

  async save(user: User): Promise<User> {
    const orm = UserOrmMapper.toOrm(user);
    const saved = await this.repository.save(orm);
    return UserOrmMapper.toDomain(saved);
  }

  async findById(id: string): Promise<User | null> {
    const orm = await this.repository.findOne({ where: { id } });
    return orm ? UserOrmMapper.toDomain(orm) : null;
  }

  async findByEmail(email: string): Promise<User | null> {
    const orm = await this.repository.findOne({
      where: { email: email.toLowerCase() },
    });
    return orm ? UserOrmMapper.toDomain(orm) : null;
  }

  async findByOrganization(organizationId: string): Promise<User[]> {
    const orms = await this.repository.find({
      where: { organizationId },
      order: { lastName: 'ASC', firstName: 'ASC' },
    });
    return UserOrmMapper.toDomainMany(orms);
  }

  async findByRole(role: string): Promise<User[]> {
    const orms = await this.repository.find({
      where: { role },
      order: { lastName: 'ASC', firstName: 'ASC' },
    });
    return UserOrmMapper.toDomainMany(orms);
  }

  async findAllActive(): Promise<User[]> {
    const orms = await this.repository.find({
      where: { isActive: true },
      order: { lastName: 'ASC', firstName: 'ASC' },
    });
    return UserOrmMapper.toDomainMany(orms);
  }

  async findAll(): Promise<User[]> {
    const orms = await this.repository.find({
      order: { createdAt: 'DESC' },
    });
    return UserOrmMapper.toDomainMany(orms);
  }

  async update(user: User): Promise<User> {
    const orm = UserOrmMapper.toOrm(user);
    const updated = await this.repository.save(orm);
    return UserOrmMapper.toDomain(updated);
  }

  async deleteById(id: string): Promise<void> {
    await this.repository.delete({ id });
  }

  async countByOrganization(organizationId: string): Promise<number> {
    return this.repository.count({ where: { organizationId } });
  }

  async emailExists(email: string): Promise<boolean> {
    const count = await this.repository.count({
      where: { email: email.toLowerCase() },
    });
    return count > 0;
  }
}
