import { events } from '../../libs/event';
import logger from '../../libs/logger';
import createQueue from '../../libs/queue';
import { VendorFulfillmentService } from '../../libs/vendor-util/fulfillment';
import { CheckoutSession } from '../../store/models/checkout-session';
import { updateVendorFulfillmentStatus } from './fulfillment-coordinator';

type VendorFulfillmentJob = {
  checkoutSessionId: string;
  invoiceId: string;
  vendorId: string;
  vendorConfig: any;
  retryOnError?: boolean;
};

export const handleVendorFulfillment = async (job: VendorFulfillmentJob) => {
  logger.debug('Raw job received in handleVendorFulfillment', {
    job,
    jobKeys: Object.keys(job),
  });

  const { checkoutSessionId, invoiceId, vendorId, vendorConfig } = job;

  try {
    const checkoutSession = await CheckoutSession.findByPk(checkoutSessionId);
    if (!checkoutSession) {
      throw new Error(`CheckoutSession not found: ${checkoutSessionId}`);
    }

    const orderInfo = {
      checkoutSessionId,
      amount_total: checkoutSession.amount_total,
      customer_id: checkoutSession.customer_id || '',
      invoiceId,
      currency_id: checkoutSession.currency_id,
      customer_did: checkoutSession.customer_did || '',
    };
    const fulfillmentResult = await VendorFulfillmentService.fulfillSingleVendorOrder(orderInfo, vendorConfig);

    logger.info('Vendor fulfillment has been sent', {
      vendorId,
      orderId: fulfillmentResult.orderId,
      status: fulfillmentResult.status,
    });

    await updateVendorFulfillmentStatus(checkoutSessionId, invoiceId, vendorId, 'sent', {
      orderId: fulfillmentResult.orderId,
      commissionAmount: fulfillmentResult.commissionAmount,
      serviceUrl: fulfillmentResult.serviceUrl,
    });
  } catch (error: any) {
    logger.error('Vendor fulfillment failed', {
      vendorId,
      checkoutSessionId,
      error,
    });

    await updateVendorFulfillmentStatus(checkoutSessionId, invoiceId, vendorId, 'failed', {
      lastError: error.message,
    });

    throw error;
  }
};

export const vendorFulfillmentQueue = createQueue<VendorFulfillmentJob>({
  name: 'vendor-fulfillment',
  onJob: handleVendorFulfillment,
  options: {
    concurrency: 1,
    maxRetries: 3,
    enableScheduledJob: true,
  },
});

export const startVendorFulfillmentQueue = () => {
  logger.debug('startVendorFulfillmentQueue');
  return Promise.resolve();
};

events.on('vendor.fulfillment.queued', async (id, job) => {
  try {
    const exist = await vendorFulfillmentQueue.get(id);
    if (!exist) {
      vendorFulfillmentQueue.push({
        id,
        job,
      });
    } else {
      logger.info('Vendor fulfillment job already exists, skipping', { id });
    }
  } catch (error: any) {
    logger.error('Failed to handle vendor fulfillment queue event', {
      id,
      error: error.message,
    });
  }
});
