import { Injectable, Logger } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { HttpService } from "@nestjs/axios";
import { firstValueFrom } from "rxjs";
import { PaymentEvent, PaymentService } from "@edr/types";
import { PaymentEventPublisher } from "./payment-event-publisher";

/**
 * Delivers events by POSTing to the owning app's idempotent mark-paid endpoint, routed by
 * the `service` discriminator. Authenticated with the shared service token (the same secret
 * the apps use to call /payments/initiate).
 */
@Injectable()
export class HttpPaymentEventPublisher implements PaymentEventPublisher {
  private readonly logger = new Logger(HttpPaymentEventPublisher.name);
  private readonly routes: Record<PaymentService, string>;
  private readonly timeoutMs: number;
  private readonly serviceToken: string;

  constructor(
    config: ConfigService,
    private readonly http: HttpService,
  ) {
    this.routes = {
      [PaymentService.PASSENGER]:
        config.get<string>("notifier.passengerUrl") ?? "",
      [PaymentService.FREIGHT]: config.get<string>("notifier.freightUrl") ?? "",
    };
    this.timeoutMs = config.get<number>("notifier.httpTimeoutMs") ?? 10_000;
    this.serviceToken = config.get<string>("app.serviceAuthToken") ?? "";
  }

  async publish(event: PaymentEvent): Promise<void> {
    const url = this.routes[event.service];
    if (!url) {
      throw new Error(
        `No mark-paid URL configured for service ${event.service}`,
      );
    }

    const response = await firstValueFrom(
      this.http.post(url, event, {
        timeout: this.timeoutMs,
        headers: this.serviceToken
          ? { "x-service-token": this.serviceToken }
          : {},
      }),
    );
    this.logger.log(
      `delivered ${event.eventType} (${event.eventId}) to ${event.service} — HTTP ${response.status}`,
    );
  }
}
