<?php

namespace App\Domains\Integration\Services;

use App\Domains\Purchase\Models\Purchase;
use App\Domains\Purchase\Models\TelepagosPayment;
use App\Domains\Purchase\Models\TelepagosQr;
use App\Domains\Purchase\Services\CheckoutService;
use App\Domains\Tenant\Models\Tenant;
use Exception;
use Illuminate\Support\Facades\Log;

class TelepagosWebhookService
{
    public function __construct(
        private readonly CheckoutService $checkoutService,
    ) {}

    /**
     * Handle the Telepagos webhook notification.
     *
     * @param string $tenantCodigo
     * @param string $cashinId
     * @return void
     * @throws Exception
     */
    public function handleWebhook(string $tenantCodigo, string $cashinId): void
    {
        $tenant = Tenant::where('codigo', $tenantCodigo)->firstOrFail();

        $telepagosService = new TelepagosIntegrationService();
        $telepagosService->forTenant($tenant->codigo);

        try {
            $details = $telepagosService->getCashinDetails($cashinId);

            $qrOrderId = $details['data']['qr_order_id'] ?? $details['qr_order_id'] ?? null;
            $amount = $this->normalizeAmount($details['data']['amount'] ?? $details['amount'] ?? 0);
            $operationId = $details['data']['operation_id'] ?? $details['operation_id'] ?? null;

            $transferenciaOperationIds = [1, 3, 11];
            $qrOperationIds = [31, 37, 47];

            $compra = null;

            if (in_array((int) $operationId, $transferenciaOperationIds, true)) {
                $cuit = $details['data']['buyer']['cuit'] ?? $details['buyer']['cuit'] ?? null;

                if (! $cuit) {
                    Log::warning("Telepagos webhook: CUIT not found for Transferencia cashin {$cashinId}");
                    return;
                }

                $dni = substr($cuit, 2, -1);

                $compra = Purchase::where('tenant_codigo', $tenantCodigo)
                ->where('transfer_payer_dni', $dni)
                    ->whereIn('status', [Purchase::STATUS_CREATED, Purchase::STATUS_PENDING_PAYMENT])
                    ->where('payment_method', 'transfer')
                    ->where('total', $amount)
                    ->latest()
                    ->first();

                if (! $compra) {
                    Log::warning("Telepagos webhook: No matching purchase found for DNI {$dni} and amount {$amount} for cashin {$cashinId}");
                    return;
                }
            } elseif (in_array((int) $operationId, $qrOperationIds, true)) {
                if (! $qrOrderId) {
                    Log::warning("Telepagos webhook: qr_order_id not found for QR cashin {$cashinId}");
                    return;
                }

                $telepagosQr = TelepagosQr::where('qr_order_id', $qrOrderId)->first();

                if (! $telepagosQr) {
                    Log::warning("Telepagos webhook: QR {$qrOrderId} not found in database for cashin {$cashinId}");
                    return;
                }

                $compra = $telepagosQr->compra;

                if (! $compra) {
                    Log::warning("Telepagos webhook: Purchase not found for QR {$qrOrderId}");
                    return;
                }

                if ($compra->status !== Purchase::STATUS_PENDING_PAYMENT) {
                    Log::warning("Telepagos webhook: Purchase {$compra->id} is not awaiting payment confirmation");
                    return;
                }

                $totalAmount = $this->normalizeAmount($compra->getTotalAmount());

                if ($amount !== $totalAmount) {
                    Log::warning("Telepagos webhook: Amount mismatch. Cashin amount: {$amount}, Purchase amount: {$totalAmount}");
                    return;
                }
            } else {
                Log::warning("Telepagos webhook: Unknown operation_id {$operationId} for cashin {$cashinId}");
                return;
            }

            $paymentData = [
                'compra_id' => $compra->id,
                'cuit_buyer' => $details['data']['buyer']['cuit'] ?? $details['buyer']['cuit'] ?? null,
                'cvu_buyer' => $details['data']['buyer']['cvu'] ?? $details['buyer']['cvu'] ?? null,
                'amount' => $amount,
                'concept' => $details['data']['concept'] ?? $details['concept'] ?? null,
                'operation' => $details['data']['operation'] ?? $details['operation'] ?? null,
                'operation_id' => $details['data']['operation_id'] ?? $details['operation_id'] ?? null,
                'transaction_id' => $details['data']['transaction_id'] ?? $details['transaction_id'] ?? null,
                'qr_order_id' => $qrOrderId,
                'link_id' => $details['data']['link_id'] ?? $details['link_id'] ?? null,
            ];

            \Illuminate\Support\Facades\DB::transaction(function () use ($compra, $paymentData) {
                TelepagosPayment::create($paymentData);
                $this->checkoutService->confirmPurchase($compra);
                $compra->markAsPaid();
            });

            Log::info("Telepagos webhook: Successfully processed cashin {$cashinId} for purchase {$compra->id}");
        } catch (Exception $e) {
            Log::error("Telepagos webhook error: " . $e->getMessage());
            throw $e;
        }
    }

    protected function normalizeAmount(mixed $amount): string
    {
        return number_format((float) $amount, 2, '.', '');
    }
}
