<?php

namespace App\Http\Controllers;

use App\Models\User;
use App\Models\Order;
use App\CentralLogics\Helpers;
use App\Scopes\ZoneScope;
use Illuminate\Http\Request;
use App\Models\BusinessSetting;
use App\Library\Payer;
use App\Traits\Payment;
use App\Library\Receiver;
use App\Library\Payment as PaymentInfo;

class PaymentController extends Controller
{
    public function payment(Request $request)
    {
        session()->put('customer_id', $request['customer_id']);
        session()->put('payment_platform', $request['payment_platform']);
        session()->put('order_id', $request->order_id);

        if ($request->has('callback')) {
            session()->put('callback', $request['callback']);
        }

        $order = Order::withoutGlobalScope(ZoneScope::class)->where(['id' => $request->order_id, 'user_id' => $request['customer_id']])->first();
        if(!$order){
            return response()->json(['errors' => ['code' => 'order-payment', 'message' => 'Data not found']], 403);
        }
        if($order->is_guest){
            $customer_details = json_decode($order['delivery_address'],true);
        }else{
            $customer = User::find($request['customer_id']);
        }

        //guest user check
        if ($order->is_guest) {
            $address = json_decode($order['delivery_address'],true);
            $customer = collect([
                'first_name' => $address['contact_person_name'],
                'last_name' => '',
                'phone' => $address['contact_person_number'],
                'email' => $address['contact_person_email'],
            ]);

        } else {
            $customerModel = User::find($request['customer_id']);
            if (!$customerModel) {
                return response()->json(['errors' => ['message' => 'Customer not found']], 403);
            }
            $customer = collect([
                'first_name' => $customerModel['f_name'],
                'last_name' => $customerModel['l_name'],
                'phone' => $customerModel['phone'],
                'email' => $customerModel['email'],
            ]);
        }


        if (session()->has('payment_method') == false) {
            session()->put('payment_method', 'ssl_commerz_payment');
        }

        $paymentSummary = method_exists($order, 'paymentSplitSummary')
            ? $order->paymentSplitSummary()
            : $this->fallbackPaymentSplitSummary($order);
        $order_amount = round(
            (float) $paymentSummary['remaining_amount'],
            (int) config('round_up_to_digit', 2)
        );

        if (!isset($customer)) {
            return response()->json(['errors' => ['message' => 'Customer not found']], 403);
        }

        if ($order_amount <= 0) {
            return response()->json(['errors' => ['message' => 'This order has no remaining payment amount']], 403);
        }

        if (!$request->has('payment_method')) {
            return response()->json(['errors' => ['message' => 'Payment not found']], 403);
        }

        $activePaymentMethods = collect(Helpers::getActivePaymentGateways())
            ->pluck('gateway')
            ->filter();
        if (!$activePaymentMethods->contains($request->payment_method)) {
            return response()->json(['errors' => ['message' => 'Selected payment method is not available']], 403);
        }

        if (method_exists($order, 'payments')) {
            $pendingPayment = $order->payments()
                ->where('payment_status', 'unpaid')
                ->first();
            if ($pendingPayment) {
                $pendingPayment->amount = $order_amount;
                $pendingPayment->payment_method = $request->payment_method;
                $pendingPayment->save();
            }
        }

        $payer = new Payer($customer['first_name'].' '.$customer['last_name'], $customer['email'], $customer['phone'], '');

        $currency = BusinessSetting::where(['key'=>'currency'])->first()?->value ?? 'BDT';

        $store_logo= BusinessSetting::where(['key' => 'logo'])->first();
        $additional_data = [
            'business_name' => BusinessSetting::where(['key'=>'business_name'])->first()?->value,
            'business_logo' => \App\CentralLogics\Helpers::get_full_url('business',$store_logo?->value,$store_logo?->storage[0]?->value ?? 'public' )
        ];

        $payment_info = new PaymentInfo(
            success_hook: 'order_place',
            failure_hook: 'order_failed',
            currency_code: $currency,
            payment_method: $request->payment_method,
            payment_platform: $request['payment_platform'],
            payer_id: $request['customer_id'],
            receiver_id: '100',
            additional_data: $additional_data,
            payment_amount: $order_amount,
            external_redirect_link: $request->has('callback')?$request['callback']:session('callback'),
            attribute: 'order',
            attribute_id: $order->id
        );

        $receiver_info = new Receiver('receiver_name','example.png');

        $redirect_link = Payment::generate_link($payer, $payment_info, $receiver_info);

        return redirect($redirect_link);

    }

    public function success()
    {
        $callback = session('callback');
        if ($callback) {
            return redirect($this->callbackUrl($callback, ['status' => 'success']));
        }
        return response()->json(['message' => 'Payment succeeded'], 200);
    }

    public function fail()
    {
        $callback = session('callback');
        if ($callback) {
            return redirect($this->callbackUrl($callback, ['status' => 'fail']));
        }
        return response()->json(['message' => 'Payment failed'], 403);
    }

    public function cancel(Request $request)
    {
        $callback = session('callback');
        if ($callback) {
            return redirect($this->callbackUrl($callback, ['status' => 'fail']));
        }
        return response()->json(['message' => 'Payment failed'], 403);
    }

    private function callbackUrl(string $url, array $parameters): string
    {
        $separator = str_contains($url, '?') ? '&' : '?';

        return $url . $separator . http_build_query($parameters);
    }

    private function fallbackPaymentSplitSummary(Order $order): array
    {
        $totalAmount = max((float) ($order->order_amount ?? 0), 0);
        $walletAmount = max((float) ($order->partially_paid_amount ?? 0), 0);

        if (($order->payment_method ?? null) === 'wallet') {
            $walletAmount = $totalAmount;
        }

        try {
            if (method_exists($order, 'payments')) {
                $walletAmount = max(
                    $walletAmount,
                    (float) $order->payments()->where('payment_method', 'wallet')->sum('amount')
                );
            }
        } catch (\Throwable) {
            // Legacy installs may not have the split-payment relation yet.
        }

        $walletAmount = min($walletAmount, $totalAmount);

        return [
            'wallet_amount' => $walletAmount,
            'remaining_amount' => max($totalAmount - $walletAmount, 0),
            'selected_payment_method' => $order->payment_method,
            'total_amount' => $totalAmount,
        ];
    }

}
