<?php

namespace App\Jobs;

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\DB;
use Illuminate\Support\Facades\Log;
use App\Services\VipResellerService;
use App\Services\EmailNotificationService;

class ProcessOrderJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public $transactionId;
    
    // ✅ RETRY CONFIGURATION
    public $tries = 3;  // Retry 3 times
    public $backoff = [30, 60, 120];  // Retry after 30s, 60s, 120s
    public $timeout = 120;  // Timeout after 2 minutes

    /**
     * Create a new job instance.
     */
    public function __construct($transactionId)
    {
        $this->transactionId = $transactionId;
    }

    /**
     * Execute the job.
     */
    public function handle(
        VipResellerService $vipResellerService,
        EmailNotificationService $emailService
    )
    {
        try {
            Log::info('Processing order job started', ['transaction_id' => $this->transactionId]);
            
            // Get transaction
            $transaction = DB::table('transactions')->where('id', $this->transactionId)->first();
            
            if (!$transaction) {
                Log::error('Transaction not found in job', ['transaction_id' => $this->transactionId]);
                return;
            }
            
            // ✅ PREVENT DUPLICATE PROCESSING
            if ($transaction->status === 'success') {
                Log::info('Transaction already success, skipping', ['invoice' => $transaction->invoice_number]);
                return;
            }
            
            // ✅ LOCK MECHANISM (prevent concurrent processing)
            $lockKey = 'process_order_' . $transaction->id;
            $lock = cache()->lock($lockKey, 60);  // 60 second lock
            
            if (!$lock->get()) {
                Log::info('Order already being processed, skipping', ['invoice' => $transaction->invoice_number]);
                return;
            }
            
            try {
                // Update status to processing
                DB::table('transactions')->where('id', $transaction->id)->update([
                    'status' => 'processing',
                    'processing_attempts' => DB::raw('COALESCE(processing_attempts, 0) + 1'),
                    'last_processed_at' => now(),
                    'updated_at' => now(),
                ]);
                
                // Call VIP Reseller API
                Log::info('Calling VIP Reseller API', [
                    'invoice' => $transaction->invoice_number,
                    'product_code' => $transaction->product_code,
                    'attempt' => $this->attempts()
                ]);
                
                $result = $vipResellerService->createOrder(
                    $transaction->product_code,
                    $transaction->customer_data
                );
                
                Log::info('VIP Reseller API Response', [
                    'invoice' => $transaction->invoice_number,
                    'result' => $result
                ]);
                
                if ($result['success']) {
                    $data = $result['data'];
                    
                    // Update transaction with success
                    DB::table('transactions')->where('id', $transaction->id)->update([
                        'trx_id' => $data['trxid'] ?? null,
                        'provider_response' => json_encode($result),
                        'provider_status' => $data['status'] ?? null,
                        'provider_note' => $data['note'] ?? null,
                        'provider_sn' => $data['sn'] ?? null,
                        'status' => $this->mapProviderStatus($data['status'] ?? 'waiting'),
                        'completed_at' => now(),
                        'updated_at' => now(),
                    ]);
                    
                    // Send order complete email
                    if (($data['status'] ?? '') === 'success' && $transaction->customer_email) {
                        try {
                            $updatedTransaction = DB::table('transactions')->where('id', $transaction->id)->first();
                            $emailService->sendOrderComplete($updatedTransaction);
                            Log::info('Order complete email sent', ['invoice' => $transaction->invoice_number]);
                        } catch (\Exception $e) {
                            Log::error('Failed to send order complete email', [
                                'invoice' => $transaction->invoice_number,
                                'error' => $e->getMessage()
                            ]);
                        }
                    }
                    
                    Log::info('Order processed successfully', ['invoice' => $transaction->invoice_number]);
                    
                } else {
                    // API returned error
                    $errorMessage = $result['message'] ?? 'Unknown error';
                    
                    Log::error('VIP Reseller API Error', [
                        'invoice' => $transaction->invoice_number,
                        'error' => $errorMessage,
                        'attempt' => $this->attempts()
                    ]);
                    
                    // Update with error
                    DB::table('transactions')->where('id', $transaction->id)->update([
                        'provider_response' => json_encode($result),
                        'provider_note' => $errorMessage,
                        'updated_at' => now(),
                    ]);
                    
                    // ✅ THROW EXCEPTION TO TRIGGER RETRY
                    throw new \Exception('API Error: ' . $errorMessage);
                }
                
            } finally {
                // Release lock
                $lock->release();
            }
            
        } catch (\Exception $e) {
            Log::error('Process Order Job Error', [
                'transaction_id' => $this->transactionId,
                'attempt' => $this->attempts(),
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            
            // ✅ IF THIS IS LAST ATTEMPT, MARK AS FAILED
            if ($this->attempts() >= $this->tries) {
                Log::error('Order processing failed after all retries', [
                    'transaction_id' => $this->transactionId,
                    'attempts' => $this->attempts()
                ]);
                
                DB::table('transactions')->where('id', $this->transactionId)->update([
                    'status' => 'failed',
                    'provider_note' => 'Processing failed after ' . $this->attempts() . ' attempts: ' . $e->getMessage(),
                    'failed_at' => now(),
                    'updated_at' => now(),
                ]);
                
                // Send failure email
                try {
                    $transaction = DB::table('transactions')->where('id', $this->transactionId)->first();
                    if ($transaction && $transaction->customer_email) {
                        $emailService = app(EmailNotificationService::class);
                        $emailService->sendOrderFailed($transaction);
                    }
                } catch (\Exception $emailError) {
                    Log::error('Failed to send failure email', ['error' => $emailError->getMessage()]);
                }
            } else {
                // ✅ RE-THROW TO TRIGGER RETRY
                throw $e;
            }
        }
    }
    
    /**
     * Handle job failure
     */
    public function failed(\Throwable $exception)
    {
        Log::error('ProcessOrderJob permanently failed', [
            'transaction_id' => $this->transactionId,
            'error' => $exception->getMessage()
        ]);
    }
    
    /**
     * Map VIP Reseller status to internal status
     */
    private function mapProviderStatus($providerStatus)
    {
        $statusMap = [
            'waiting' => 'processing',
            'process' => 'processing',
            'success' => 'success',
            'failed' => 'failed',
            'error' => 'failed',
        ];
        
        return $statusMap[$providerStatus] ?? 'processing';
    }
}
