import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { In, IsNull, Repository } from 'typeorm';
import { ClsService } from 'nestjs-cls';
import { TenantAwareRepository } from '../../../common/repositories/tenant-aware.repository';
import { BookingCashCollectionEntity } from '../../../entities/booking-cash-collection.entity';

export type CashCollectionLineKind = 'TRANSPORT' | 'ACTIVITY' | 'SPECIAL';

export interface CashCollectionLine {
  kind: CashCollectionLineKind;
  item_id: string;
}

@Injectable()
export class BookingCashCollectionRepository extends TenantAwareRepository<BookingCashCollectionEntity> {
  constructor(
    @InjectRepository(BookingCashCollectionEntity)
    repo: Repository<BookingCashCollectionEntity>,
    cls: ClsService,
  ) {
    super(repo, cls);
  }

  async findWithRelations(id: string): Promise<BookingCashCollectionEntity | null> {
    return this.findOne({
      where: { id } as never,
      relations: {
        currency: true,
        expense_supplier: true,
        expense_driver: true,
        expense_activity: true,
        expense_collected_by_user: true,
        cash_supplier: true,
        cash_driver: true,
        cash_activity: true,
        cash_collected_by_user: true,
      },
    });
  }

  async findLiveByLine(
    line: CashCollectionLine,
  ): Promise<BookingCashCollectionEntity | null> {
    const where =
      line.kind === 'TRANSPORT'
        ? { transport_item_id: line.item_id }
        : line.kind === 'ACTIVITY'
          ? { activity_item_id: line.item_id }
          : { special_item_id: line.item_id };
    return this.findOne({
      where: where as never,
      relations: {
        currency: true,
        expense_supplier: true,
        expense_driver: true,
        expense_activity: true,
        expense_collected_by_user: true,
        cash_supplier: true,
        cash_driver: true,
        cash_activity: true,
        cash_collected_by_user: true,
      },
    });
  }

  async findLiveUnscopedByBooking(
    bookingId: string,
  ): Promise<BookingCashCollectionEntity | null> {
    return this.findOne({
      where: {
        booking_id: bookingId,
        transport_item_id: IsNull(),
        activity_item_id: IsNull(),
        special_item_id: IsNull(),
      } as never,
      order: { created_at: 'DESC' },
      relations: {
        currency: true,
        expense_supplier: true,
        expense_driver: true,
        expense_activity: true,
        expense_collected_by_user: true,
        cash_supplier: true,
        cash_driver: true,
        cash_activity: true,
        cash_collected_by_user: true,
      },
    });
  }

  async findLiveUnscoped(
    bookingId: string,
    collectionDate: string,
  ): Promise<BookingCashCollectionEntity | null> {
    return this.findOne({
      where: {
        booking_id: bookingId,
        collection_date: collectionDate,
        transport_item_id: IsNull(),
        activity_item_id: IsNull(),
        special_item_id: IsNull(),
      } as never,
      relations: {
        currency: true,
        expense_supplier: true,
        expense_driver: true,
        expense_activity: true,
        expense_collected_by_user: true,
        cash_supplier: true,
        cash_driver: true,
        cash_activity: true,
        cash_collected_by_user: true,
      },
    });
  }

  async findLiveByBookingIds(
    bookingIds: string[],
  ): Promise<BookingCashCollectionEntity[]> {
    if (bookingIds.length === 0) return [];
    return this.find({
      where: { booking_id: In(bookingIds) } as never,
      relations: {
        currency: true,
        expense_supplier: true,
        expense_driver: true,
        expense_activity: true,
        expense_collected_by_user: true,
        cash_supplier: true,
        cash_driver: true,
        cash_activity: true,
        cash_collected_by_user: true,
      },
    });
  }
}
