<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Services\TripayService;
use App\Services\VipResellerService;
use App\Services\EmailNotificationService;  
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Auth;
use App\Jobs\ProcessOrderJob;
use Illuminate\Support\Str;
use Carbon\Carbon;

class TripayController extends Controller
{
    private $tripayService;
    private $vipResellerService;
    private $emailService;  // ← ADD THIS
    
    public function __construct(
        TripayService $tripayService, 
        VipResellerService $vipResellerService,
        EmailNotificationService $emailService  // ← ADD THIS
    ) {
        $this->tripayService = $tripayService;
        $this->vipResellerService = $vipResellerService;
        $this->emailService = $emailService;  // ← ADD THIS
    }
    
    /**
     * Get available payment channels
     */
    public function getChannels()
    {
        $result = $this->tripayService->getPaymentChannels();
        
        if ($result['success']) {
            // Group by category
            $grouped = [
                'va' => [],
                'ewallet' => [],
                'retail' => [],
            ];
            
            foreach ($result['data'] as $channel) {
                // Skip inactive channels
                if (!$channel['active']) continue;
                
                $code = strtoupper($channel['code']);
                $group = strtoupper($channel['group']);
                
                // E-Wallet
                if ($group === 'E-WALLET' || in_array($code, ['OVO', 'DANA', 'SHOPEEPAY', 'LINKAJA', 'QRIS', 'QRISC', 'QRIS2'])) {
                    $grouped['ewallet'][] = [
                        'code' => $channel['code'],
                        'name' => $channel['name'],
                        'fee_percent' => $channel['fee_customer']['percent'] ?? 0,
                        'fee_flat' => $channel['fee_customer']['flat'] ?? 0,
                        'icon_url' => $channel['icon_url'] ?? null,
                    ];
                }
                // Virtual Account
                elseif ($group === 'VIRTUAL-ACCOUNT' || str_contains($code, 'VA')) {
                    $grouped['va'][] = [
                        'code' => $channel['code'],
                        'name' => $channel['name'],
                        'fee_percent' => $channel['fee_customer']['percent'] ?? 0,
                        'fee_flat' => $channel['fee_customer']['flat'] ?? 0,
                        'icon_url' => $channel['icon_url'] ?? null,
                    ];
                }
                // Retail
                else {
                    $grouped['retail'][] = [
                        'code' => $channel['code'],
                        'name' => $channel['name'],
                        'fee_percent' => $channel['fee_customer']['percent'] ?? 0,
                        'fee_flat' => $channel['fee_customer']['flat'] ?? 0,
                        'icon_url' => $channel['icon_url'] ?? null,
                    ];
                }
            }
            
            return response()->json([
                'success' => true,
                'data' => $grouped
            ]);
        }
        
        // Fallback if API fails
        return response()->json([
            'success' => true,
            'data' => $this->getFallbackChannels()
        ]);
    }
    
    /**
     * Fallback payment channels for sandbox
     */
    private function getFallbackChannels()
    {
        return [
            // E-Wallet FIRST (Murah!)
            'ewallet' => [
                ['code' => 'QRIS', 'name' => 'QRIS (Semua E-Wallet)', 'fee_percent' => 0.7, 'active' => true],
                ['code' => 'SHOPEEPAY', 'name' => 'ShopeePay', 'fee_percent' => 1.5, 'active' => true],
                ['code' => 'DANA', 'name' => 'DANA', 'fee_percent' => 1.5, 'active' => true],
                ['code' => 'OVO', 'name' => 'OVO', 'fee_percent' => 2, 'active' => true],
            ],
            
            // Retail (Sedang)
            'retail' => [
                ['code' => 'ALFAMART', 'name' => 'Alfamart', 'fee_flat' => 2500, 'active' => true],
                ['code' => 'INDOMARET', 'name' => 'Indomaret', 'fee_flat' => 2500, 'active' => true],
            ],
            
            // VA (Mahal tapi tetap available)
            'va' => [
                ['code' => 'BRIVA', 'name' => 'BRI Virtual Account', 'fee_flat' => 4000, 'active' => true],
                ['code' => 'BCAVA', 'name' => 'BCA Virtual Account', 'fee_flat' => 4000, 'active' => true],
                ['code' => 'BNIVA', 'name' => 'BNI Virtual Account', 'fee_flat' => 4000, 'active' => true],
            ],
        ];
    }
    
