import { Processor, WorkerHost } from '@nestjs/bullmq';
import { Logger } from '@nestjs/common';
import { Job } from 'bullmq';
import { PrismaService } from '../../prisma/prisma.service';
import { createHmac } from 'crypto';

export interface WebhookJobData {
  clubId: string;
  subscriptionId: string;
  event: string;
  payload: Record<string, any>;
  secret: string;
  url: string;
}

@Processor('webhook-delivery')
export class WebhookDeliveryProcessor extends WorkerHost {
  private readonly logger = new Logger(WebhookDeliveryProcessor.name);

  constructor(private readonly prisma: PrismaService) {
    super();
  }

  async process(job: Job<WebhookJobData>): Promise<void> {
    const { clubId, subscriptionId, event, payload, secret, url } = job.data;
    const attempt = job.attemptsMade + 1;

    this.logger.log(
      `Delivering webhook: event=${event}, url=${url}, attempt=${attempt}`,
    );

    const body = JSON.stringify(payload);
    const signature = createHmac('sha256', secret).update(body).digest('hex');

    let statusCode: number | null = null;
    let response: string | null = null;

    try {
      const res = await fetch(url, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-Webhook-Signature': signature,
          'X-Webhook-Event': event,
        },
        body,
        signal: AbortSignal.timeout(10000),
      });

      statusCode = res.status;
      response = await res.text();
    } catch (err: any) {
      response = err.message;
    }

    const success = statusCode !== null && statusCode >= 200 && statusCode < 300;

    await this.prisma.webhookLog.create({
      data: {
        clubId,
        subscriptionId,
        event,
        payload,
        statusCode,
        response: response?.slice(0, 1000) ?? null,
        attempt,
        deliveredAt: success ? new Date() : null,
      },
    });

    if (!success) {
      this.logger.warn(
        `Webhook delivery failed: event=${event}, url=${url}, attempt=${attempt}, status=${statusCode}`,
      );
      throw new Error(
        `Webhook delivery failed with status ${statusCode}: ${response?.slice(0, 200)}`,
      );
    }

    this.logger.log(
      `Webhook delivered: event=${event}, url=${url}, status=${statusCode}`,
    );
  }
}
