<?php

namespace App\Jobs;

use App\Application\Services\Blockchain\Trc20TransactionProcessor;
use App\Domain\Blockchain\Contracts\BlockchainGateway;
use App\Models\{Asset,Payout,ProviderEvent};
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Throwable;

final class ProcessProviderEventJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
    public int $tries = 10;
    public array $backoff = [5,15,30,60,120,300];
    public function __construct(public int $providerEventId) { $this->onQueue('provider-webhooks'); }

    public function handle(BlockchainGateway $gateway, Trc20TransactionProcessor $processor): void
    {
        $event = ProviderEvent::findOrFail($this->providerEventId);
        if ($event->processed_at) return;
        try {
            $payload = (array) $event->raw_payload;
            if (isset($payload['third_party_id'])) {
                $payout = Payout::where('provider_idempotency_key', (string) $payload['third_party_id'])->first();
                if ($payout && !empty($payload['cid'])) {
                    $payout->update(['provider_transfer_id' => (string) $payload['cid'], 'tx_hash' => $payload['txid'] ?? $payout->tx_hash]);
                    SyncPayoutJob::dispatch($payout->id)->onQueue('payouts');
                }
            } else {
                $txid = (string) ($payload['txid'] ?? '');
                if ($txid === '') throw new \RuntimeException('PROVIDER_DEPOSIT_TXID_MISSING');
                $asset = Asset::where('network', 'tron')
                    ->where('contract_address', (string) ($payload['token_id'] ?? ''))
                    ->where('enabled', true)->firstOrFail();
                $processor->process($gateway->getTransaction('tron', $txid), $asset);
            }
            $event->update(['processed_at' => now(), 'processing_error' => null]);
        } catch (Throwable $e) {
            $event->update(['processing_error' => substr($e->getMessage(), 0, 2000)]);
            throw $e;
        }
    }
}
