import { Injectable } from '@nestjs/common';
import { PrismaService } from 'src/prisma/prisma.service';
import type { IPaymentGateway, PaymentInitResult, PaymentConfirmResult, PaymentRefundResult } from './interfaces/payment-gateway.interface';

// PÚBLICO — respuestas mockeadas para demo. Sin llamadas a vpos.infonet.com.py.
// Cuando aprueben presupuesto: reemplazar por BancardVposService en bancard.module.ts
@Injectable()
export class BancardMockService implements IPaymentGateway {
  constructor(private readonly prisma: PrismaService) {}

  async initPayment(params: {
    empresaId: string;
    monto: number;
    moneda: string;
    descripcion: string;
    clienteId?: string;
    usuarioId?: string;
    origenModulo: string;
    origenId?: string;
  }): Promise<PaymentInitResult> {
    const shopProcessId = await this.generateShopProcessId(params.empresaId);

    const pago = await this.prisma.pago_bancard.create({
      data: {
        empresa_id: params.empresaId,
        shop_process_id: shopProcessId,
        process_id: `MOCK-${shopProcessId}`,
        tipo_operacion: 'single_buy',
        origen_modulo: params.origenModulo as any,
        origen_id: params.origenId ?? null,
        cliente_id: params.clienteId ?? null,
        usuario_id: params.usuarioId ?? null,
        monto: params.monto,
        moneda: params.moneda,
        estado: 'procesando',
        meta_json: { mock: true, descripcion: params.descripcion },
      },
    });

    return {
      processUrl: `mock://vpos/${shopProcessId}`,
      shopProcessId,
      pagoId: pago.id,
    };
  }

  async confirmPayment(shopProcessId: bigint, empresaId: string): Promise<PaymentConfirmResult> {
    const pago = await this.prisma.pago_bancard.findFirst({
      where: { shop_process_id: shopProcessId, empresa_id: empresaId },
    });
    return {
      aprobado: pago?.estado === 'aprobado',
      responseCode: '00',
      responseDescription: 'Aprobado',
      authorizationNumber: `MOCK-AUTH-${shopProcessId}`,
      ticketNumber: `MOCK-TKT-${shopProcessId}`,
    };
  }

  async confirmarMock(pagoId: string): Promise<void> {
    await this.prisma.pago_bancard.update({
      where: { id: pagoId },
      data: {
        estado: 'aprobado',
        response_code: '00',
        response_description: 'Aprobado (mock)',
        authorization_number: `MA${String(Date.now()).slice(-8)}`,
        ticket_number: `TKT${String(Date.now()).slice(-8)}`,
        fecha_confirmacion: new Date(),
        updated_at: new Date(),
      },
    });
  }

  async refund(_pagoId: string, _empresaId: string, _monto?: number): Promise<PaymentRefundResult> {
    return { success: true, message: 'Refund simulado (mock)' };
  }

  private async generateShopProcessId(empresaId: string): Promise<bigint> {
    const last = await this.prisma.pago_bancard.findFirst({
      where: { empresa_id: empresaId },
      orderBy: { shop_process_id: 'desc' },
      select: { shop_process_id: true },
    });
    const anio = BigInt(new Date().getFullYear() % 100);
    const seq = last ? (last.shop_process_id % 1_000_000_000n) + 1n : 1n;
    return anio * 1_000_000_000n + seq;
  }
}
