<?php

namespace App\Services;

use App\Models\Booking;
use App\Models\Table;
use App\Models\User;
use Midtrans\Config;
use Midtrans\Snap;
use Illuminate\Support\Facades\Log;

class MidtransService
{
    public function __construct()
    {
        $serverKey = config('midtrans.server_key');
        $clientKey = config('midtrans.client_key');
        $merchantId = config('midtrans.merchant_id');
        $isProduction = config('midtrans.is_production', false);

        // Log semua konfigurasi untuk debugging
        Log::info('Midtrans Configuration:', [
            'server_key' => $serverKey,
            'client_key' => $clientKey,
            'merchant_id' => $merchantId,
            'is_production' => $isProduction
        ]);

        if (empty($serverKey)) {
            throw new \Exception('Midtrans server key is not configured');
        }

        Config::$serverKey = $serverKey;
        Config::$isProduction = $isProduction;
        Config::$isSanitized = true;
        Config::$is3ds = true;

        // Log konfigurasi yang digunakan oleh Midtrans
        Log::info('Midtrans Config:', [
            'server_key' => Config::$serverKey,
            'is_production' => Config::$isProduction,
            'is_sanitized' => Config::$isSanitized,
            'is_3ds' => Config::$is3ds
        ]);
    }

    // Method baru untuk membuat transaksi sementara tanpa booking record
    public function createTemporaryTransaction(Table $table, int $amount, string $orderId, User $user)
    {
        try {
            if ($amount <= 0) {
                throw new \Exception('Invalid booking amount');
            }

            $params = [
                'transaction_details' => [
                    'order_id' => $orderId,
                    'gross_amount' => (int) $amount,
                ],
                'customer_details' => [
                    'first_name' => $user->name,
                    'email' => $user->email,
                ],
                'item_details' => [
                    [
                        'id' => $table->id,
                        'price' => (int) $amount,
                        'quantity' => 1,
                        'name' => 'Booking Meja ' . $table->name,
                    ],
                ],
                'expiry' => [
                    'start_time' => now()->format('Y-m-d H:i:s O'),
                    'unit' => 'hour',
                    'duration' => 24,
                ],
            ];

            Log::info('Creating Midtrans temporary transaction:', [
                'order_id' => $orderId,
                'amount' => $amount,
                'params' => $params
            ]);

            $snapToken = Snap::getSnapToken($params);
            
            if (empty($snapToken)) {
                throw new \Exception('Empty snap token received from Midtrans');
            }

            Log::info('Midtrans temporary transaction created successfully:', [
                'order_id' => $orderId,
                'snap_token' => $snapToken
            ]);

            return $snapToken;
        } catch (\Exception $e) {
            Log::error('Midtrans temporary transaction failed:', [
                'order_id' => $orderId,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            throw new \Exception('Failed to create Midtrans transaction: ' . $e->getMessage());
        }
    }

    // Metode original untuk backward compatibility
    public function createTransaction(Booking $booking)
    {
        try {
            if (!$booking->user) {
                throw new \Exception('User not found for booking');
            }

            if (empty($booking->total_amount) || $booking->total_amount <= 0) {
                throw new \Exception('Invalid booking amount');
            }

            $params = [
                'transaction_details' => [
                    'order_id' => 'BOOK-' . $booking->id,
                    'gross_amount' => (int) $booking->total_amount,
                ],
                'customer_details' => [
                    'first_name' => $booking->user->name,
                    'email' => $booking->user->email,
                ],
                'item_details' => [
                    [
                        'id' => $booking->table_id,
                        'price' => (int) $booking->total_amount,
                        'quantity' => 1,
                        'name' => 'Booking Meja ' . $booking->table->name,
                    ],
                ],
                'expiry' => [
                    'start_time' => now()->format('Y-m-d H:i:s O'),
                    'unit' => 'hour',
                    'duration' => 24,
                ],
            ];

            Log::info('Creating Midtrans transaction:', [
                'booking_id' => $booking->id,
                'amount' => $booking->total_amount,
                'params' => $params
            ]);

            $snapToken = Snap::getSnapToken($params);
            
            if (empty($snapToken)) {
                throw new \Exception('Empty snap token received from Midtrans');
            }

            Log::info('Midtrans transaction created successfully:', [
                'booking_id' => $booking->id,
                'snap_token' => $snapToken
            ]);

            return $snapToken;
        } catch (\Exception $e) {
            Log::error('Midtrans transaction failed:', [
                'booking_id' => $booking->id,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            throw new \Exception('Failed to create Midtrans transaction: ' . $e->getMessage());
        }
    }

    public function handleNotification($notification)
    {
        try {
            $transaction = $notification->transaction_status;
            $type = $notification->payment_type;
            $orderId = $notification->order_id;
            $fraud = $notification->fraud_status;

            Log::info('Received Midtrans notification:', [
                'transaction_status' => $transaction,
                'payment_type' => $type,
                'order_id' => $orderId,
                'fraud_status' => $fraud
            ]);

            // Check if this is a temporary order
            if (strpos($orderId, 'TEMP-') === 0) {
                Log::info('Notification for temporary order received, will be handled separately', [
                    'order_id' => $orderId
                ]);
                return null;
            }

            // Handle existing bookings
            // Extract booking ID from order ID (format: BOOK-{id})
            $bookingId = explode('-', $orderId)[1];
            $booking = Booking::findOrFail($bookingId);

            if ($transaction == 'capture') {
                if ($type == 'credit_card') {
                    if ($fraud == 'challenge') {
                        $booking->status = 'pending';
                    } else {
                        $booking->status = 'paid';
                    }
                }
            } else if ($transaction == 'settlement') {
                $booking->status = 'paid';
            } else if ($transaction == 'pending') {
                $booking->status = 'pending';
            } else if ($transaction == 'deny') {
                $booking->status = 'cancelled';
            } else if ($transaction == 'expire') {
                $booking->status = 'expired';
            } else if ($transaction == 'cancel') {
                $booking->status = 'cancelled';
            }

            $booking->payment_id = $notification->transaction_id;
            $booking->payment_method = $type;
            $booking->save();

            Log::info('Booking status updated:', [
                'booking_id' => $booking->id,
                'new_status' => $booking->status
            ]);

            return $booking;
        } catch (\Exception $e) {
            Log::error('Failed to handle Midtrans notification:', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            throw $e;
        }
    }
}