    /**
     * Create payment transaction
     */
    public function createPayment(Request $request)
    {
        try {
            $validated = $request->validate([
                'product_id' => 'required|integer',
                'customer_data' => 'required|string',
                'payment_method' => 'required|string',
                'customer_name' => 'required|string',
                'customer_email' => 'required|email',
                'customer_phone' => 'nullable|string',
            ]);
            
            $customerData = $validated['customer_data'];
            
            // Get product
            $product = DB::table('products')
                ->join('categories', 'products.category_id', '=', 'categories.id')
                ->where('products.id', $validated['product_id'])
                ->select('products.*', 'categories.name as category_name', 'categories.slug as category_slug')
                ->first();
            
            if (!$product) {
                return response()->json([
                    'success' => false,
                    'message' => 'Product not found'
                ], 404);
            }
            
            // Pricing
            $productPrice = (int) $product->selling_price;
            $paymentFee = $this->tripayService->calculateFee($validated['payment_method'], $productPrice);
            $totalAmount = $productPrice + $paymentFee;
            $basePrice = $product->base_price ?? $productPrice;
            $marginAmount = $productPrice - $basePrice;
            
            // Generate references
            $invoiceNumber = 'INV-' . date('Ymd') . '-' . strtoupper(Str::random(8));
            $merchantRef = 'TRX-' . time() . '-' . strtoupper(Str::random(6));
            $defaultExpiredAt = Carbon::now()->addHour();
            
            // Create transaction in database
            $transactionId = DB::table('transactions')->insertGetId([
                'invoice_number' => $invoiceNumber,
                'merchant_ref' => $merchantRef,
                'product_id' => $product->id,
                'customer_name' => $validated['customer_name'],
                'customer_email' => $validated['customer_email'],
                'customer_phone' => $validated['customer_phone'],
                'customer_data' => $customerData,
                'product_name' => $product->name,
                'product_code' => $product->sku,
                'base_price' => $basePrice,
                'margin_amount' => $marginAmount,
                'product_price' => $productPrice,
                'payment_fee' => $paymentFee,
                'total_amount' => $totalAmount,
                'payment_method' => $validated['payment_method'],
                'status' => 'pending',
                'payment_status' => 'UNPAID',
                'expired_at' => $defaultExpiredAt,
                'created_at' => now(),
                'updated_at' => now(),
            ]);
            
            // Create Tripay payment
            $tripayResult = $this->tripayService->createTransaction([
                'method' => $validated['payment_method'],
                'merchant_ref' => $merchantRef,
                'amount' => $totalAmount,
                'customer_name' => $validated['customer_name'],
                'customer_email' => $validated['customer_email'],
                'customer_phone' => $validated['customer_phone'] ?? '081234567890',
                'order_items' => [
                    [
                        'sku' => $product->sku,
                        'name' => $product->name,
                        'price' => $productPrice,
                        'quantity' => 1,
                    ],
                    [
                        'sku' => 'FEE',
                        'name' => 'Biaya Payment Gateway',
                        'price' => $paymentFee,
                        'quantity' => 1,
                    ],
                ],
                'return_url' => url('/transactions/' . $invoiceNumber . '/payment'),
            ]);
            
            if (!$tripayResult['success']) {
                DB::table('transactions')->where('id', $transactionId)->delete();
                
                return response()->json([
                    'success' => false,
                    'message' => $tripayResult['message']
                ], 400);
            }
            
            // Calculate proper expired time
            $expiredTime = $defaultExpiredAt;
            if (isset($tripayResult['data']['expired_time'])) {
                try {
                    $tripayExpired = Carbon::createFromTimestamp($tripayResult['data']['expired_time']);
                    $minExpired = Carbon::now()->addMinutes(10);
                    if ($tripayExpired->greaterThan($minExpired)) {
                        $expiredTime = $tripayExpired;
                    }
                } catch (\Exception $e) {
                    Log::warning('Failed to parse Tripay expired time', [
                        'expired_time' => $tripayResult['data']['expired_time'],
                        'error' => $e->getMessage()
                    ]);
                }
            }
            
            // Update transaction with Tripay reference
            DB::table('transactions')->where('id', $transactionId)->update([
                'reference' => $tripayResult['data']['reference'],
                'checkout_url' => $tripayResult['data']['checkout_url'] ?? null,
                'payment_name' => $validated['payment_method'],
                'payment_instructions' => isset($tripayResult['data']['instructions']) ? json_encode($tripayResult['data']['instructions']) : null,
                'expired_at' => $expiredTime,
                'updated_at' => now(),
            ]);
            
            // 📧 EMAIL 1: Send "Order Created" notification
            $transaction = DB::table('transactions')->where('id', $transactionId)->first();
            if ($transaction && $transaction->customer_email) {
                try {
                    $this->emailService->sendOrderCreated($transaction);
                    Log::info('Order created email sent', ['invoice' => $invoiceNumber]);
                } catch (\Exception $e) {
                    Log::error('Failed to send order created email', [
                        'invoice' => $invoiceNumber,
                        'error' => $e->getMessage()
                    ]);
                }
            }
            
            return response()->json([
                'success' => true,
                'data' => [
                    'transaction_id' => $transactionId,
                    'invoice_number' => $invoiceNumber,
                    'checkout_url' => $tripayResult['data']['checkout_url'],
                    'payment_url' => $tripayResult['data']['checkout_url'],
                    'qr_url' => $tripayResult['data']['qr_url'] ?? null,
                    'reference' => $tripayResult['data']['reference'],
                    'amount' => $tripayResult['data']['amount'],
                    'total_fee' => $tripayResult['data']['total_fee'] ?? 0,
                ]
            ]);
            
        } catch (\Exception $e) {
            Log::error('Create Payment Error', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            
            return response()->json([
                'success' => false,
                'message' => 'Failed to create payment: ' . $e->getMessage()
            ], 500);
        }
    }
    
   public function callback(Request $request)
    {
        try {
            $json = $request->getContent();
            $signature = $request->header('X-Callback-Signature');
            
            // Verify signature
            if (!$this->tripayService->verifyCallbackSignature($json, $signature)) {
                Log::error('Tripay Invalid Signature', ['signature' => $signature]);
                return response()->json(['success' => false], 400);
            }
            
            $data = json_decode($json, true);
            
            Log::info('Tripay Callback', ['data' => $data]);
            
            // Get transaction by reference
            $transaction = DB::table('transactions')
                ->where('reference', $data['reference'])
                ->first();
            
            if (!$transaction) {
                Log::error('Transaction not found', ['reference' => $data['reference']]);
                return response()->json(['success' => false], 404);
            }
            
            // ✅ FIX 1: PREVENT DUPLICATE PROCESSING
            if ($transaction->status === 'processing' || $transaction->status === 'success') {
                Log::info('Transaction already processed, skipping', [
                    'invoice' => $transaction->invoice_number,
                    'current_status' => $transaction->status
                ]);
                return response()->json(['success' => true, 'message' => 'Already processed']);
            }
            
            // Update transaction status
            $status = $this->mapTripayStatus($data['status']);
            
            DB::table('transactions')->where('id', $transaction->id)->update([
                'status' => $status,
                'payment_status' => $data['status'],
                'paid_at' => $status === 'paid' ? now() : null,
                'updated_at' => now(),
            ]);
            
            // Send payment success email
            if ($status === 'paid' && $transaction->customer_email) {
                try {
                    $updatedTransaction = DB::table('transactions')->where('id', $transaction->id)->first();
                    $this->emailService->sendPaymentSuccess($updatedTransaction);
                    Log::info('Payment success email sent', ['invoice' => $transaction->invoice_number]);
                } catch (\Exception $e) {
                    Log::error('Failed to send payment success email', [
                        'invoice' => $transaction->invoice_number,
                        'error' => $e->getMessage()
                    ]);
                }
            }
            
            // ✅ FIX 2: USE QUEUE FOR ORDER PROCESSING
            if ($status === 'paid') {
                // Quick response to Tripay (< 1 second)
                DB::table('transactions')->where('id', $transaction->id)->update([
                    'status' => 'processing',
                    'updated_at' => now(),
                ]);
                
                // Dispatch to queue (async processing)
                ProcessOrderJob::dispatch($transaction->id)
                    ->delay(now()->addSeconds(2));  // Small delay to ensure DB committed
                
                Log::info('Order queued for processing', ['invoice' => $transaction->invoice_number]);
            }
            
            // Quick response to Tripay
            return response()->json(['success' => true]);
            
        } catch (\Exception $e) {
            Log::error('Tripay Callback Error', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            
            // Still return 200 to prevent Tripay retry
            return response()->json(['success' => false, 'message' => 'Internal error'], 200);
        }
    }
    
    private function mapTripayStatus($tripayStatus)
    {
        $statusMap = [
            'PAID' => 'paid',
            'UNPAID' => 'pending',
            'EXPIRED' => 'expired',
            'FAILED' => 'failed',
            'REFUND' => 'refunded',
        ];
        
        return $statusMap[$tripayStatus] ?? 'pending';
    }
    
    /**
     * Process order to VIP Reseller
     */
    private function processOrder($transaction)
    {
        try {
            // Update status to processing
            DB::table('transactions')->where('id', $transaction->id)->update([
                'status' => 'processing',
                'updated_at' => now(),
            ]);
            
            // Create order to VIP Reseller
            $result = $this->vipResellerService->createOrder(
                $transaction->product_code,
                $transaction->customer_data
            );
            
            if ($result['success']) {
                $data = $result['data'];
                
                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'),
                    'updated_at' => now(),
                ]);
                
                // 📧 EMAIL 3: Send "Order Complete" if success
                if (($data['status'] ?? '') === 'success' && $transaction->customer_email) {
                    try {
                        $updatedTransaction = DB::table('transactions')->where('id', $transaction->id)->first();
                        $this->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()
                        ]);
                    }
                }
            } else {
                DB::table('transactions')->where('id', $transaction->id)->update([
                    'status' => 'failed',
                    'provider_response' => json_encode($result),
                    'provider_note' => $result['message'],
                    'updated_at' => now(),
                ]);
            }
            
        } catch (\Exception $e) {
            Log::error('Process Order Error', [
                'invoice' => $transaction->invoice_number,
                'error' => $e->getMessage()
            ]);
            
            DB::table('transactions')->where('id', $transaction->id)->update([
                'status' => 'failed',
                'provider_note' => 'Processing error: ' . $e->getMessage(),
                'updated_at' => now(),
            ]);
        }
    }
    
    /**
     * 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';
    }
}