/**
 * TypeORM Booking Repository
 *
 * Implements BookingRepository interface using TypeORM
 */

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Booking } from '@domain/entities/booking.entity';
import { BookingNumber } from '@domain/value-objects/booking-number.vo';
import { BookingStatus } from '@domain/value-objects/booking-status.vo';
import { BookingRepository } from '@domain/ports/out/booking.repository';
import { BookingOrmEntity } from '../entities/booking.orm-entity';
import { ContainerOrmEntity } from '../entities/container.orm-entity';
import { BookingOrmMapper } from '../mappers/booking-orm.mapper';

@Injectable()
export class TypeOrmBookingRepository implements BookingRepository {
  constructor(
    @InjectRepository(BookingOrmEntity)
    private readonly bookingRepository: Repository<BookingOrmEntity>,
    @InjectRepository(ContainerOrmEntity)
    private readonly containerRepository: Repository<ContainerOrmEntity>
  ) {}

  async save(booking: Booking): Promise<Booking> {
    const orm = BookingOrmMapper.toOrm(booking);
    const saved = await this.bookingRepository.save(orm);
    return BookingOrmMapper.toDomain(saved);
  }

  async findById(id: string): Promise<Booking | null> {
    const orm = await this.bookingRepository.findOne({
      where: { id },
      relations: ['containers'],
    });
    return orm ? BookingOrmMapper.toDomain(orm) : null;
  }

  async findByBookingNumber(bookingNumber: BookingNumber): Promise<Booking | null> {
    const orm = await this.bookingRepository.findOne({
      where: { bookingNumber: bookingNumber.value },
      relations: ['containers'],
    });
    return orm ? BookingOrmMapper.toDomain(orm) : null;
  }

  async findByUser(userId: string): Promise<Booking[]> {
    const orms = await this.bookingRepository.find({
      where: { userId },
      relations: ['containers'],
      order: { createdAt: 'DESC' },
    });
    return BookingOrmMapper.toDomainMany(orms);
  }

  async findByOrganization(organizationId: string): Promise<Booking[]> {
    const orms = await this.bookingRepository.find({
      where: { organizationId },
      relations: ['containers'],
      order: { createdAt: 'DESC' },
    });
    return BookingOrmMapper.toDomainMany(orms);
  }

  async findByStatus(status: BookingStatus): Promise<Booking[]> {
    const orms = await this.bookingRepository.find({
      where: { status: status.value },
      relations: ['containers'],
      order: { createdAt: 'DESC' },
    });
    return BookingOrmMapper.toDomainMany(orms);
  }

  async findAll(): Promise<Booking[]> {
    const orms = await this.bookingRepository.find({
      relations: ['containers'],
      order: { createdAt: 'DESC' },
    });
    return BookingOrmMapper.toDomainMany(orms);
  }

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