import { PaymentMethod, Provider } from "@prisma/client";

export interface ProviderCreatePaymentInput {
  /** ID interno del intent — se envía al provider como referencia externa. */
  intentId: string;
  amount: string; // decimal serializado (ej. "150000.0000")
  currency: string; // ISO 4217
  country: string; // ISO 3166-1 alpha-2
  description?: string | null;
  externalReference?: string | null;
  customer?: {
    email?: string | null;
    name?: string | null;
    docType?: string | null;
    docNumber?: string | null;
    phone?: string | null;
    country?: string | null;
  };
  /** URLs a las que el provider redirige al usuario tras el pago (hosted checkout). */
  returnUrl?: string;
  cancelUrl?: string;
  /** Webhook URL del propio gateway al que el provider notifica resultados (no del merchant). */
  notificationUrl?: string;
  /**
   * Medio de pago elegido por el comprador, en el código propio del provider.
   * Requerido por providers que exigen seleccionar el medio antes de crear la
   * transacción (ej. `platformId` de Dpago). Los que dejan elegir en su propio
   * checkout (ej. dLocal) lo ignoran.
   */
  platformId?: string;
  /** Método interno ya resuelto desde el catálogo (provider_payment_method). */
  method?: PaymentMethod;
  /**
   * Pedir explícitamente un LINK DE PAGO nativo del provider (ej. Dpago `/links`)
   * en vez de una transacción directa. Fuerza el link aunque haya platformId o
   * defaultPlatformId configurado. Los providers sin link nativo lo ignoran.
   */
  preferLink?: boolean;
}

export type ProviderPaymentStatus =
  | "pending"
  | "processing"
  | "approved"
  | "rejected"
  | "expired"
  | "error";

export interface ProviderCreatePaymentResult {
  providerPaymentId: string;
  status: ProviderPaymentStatus;
  method: PaymentMethod;
  /** URL a la que redirigir al comprador si el provider hospedó el checkout. */
  redirectUrl?: string | null;
  /**
   * Datos para renderizar un QR sin redirección (ej. `qrInformation` de Dpago).
   * Presente cuando el medio elegido es de tipo QR y el provider devuelve el QR
   * inline en vez de una URL de checkout. Shape específico de cada provider.
   */
  qrData?: unknown | null;
  responseCode?: string | null;
  responseMessage?: string | null;
  rawRequest: unknown;
  rawResponse: unknown;
}

export interface ProviderGetPaymentResult {
  providerPaymentId: string;
  status: ProviderPaymentStatus;
  responseCode?: string | null;
  responseMessage?: string | null;
  rawResponse: unknown;
}

export interface ProviderRefundInput {
  providerPaymentId: string;
  amount: string;
  reason?: string | null;
}

export interface ProviderRefundResult {
  providerRefundId: string;
  status: "pending" | "approved" | "rejected" | "error";
  responseCode?: string | null;
  responseMessage?: string | null;
  rawRequest: unknown;
  rawResponse: unknown;
}

export interface ProviderAdapter {
  readonly provider: Provider;
  createPayment(input: ProviderCreatePaymentInput): Promise<ProviderCreatePaymentResult>;
  getPayment(providerPaymentId: string): Promise<ProviderGetPaymentResult>;
  refund(input: ProviderRefundInput): Promise<ProviderRefundResult>;
  /** Verifica firma del webhook entrante del provider y devuelve el evento normalizado. */
  parseWebhook(rawBody: string, headers: Record<string, string>): {
    providerPaymentId: string;
    status: ProviderPaymentStatus;
    raw: unknown;
  } | null;
}
