<?php
namespace App\Jobs;
use App\Application\Services\Payouts\{PayoutPolicyService,PayoutStateMachine,PayoutSettlementService};use App\Domain\Blockchain\Contracts\BlockchainGateway;use App\Domain\Blockchain\Data\TransferRequest;use App\Models\{OperationsAlert,Payout};use Illuminate\Bus\Queueable;use Illuminate\Contracts\Queue\ShouldQueue;use Illuminate\Foundation\Bus\Dispatchable;use Illuminate\Queue\InteractsWithQueue;use Illuminate\Queue\SerializesModels;use Illuminate\Support\Facades\Cache;use Throwable;
final class BroadcastPayoutJob implements ShouldQueue {use Dispatchable,InteractsWithQueue,Queueable,SerializesModels;public int $tries=1;public int $timeout=60;public function __construct(public int $payoutId){$this->onQueue('payouts');}
 public function handle(BlockchainGateway $gateway,PayoutPolicyService $policy,PayoutStateMachine $sm):void{$lock=Cache::lock("payout-broadcast:{$this->payoutId}",180);if(!$lock->get())return;try{$p=Payout::with('asset')->findOrFail($this->payoutId);if(!in_array($p->status,['approved','broadcasting'],true))return;$policy->assertNoKillSwitch($p);$providerKey=$p->provider_idempotency_key?:'payout-'.$p->public_id;$p->update(['provider_idempotency_key'=>$providerKey]);if($p->provider_transfer_id){$transfer=$gateway->getTransfer($p->provider_transfer_id);}else{$sm->transition($p,'broadcasting');$p->update(['broadcast_started_at'=>now()]);try{$transfer=$gateway->createTransfer(new TransferRequest($p->asset->network,$p->asset->code,$p->to_address,(string)$p->amount_atomic,$providerKey));}catch(Throwable $e){OperationsAlert::create(['severity'=>'critical','code'=>'PAYOUT_BROADCAST_AMBIGUOUS','subject_type'=>'payout','subject_id'=>(string)$p->id,'message'=>'Transfer creation failed or timed out; provider acceptance must be checked before retry.','context'=>['provider_idempotency_key'=>$providerKey,'error'=>$e->getMessage()]]);$p->update(['status'=>'manual_review','failure_reason'=>$e->getMessage()]);return;}}
   $p->update(['provider_transfer_id'=>$transfer->providerTransferId,'tx_hash'=>$transfer->txHash,'broadcast_at'=>now()]);$sm->transition($p,'confirming');SyncPayoutJob::dispatch($p->id)->delay(now()->addSeconds(10))->onQueue('payouts');
  }finally{$lock->release();}}
}
