import { Injectable, Inject } from "@nestjs/common";
import { InjectQueue } from "@nestjs/bullmq";
import { Queue } from "bullmq";
import { Logger } from "nestjs-pino";
import { QUEUE_NAMES } from "@bff/infra/queue/queue.constants";

export interface ProvisioningJobData {
  sfOrderId: string;
  idempotencyKey: string;
  correlationId?: string;
}

@Injectable()
export class ProvisioningQueueService {
  constructor(
    @InjectQueue(QUEUE_NAMES.PROVISIONING) private readonly queue: Queue<ProvisioningJobData>,
    @Inject(Logger) private readonly logger: Logger
  ) {}

  async enqueue(job: ProvisioningJobData): Promise<void> {
    const jobId = job.idempotencyKey || `sf:${job.sfOrderId}`;
    try {
      await this.queue.add("provision", job, {
        jobId,
        removeOnComplete: 100,
        removeOnFail: 100,
        attempts: 1, // No automatic retries; Salesforce is source of truth for retry
      });
      // Use info level so it's visible in default logs
      this.logger.log("Queued provisioning job", {
        sfOrderId: job.sfOrderId,
        idempotencyKey: job.idempotencyKey,
        correlationId: job.correlationId,
      });
    } catch (err: unknown) {
      const msg = err instanceof Error ? err.message : String(err);
      if (/already exists/i.test(msg)) {
        this.logger.debug("Duplicate provisioning job ignored", {
          sfOrderId: job.sfOrderId,
          jobId,
        });
        return;
      }
      throw err;
    }
  }

  async depth(): Promise<number> {
    const counts = await this.queue.getJobCounts("waiting", "active", "delayed");
    return (counts.waiting || 0) + (counts.active || 0) + (counts.delayed || 0);
  }
}
