<?php

namespace App\Http\Controllers\Frontend;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Order;
use App\Models\Shipping;
use App\Models\Payment;
use App\Models\Customer;
use App\Models\DigitalDownload; 
use App\Services\FacebookCapiService;
use UddoktaPay\LaravelSDK\UddoktaPay;
use UddoktaPay\LaravelSDK\Requests\CheckoutRequest;
use UddoktaPay\LaravelSDK\Exceptions\UddoktaPayException;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Session;

class UddoktaPayController extends Controller
{
    protected $facebookCapiService;

    public function __construct(FacebookCapiService $facebookCapiService)
    {
        $this->facebookCapiService = $facebookCapiService;
    }
    /**
     * Redirect user to UddoktaPay checkout page
     */
    public function checkout(Request $request, $order_id = null)
    {
        $orderId = $order_id ?? $request->order_id;

        if(!$orderId){
            return redirect()->back()->with('error', 'Order ID missing for UddoktaPay.');
        }

        $order = Order::findOrFail($orderId);
        $shipping = Shipping::where('order_id', $order->id)->first();

        $fullName = $shipping->name ?? 'Customer';
        $email    = 'customer@example.com';

        if (Session::has('payable_amount') && Session::get('payable_amount') > 0) {
            $amount = (float) Session::get('payable_amount');
        } else {
            $amount = (float) $order->amount;
        }

        Log::info("UddoktaPay checkout for order {$order->id} with amount={$amount}");

        $uddoktapay = UddoktaPay::make(env('UDDOKTAPAY_API_KEY'), env('UDDOKTAPAY_API_URL'));

        try {
            $checkoutRequest = CheckoutRequest::make()
                ->setFullName($fullName)
                ->setEmail($email)
                ->setAmount($amount)
                ->addMetadata('order_id', $order->id)
                ->setRedirectUrl(route('uddoktapay.verify'))
                ->setCancelUrl(route('uddoktapay.cancel'))
                ->setWebhookUrl(route('uddoktapay.ipn'));

            $response = $uddoktapay->checkout($checkoutRequest);

            if ($response->failed()) {
                Log::error('UddoktaPay Checkout Failed: ' . $response->message());
                return redirect()->back()->with('error', 'Payment initiation failed.');
            }

            $order->payment_gateway = 'uddoktapay';
            $order->payment_status  = 'pending';
            $order->save();

            return redirect($response->paymentURL());

        } catch (UddoktaPayException $e) {
            Log::error('UddoktaPay Checkout Error: ' . $e->getMessage());
            return redirect()->back()->with('error', "Payment Error: " . $e->getMessage());
        }
    }

