<?php

namespace App\Http\Controllers;

use App\Models\Product;
use App\Models\Transaction;
use App\Services\TripayService;
use Illuminate\Support\Facades\Mail;
use App\Services\OrderService;
use App\Services\VipResellerService;
use App\Mail\OrderComplete;
use Illuminate\Support\Facades\Log; 
use App\Services\EmailNotificationService;
use Illuminate\Http\Request;
use Illuminate\Support\Str;

class TransactionController extends Controller
{
    private $tripayService;
    private $vipResellerService;
    private $emailService;

    public function __construct(
        TripayService $tripayService,
        VipResellerService $vipResellerService,
        EmailNotificationService $emailService
    ) {
        $this->tripayService = $tripayService;
        $this->vipResellerService = $vipResellerService;
        $this->emailService = $emailService;
    }

    /**
     * Get payment methods with fees
     */
   public function getPaymentMethods(Request $request)
{
    $productId = $request->input('product_id');
    $product = Product::findOrFail($productId);

    // Calculate product price with margin
    $basePrice = $product->base_price;
    $marginPercentage = $product->margin_percentage ?? 10;
    $marginAmount = $basePrice * ($marginPercentage / 100);
    $productPrice = $basePrice + $marginAmount;

    // Get available channels from Tripay
    $channelsResult = $this->tripayService->getPaymentChannels();
    
    if (!$channelsResult['success']) {
        return response()->json([
            'success' => false,
            'message' => 'Failed to get payment methods',
        ], 500);
    }

    // ⭐ FIX: Calculate fee based on actual product price (not inflated)
    $channels = collect($channelsResult['data'])->map(function ($channel) use ($productPrice) {
        // Fee should be calculated on ACTUAL product price
        $fee = $this->tripayService->calculateFee($channel['code'], $productPrice);
        $totalAmount = $productPrice + $fee;

        return [
            'code' => $channel['code'],
            'name' => $channel['name'],
            'group' => $channel['group'],
            'icon_url' => $channel['icon_url'] ?? null,
            'fee_flat' => $fee,  // ⭐ ADD THIS
            'fee' => $fee,
            'total_amount' => $totalAmount,
            'active' => $channel['active'] ?? true,
        ];
    })->filter(function ($channel) {
        return $channel['active'];
    })->groupBy('group')->toArray();

    return response()->json([
        'success' => true,
        'data' => [
            'product_price' => $productPrice,
            'channels' => $channels,
        ],
    ]);
}

