import { InjectQueue, Processor, WorkerHost } from '@nestjs/bullmq';
import { Job, Queue, Worker } from 'bullmq';
import { TourService } from 'src/modules/feat-business-objects/entities/tour/tour.service';
import { TOURS_QUEUE } from 'src/modules/feat-business-objects/entities/tour/tour.tokens';
import { DispoLiveExtractorsService } from '../../feat-extractors/dispo-live-extractors.service';
import { firstValueFrom, from, lastValueFrom, map, switchMap, tap } from 'rxjs';
import { TourTransformer } from '../../feat-transformers/transformers/tour.transformer';
import { TourSource } from '@prisma/client';
import { ToursCalculationAdapater } from '../../feat-transformers/adapter/tours-calculation.adapter';
import { Logger } from '@nestjs/common';

@Processor(TOURS_QUEUE, {
  limiter: {
    duration: 1000,
    max: 10,
  },
})
export class ToursConsumer extends WorkerHost {
  private readonly logger = new Logger(ToursConsumer.name);

  constructor(
    private readonly service: TourService,
    private readonly apiService: DispoLiveExtractorsService,
    private readonly tourCalculationAdapter: ToursCalculationAdapater,
  ) {
    super();
  }

  async process(job: Job, token?: string): Promise<any> {
    let isCreate = false;
    switch (job.name) {
      case 'Create':
        isCreate = true;
      case 'Update':
        this.logger.log(`Working on Job(${job.id}): ${job.data?.id}`);
        const tour = await lastValueFrom(
          this.apiService.extractTour(job.data?.id, job.id).pipe(
            map((tour) =>
              TourTransformer.transform({
                ...tour,
                id: tour._id ?? tour.id,
                insertedAt: new Date(),
                internalId: tour.jobId,
              } as TourSource),
            ),
            switchMap((tour) =>
              from(
                this.tourCalculationAdapter.addRevenueAndConsumptionCostsToTours(
                  [tour],
                ),
              ).pipe(map(([tour]) => tour)),
            ),
          ),
        );
        if (isCreate || job.name === 'Create') {
          return await this.service.createTour(tour).then(() => this.logger.log(`Created tour ${tour.id} successfully`));
        } 
        return await this.service.updateTour(tour.id, tour).then(() => this.logger.log(`Updated tour ${tour.id} successfully`));
      default:
        console.log(`No case matched`, job);
    }
  }
}
