import type { HybxClient } from './HybxClient';
import type {
  HybxPaymentRequest,
  HybxPaymentResponse,
  HybxSettlementEvent,
  HybxWebhookPayload,
} from './types';
import { loadHybxConfig, type HybxConfig } from './config';

/**
 * HTTP HYBX client — uses api-fineract-unified spec (Volume 20).
 * Production allowed when HYBX_UNIFIED_API_OK=1 and unified manifest exists.
 */

export class HttpHybxClient implements HybxClient {
  readonly environment: string;
  private readonly config: HybxConfig;

  constructor(options?: { config?: HybxConfig; testMode?: boolean; allowProduction?: boolean }) {
    this.config = options?.config ?? loadHybxConfig({ testMode: options?.testMode ?? true });
    this.environment = this.config.environment;
    const unifiedOk = process.env.HYBX_UNIFIED_API_OK === '1' || options?.allowProduction === true;
    if (this.config.environment === 'production' && !unifiedOk) {
      throw new Error(
        'HttpHybxClient production requires HYBX_UNIFIED_API_OK=1 (api-fineract-unified.v1.openapi.yaml integrated)'
      );
    }
  }

  private async postJson<T>(path: string, body: unknown): Promise<T> {
    const controller = new AbortController();
    const timeout = setTimeout(() => controller.abort(), this.config.requestTimeoutMs);
    try {
      const res = await fetch(`${this.config.baseUrl}${path}`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-API-Key': this.config.apiKey,
          Authorization: `Bearer ${this.config.clientSecret}`,
        },
        body: JSON.stringify(body),
        signal: controller.signal,
      });
      if (!res.ok) {
        throw new Error(`HYBX HTTP ${res.status}: ${await res.text()}`);
      }
      return (await res.json()) as T;
    } finally {
      clearTimeout(timeout);
    }
  }

  async initiatePayment(request: HybxPaymentRequest): Promise<HybxPaymentResponse> {
    return this.postJson<HybxPaymentResponse>('/v1/payments', request);
  }

  async getPaymentStatus(paymentId: string): Promise<HybxPaymentResponse> {
    const res = await fetch(`${this.config.baseUrl}/v1/payments/${paymentId}`, {
      headers: { 'X-API-Key': this.config.apiKey },
    });
    if (!res.ok) throw new Error(`HYBX HTTP ${res.status}`);
    return (await res.json()) as HybxPaymentResponse;
  }

  async listSettlementEvents(since?: string): Promise<HybxSettlementEvent[]> {
    const q = since ? `?since=${encodeURIComponent(since)}` : '';
    const res = await fetch(`${this.config.baseUrl}/v1/settlement-events${q}`, {
      headers: { 'X-API-Key': this.config.apiKey },
    });
    if (!res.ok) throw new Error(`HYBX HTTP ${res.status}`);
    return (await res.json()) as HybxSettlementEvent[];
  }

  parseWebhookPayload(body: string): HybxWebhookPayload {
    const parsed = JSON.parse(body) as Record<string, unknown>;
    return {
      eventType: String(parsed.eventType ?? 'unknown'),
      eventId: String(parsed.eventId ?? ''),
      timestamp: String(parsed.timestamp ?? new Date().toISOString()),
      data: (parsed.data as Record<string, unknown>) ?? parsed,
    };
  }
}
