import fetch from "node-fetch";
import { createHmac, randomBytes } from "crypto";
import { DepositEvent, LaravelBlinkDepositPayload, LaravelDepositPayload } from "../types";

export class LaravelDepositClient {
  constructor(
    private baseUrl: string,
    private relaySecret?: string,
    private relayHmacSecret?: string
  ) {}

  async persistDeposit(event: DepositEvent): Promise<any> {
    if (event.source === "blink") {
      const payload: LaravelBlinkDepositPayload = {
        provider: "blink",
        network: "bitcoin_lightning",
        asset: "BTC",
        user_id: event.user_id,
        amount_sats: event.amount_sats || Number(event.amount),
        payment_hash: event.payment_hash || event.tx_hash,
        provider_reference: event.provider_reference || null,
        status: "confirmed",
        raw_payload: event.raw_payload,
      };

      const body = JSON.stringify(payload);
      return this.request("POST", "/api/v1/deposits", body);
    }

    const payload: LaravelDepositPayload = {
      user_id: event.user_id,
      wallet_address: event.wallet_address,
      amount: event.amount,
      asset: event.asset,
      tx_hash: event.tx_hash,
      block_number: event.block_number,
      asset_address: event.asset_address,
      from_address: event.from_address,
      to_address: event.to_address,
      chain_type: event.chain_type,
      network: event.network,
      wallet_id: event.wallet_id,
      organization_id: event.organization_id,
      branch_id: event.branch_id,
      terminal_id: event.terminal_id,
      payment_id: event.payment_id,
      supported_asset_id: event.supported_asset_id,
      derivation_index: event.derivation_index,
      idempotency_key: event.idempotency_key,
      occurred_at: event.occurred_at,
      raw_payload: event.raw_payload,
    };

    const body = JSON.stringify(payload);
    return this.request("POST", "/api/v1/deposits", body);
  }

  private async request(method: "POST", path: string, body: string): Promise<any> {
    const response = await fetch(`${this.baseUrl}${path}`, {
      method,
      headers: this.headers(body),
      body,
    });

    if (!response.ok) {
      throw new Error(`Request failed for ${path} with status ${response.status}`);
    }

    return response.json();
  }

  private headers(body: string): Record<string, string> {
    const headers: Record<string, string> = { "content-type": "application/json" };

    if (this.relaySecret) {
      headers["x-relay-secret"] = this.relaySecret;
    }

    if (this.relayHmacSecret) {
      const timestamp = Math.floor(Date.now() / 1000).toString();
      const nonce = randomBytes(16).toString("hex");
      const signature = createHmac("sha256", this.relayHmacSecret)
        .update(`${timestamp}.${nonce}.${body}`)
        .digest("hex");

      headers["x-relay-timestamp"] = timestamp;
      headers["x-relay-nonce"] = nonce;
      headers["x-relay-signature"] = signature;
    }

    return headers;
  }
}
