import { Processor, WorkerHost } from "@nestjs/bullmq";
import { Injectable, Inject } from "@nestjs/common";
import { Logger } from "nestjs-pino";
import { OrderFulfillmentOrchestrator } from "../services/order-fulfillment-orchestrator.service.js";
import { SalesforceFacade } from "@bff/integrations/salesforce/facades/salesforce.facade.js";
import type { ProvisioningJobData } from "./provisioning.queue.js";
import { QUEUE_NAMES } from "@bff/infra/queue/queue.constants.js";

@Processor(QUEUE_NAMES.PROVISIONING)
@Injectable()
export class ProvisioningProcessor extends WorkerHost {
  constructor(
    private readonly orchestrator: OrderFulfillmentOrchestrator,
    private readonly salesforceService: SalesforceFacade,
    @Inject(Logger) private readonly logger: Logger
  ) {
    super();
  }

  async process(job: { data: ProvisioningJobData }): Promise<void> {
    const { sfOrderId, idempotencyKey } = job.data;
    this.logger.log("Processing provisioning job", {
      sfOrderId,
      idempotencyKey,
      correlationId: job.data.correlationId,
    });

    const order = await this.salesforceService.getOrder(sfOrderId);
    const activationStatus = order?.Activation_Status__c ?? "";
    const orderStatus = order?.Status ?? "";
    const simType = order?.SIM_Type__c ?? "";
    const assignedPhysicalSim = order?.Assign_Physical_SIM__c ?? "";
    const lastErrorCode = order?.Activation_Error_Code__c ?? "";

    // Guard: Determine if this is a valid provisioning request
    // Case 1: Standard flow - Activation_Status__c = "Activating"
    // Case 2: Physical SIM flow - Status = "Approved" with SIM_Type__c = "Physical SIM"
    const isStandardActivation = activationStatus === "Activating";
    const isPhysicalSimApproval =
      orderStatus === "Approved" && simType === "Physical SIM" && !!assignedPhysicalSim;

    if (!isStandardActivation && !isPhysicalSimApproval) {
      this.logger.log("Skipping provisioning job: Order not in activatable state", {
        sfOrderId,
        activationStatus,
        orderStatus,
        simType,
        hasAssignedPhysicalSim: !!assignedPhysicalSim,
      });
      return; // Ack + no-op to safely handle duplicate/old events
    }

    // Guard: Avoid thrashing on known user-actionable failures
    if (lastErrorCode === "PAYMENT_METHOD_MISSING") {
      this.logger.log("Skipping provisioning job: Awaiting payment method addition", {
        sfOrderId,
        activationStatus,
        lastErrorCode,
      });
      return;
    }

    this.logger.log("Proceeding with provisioning", {
      sfOrderId,
      isStandardActivation,
      isPhysicalSimApproval,
      simType,
    });

    // Execute the same orchestration used by the webhook path, but without payload validation
    await this.orchestrator.executeFulfillment(sfOrderId, {}, idempotencyKey);
    this.logger.log("Provisioning job completed", { sfOrderId });
  }
}