    /**
     * Create new transaction
     */
    // ⭐ REPLACE THE create() METHOD IN TransactionController WITH THIS:

public function create(Request $request)
{
    $request->validate([
        'product_id' => 'required|exists:products,id',
        'customer_data' => 'required|string',
        'customer_phone' => 'nullable|string',
        'customer_email' => 'nullable|email',
        'customer_name' => 'nullable|string',
        'payment_method' => 'required|string',
        'voucher_code' => 'nullable|string',
    ]);

    try {
        $product = Product::findOrFail($request->product_id);

        // Calculate pricing with margin
        $basePrice = $product->base_price;
        $marginPercentage = $product->margin_percentage ?? 10;
        $marginAmount = $basePrice * ($marginPercentage / 100);
        $productPrice = $basePrice + $marginAmount;

        // VOUCHER VALIDATION
        $voucherCode = strtoupper($request->input('voucher_code', ''));
        $voucherId = null;
        $discountAmount = 0;
        
        if ($voucherCode) {
            $voucher = \App\Models\Voucher::where('code', $voucherCode)
                ->where('is_active', true)
                ->first();
            
            if ($voucher) {
                $validation = $voucher->validate($productPrice, $request->customer_email);
                
                if ($validation['valid']) {
                    $discountAmount = $voucher->calculateDiscount($productPrice);
                    $voucherId = $voucher->id;
                }
            }
        }

        // Calculate final price after discount
        $priceAfterDiscount = $productPrice - $discountAmount;

        // Calculate payment fee on discounted price
        $paymentMethod = $request->payment_method;
        $paymentFee = $this->tripayService->calculateFee($paymentMethod, $priceAfterDiscount);
        
        // ⭐ FORCE INTEGER
        $totalAmount = (int) ($priceAfterDiscount + $paymentFee);
        $priceAfterDiscount = (int) $priceAfterDiscount;
        $paymentFee = (int) $paymentFee;

        // Generate invoice number & merchant ref
        $invoiceNumber = 'INV-' . date('Ymd') . '-' . strtoupper(Str::random(8));
        $merchantRef = 'TRX-' . time() . '-' . strtoupper(Str::random(6));

        // Create transaction
        $transaction = Transaction::create([
            'invoice_number' => $invoiceNumber,
            'merchant_ref' => $merchantRef,
            'customer_email' => $request->customer_email,
            'customer_phone' => $request->customer_phone,
            'customer_name' => $request->customer_name ?? 'Customer',
            'product_id' => $product->id,
            'product_name' => $product->name,
            'product_code' => $product->sku,
            'customer_data' => $request->customer_data,
            'base_price' => $basePrice,
            'margin_amount' => $marginAmount,
            'product_price' => $productPrice,
            'payment_fee' => $paymentFee,
            'total_amount' => $totalAmount,
            'payment_method' => $paymentMethod,
            'status' => 'pending',
            'payment_status' => 'UNPAID',
            'expired_at' => now()->addHours(24),
            'voucher_id' => $voucherId,
            'voucher_code' => $voucherCode ?: null,
            'original_price' => $productPrice,
            'discount_amount' => $discountAmount,
        ]);

        // ⭐ LOG BEFORE TRIPAY
        \Log::info('Creating Tripay Transaction', [
            'merchant_ref' => $merchantRef,
            'total_amount' => $totalAmount,
            'payment_method' => $paymentMethod,
            'price_after_discount' => $priceAfterDiscount,
            'payment_fee' => $paymentFee,
        ]);

        // Create Tripay payment
        $tripayResult = $this->tripayService->createTransaction([
            'method' => $paymentMethod,
            'merchant_ref' => $merchantRef,
            'amount' => $totalAmount,
            'customer_name' => $transaction->customer_name,
            'customer_email' => $transaction->customer_email,
            'customer_phone' => $transaction->customer_phone ?? '081234567890',
            'order_items' => [
                [
                    'sku' => $product->sku,
                    'name' => $product->name,
                    'price' => $priceAfterDiscount,
                    'quantity' => 1,
                ],
                [
                    'sku' => 'FEE',
                    'name' => 'Biaya Payment Gateway',
                    'price' => $paymentFee,
                    'quantity' => 1,
                ],
            ],
            'return_url' => route('transactions.payment', $invoiceNumber),
        ]);

        // ⭐ LOG TRIPAY RESPONSE
        \Log::info('Tripay Create Response', $tripayResult);

        if (!$tripayResult['success']) {
            $transaction->delete();
            return response()->json([
                'success' => false,
                'message' => 'Failed to create payment: ' . ($tripayResult['message'] ?? 'Unknown error'),
            ], 500);
        }

        $tripayData = $tripayResult['data'];

        // Update transaction with Tripay data
        $transaction->update([
            'reference' => $tripayData['reference'],
            'payment_name' => $tripayData['payment_name'] ?? $paymentMethod,
            'checkout_url' => $tripayData['checkout_url'] ?? null,
            'payment_instructions' => $tripayData['instructions'] ?? null,
            'expired_at' => $tripayData['expired_time'] ? date('Y-m-d H:i:s', $tripayData['expired_time']) : now()->addHours(24),
        ]);

        // EMAIL
        if ($transaction->customer_email) {
            try {
                $this->emailService->sendOrderCreated($transaction->fresh());
            } catch (\Exception $e) {
                \Log::error('Failed to send order created email: ' . $e->getMessage());
            }
        }

        return response()->json([
            'success' => true,
            'message' => 'Transaction created successfully',
            'data' => [
                'invoice_number' => $transaction->invoice_number,
                'reference' => $transaction->reference,
                'total_amount' => $transaction->total_amount,
                'discount_amount' => $discountAmount,
                'checkout_url' => $transaction->checkout_url,
            ],
        ]);

    } catch (\Exception $e) {
        \Log::error('Transaction Create Error', [
            'error' => $e->getMessage(),
            'trace' => $e->getTraceAsString(),
        ]);
        
        return response()->json([
            'success' => false,
            'message' => 'Failed to create transaction: ' . $e->getMessage(),
        ], 500);
    }
}
 public function tripayCallback(Request $request)
{
    $json = $request->getContent();
    $signature = $request->header('X-Callback-Signature');

    // Verify signature
    if (!$this->tripayService->verifyCallbackSignature($json, $signature)) {
        return response()->json(['message' => 'Invalid signature'], 403);
    }

    $data = json_decode($json, true);

    // Get transaction with lock
    $transaction = Transaction::where('merchant_ref', $data['merchant_ref'])
        ->lockForUpdate() // ✅ LOCK ROW
        ->first();

    if (!$transaction) {
        return response()->json(['message' => 'Transaction not found'], 404);
    }

    // ✅ IDEMPOTENCY CHECK: Skip if already paid
    if ($transaction->payment_status === 'PAID') {
        Log::info('Duplicate callback ignored', [
            'merchant_ref' => $data['merchant_ref'],
            'reference' => $data['reference'] ?? null,
        ]);
        
        return response()->json(['message' => 'Already processed'], 200);
    }

    $status = $data['status'];

    if ($status === 'PAID') {
        $transaction->update([
            'payment_status' => 'PAID',
            'paid_at' => now(),
            'status' => 'paid',
        ]);

        // Apply voucher
        if ($transaction->voucher_id && $transaction->discount_amount > 0) {
            try {
                $voucher = \App\Models\Voucher::find($transaction->voucher_id);
                if ($voucher) {
                    $voucher->apply(
                        $transaction->invoice_number,
                        $transaction->customer_email ?? 'guest',
                        $transaction->discount_amount
                    );
                }
            } catch (\Exception $e) {
                Log::error('Failed to apply voucher: ' . $e->getMessage());
            }
        }

        // Send payment success email
        if ($transaction->customer_email) {
            try {
                $this->emailService->sendPaymentSuccess($transaction->fresh());
            } catch (\Exception $e) {
                Log::error('Failed to send payment success email: ' . $e->getMessage());
            }
        }

        // ✅ Process order ONCE
        $orderService = app(OrderService::class);
        $result = $orderService->processOrder($transaction);
        
        Log::info('Order processing result', [
            'transaction_id' => $transaction->id,
            'result' => $result,
        ]);

    } elseif (in_array($status, ['EXPIRED', 'FAILED'])) {
        $transaction->update([
            'payment_status' => $status,
            'status' => $status === 'EXPIRED' ? 'expired' : 'failed',
        ]);
    }

    return response()->json(['message' => 'OK']);
}
/**
 * Check transaction status
 */
    public function checkStatus($invoiceNumber)
    {
        try {
            $transaction = Transaction::where('invoice_number', $invoiceNumber)->firstOrFail();

            // ✅ If paid but still processing, check VIP Reseller status
            if ($transaction->payment_status === 'PAID' && $transaction->trx_id && 
                in_array($transaction->status, ['paid', 'processing'])) {
                
                $result = $this->vipResellerService->checkOrderStatus($transaction->trx_id);

                if ($result['success'] && isset($result['data'])) {
                    $data = $result['data'];

                    $transaction->update([
                        'provider_status' => $data['status'] ?? null,
                        'provider_note' => $data['note'] ?? null,
                        'provider_sn' => $data['sn'] ?? null,
                        'status' => $this->mapProviderStatus($data['status'] ?? 'waiting'),
                    ]);
                }
            }
            
            // ✅ If payment still unpaid, check Tripay status
            if ($transaction->payment_status === 'UNPAID' && $transaction->reference) {
                // TODO: Add Tripay status check via API
                // $tripayStatus = $this->tripayService->checkTransactionStatus($transaction->reference);
            }

            return response()->json([
                'success' => true,
                'data' => [
                    'invoice_number' => $transaction->invoice_number,
                    'payment_status' => $transaction->payment_status,
                    'status' => $transaction->status,
                    'provider_sn' => $transaction->provider_sn,
                    'paid_at' => $transaction->paid_at,
                    'completed_at' => $transaction->completed_at,
                ],
            ]);

        } catch (\Exception $e) {
            Log::error('Check Status Error', [
                'invoice' => $invoiceNumber,
                'error' => $e->getMessage(),
            ]);
            
            return response()->json([
                'success' => false,
                'message' => 'Failed to check status: ' . $e->getMessage(),
            ], 500);
        }
    }

    /**
     * Payment page
     */
    public function paymentPage($invoiceNumber)
    {
        $transaction = Transaction::where('invoice_number', $invoiceNumber)
            ->with(['product', 'product.category'])
            ->with('product')
            ->firstOrFail();

        return view('payment.index', compact('transaction'));
    }

    /**
     * Map VIP Reseller status to our status
     */
    private function mapProviderStatus($providerStatus)
    {
        $statusMap = [
            'waiting' => 'processing',
            'process' => 'processing',
            'success' => 'success',
            'failed' => 'failed',
            'error' => 'failed',
        ];

        return $statusMap[$providerStatus] ?? 'processing';
    }
}