    /**
     * Payment verification after returning from UddoktaPay
     */
    public function verify(Request $request)
    {
        $uddoktapay = UddoktaPay::make(env('UDDOKTAPAY_API_KEY'), env('UDDOKTAPAY_API_URL'));

        try {
            $response = $uddoktapay->verify($request);
            $metadata = $response->metadata();

            $order_id = $metadata['order_id'] ?? null;
            $order    = Order::where('id', $order_id)->first();

            if (!$order) {
                return redirect()->route('customer.account')->with('error', 'Order not found.');
            }

            if ($response->success()) {
                $order->payment_status  = 'paid';
                $order->payment_gateway = 'uddoktapay';
                $order->save();

                $payment = Payment::where('order_id', $order->id)->first();
                if($payment){
                    $payment->payment_status = 'paid';
                    if (Session::has('payable_amount')) {
                        $payment->amount = Session::get('payable_amount');
                    } else {
                        $payment->amount = $order->amount; 
                    }
                    $payment->save();
                }

                $this->createDigitalDownloads($order);

                try {
                    $customer = Customer::find($order->customer_id);
                    $userData = [];
                    
                    if ($customer && $customer->email) {
                        $userData['email'] = $customer->email;
                    } elseif ($customer && $customer->phone) {
                        $userData['phone'] = $customer->phone;
                    }
                    
                    $shipping = Shipping::where('order_id', $order->id)->first();
                    if (empty($userData['phone']) && $shipping && $shipping->phone) {
                        $userData['phone'] = $shipping->phone;
                    }
                    
                    if (isset($_COOKIE['_fbp'])) {
                        $userData['fbp'] = $_COOKIE['_fbp'];
                    }
                    if (isset($_COOKIE['_fbc'])) {
                        $userData['fbc'] = $_COOKIE['_fbc'];
                    }
                    
                    register_shutdown_function(function () use ($order, $payment, $userData) {
                        try {
                            $orderDetails = $order->orderdetails ?? \App\Models\Order::with('orderdetails')->find($order->id)?->orderdetails ?? collect();
                            $contentIds  = $orderDetails->pluck('product_id')->map(fn($id) => (string)$id)->values()->toArray();
                            $contents    = $orderDetails->map(fn($i) => ['id' => (string)$i->product_id, 'quantity' => (int)$i->qty, 'item_price' => (float)$i->sale_price])->values()->toArray();
                            app(\App\Services\FacebookCapiService::class)->sendEvent('Purchase', [
                                'currency'     => 'BDT',
                                'value'        => $payment->amount ?? $order->amount,
                                'order_id'     => $order->invoice_id ?? $order->id,
                                'content_ids'  => $contentIds,
                                'contents'     => $contents,
                                'num_items'    => count($contents),
                                'content_type' => 'product',
                            ], $userData, [
                                'event_id'         => 'purchase_' . ($order->invoice_id ?? $order->id),
                                'event_source_url' => request()->fullUrl(),
                            ]);
                        } catch (\Exception $e) {
                            Log::error('Facebook CAPI Purchase event failed for order ' . $order->id . ': ' . $e->getMessage());
                        }
                    });
                } catch (\Exception $e) {
                    Log::error('Facebook CAPI setup failed for order ' . $order->id . ': ' . $e->getMessage());
                }

                Session::forget('payable_amount');

                return redirect()->route('customer.order_success', $order->id)
                                 ->with('success', 'Payment Successful! Your digital downloads are ready.');
            } else {
                $order->payment_status  = 'failed';
                $order->payment_gateway = 'uddoktapay';
                $order->save();

                return redirect()->route('customer.order_success', $order->id)
                                 ->with('error', 'Payment Failed!');
            }

        } catch (UddoktaPayException $e) {
            Log::error('UddoktaPay Verify Error: ' . $e->getMessage());
            return redirect()->route('customer.account')->with('error', "Verification Error: " . $e->getMessage());
        }
    }

    /**
     * If customer cancels payment
     */
    public function cancel()
    {
        return redirect()->route('customer.account')
                         ->with('error', 'Payment cancelled by user.');
    }

    /**
     * IPN (Instant Payment Notification)
     * Called automatically from UddoktaPay server after payment.
     */
    public function ipn(Request $request)
    {
        $uddoktapay = UddoktaPay::make(env('UDDOKTAPAY_API_KEY'), env('UDDOKTAPAY_API_URL'));
        $response   = $uddoktapay->ipn($request);

        if ($response->success()) {
            $metadata = $response->metadata();

            $order_id = $metadata['order_id'] ?? null;
            $order    = Order::where('id', $order_id)->first();

            if ($order && $order->payment_status != 'paid') {
                $order->payment_status  = 'paid';
                $order->payment_gateway = 'uddoktapay';
                $order->save();

                $payment = Payment::where('order_id', $order->id)->first();
                if($payment){
                    $payment->payment_status = 'paid';
                    $payment->save();
                }

                $this->createDigitalDownloads($order);

                Log::info("Order #{$order_id} marked as paid via IPN and digital downloads created.");
            }
        } else {
            Log::warning('UddoktaPay IPN Failed or Invalid');
        }
    }


    // =====================================
    // ⭐ DIGITAL DOWNLOAD CREATOR (HELPER)
    // =====================================
    private function createDigitalDownloads(Order $order)
    {
        // orderdetails + product রিলেশন লোড করি
        $order->loadMissing('orderdetails.product');

        foreach ($order->orderdetails as $item) {
            $product = $item->product;

            if ($product && $product->is_digital == 1 && $product->digital_file) {

                DigitalDownload::firstOrCreate(
                    [
                        'order_id'    => $order->id,
                        'product_id'  => $product->id,
                        'customer_id' => $order->customer_id,
                    ],
                    [
                        'token'               => Str::uuid(),
                        'file_path'           => $product->digital_file,
                        'remaining_downloads' => $product->download_limit ?? 5,
                        'expires_at'          => $product->download_expire_days
                                                    ? now()->addDays($product->download_expire_days)
                                                    : null,
                    ]
                );
            }
        }
    }
}
