<?php

namespace App\Http\Controllers\Frontend;

use App;
use App\Http\Controllers\Controller;
use App\Http\Requests\Order\OrderCreateRequest;
use App\Models\Order;
use App\Models\Role;
use App\Models\User;
use App\Services\CartService;
use App\Services\OrderService;
use App\Services\PaymentGatewayManager;
use App\Services\SubscriptionService;
use Illuminate\Auth\Events\Registered;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Storage;
use Swift_TransportException;

class OrderController extends Controller
{
    protected OrderService $orderService;

    protected CartService $cartService;
    protected PaymentGatewayManager $gatewayManager;
    protected SubscriptionService $subscriptionService;

    public function __construct(
        OrderService   $orderService,
        CartService    $cartService,
        PaymentGatewayManager $gatewayManager,
        SubscriptionService $subscriptionService
    )
    {
        $this->orderService = $orderService;
        $this->gatewayManager = $gatewayManager;
        $this->cartService = $cartService;
        $this->subscriptionService = $subscriptionService;
    }

    public function validateCheckoutForm(OrderCreateRequest $request)
    {
        return response()->json(['success' => true]);
    }

    /**
     * @throws \Exception
     */
    public function submit(OrderCreateRequest $request)
    {
        ch_verify_recaptcha();

        if (Session::has('order_payment')) {
            Session::forget('order_payment');
            Session::save();
        }

        // TODO: move to service
        $validated = $request->validated();

        if (!auth()->check()) {
            $billingData = $validated['billing'];

            $user = User::create([
                'email' => data_get($billingData, 'email'),
                'first_name' => data_get($billingData, 'first_name'),
                'last_name' => data_get($billingData, 'last_name'),
                'password' => bcrypt(data_get($billingData, 'password')),
                'email_verified_at' => setting('email_verification', 'off') == 'off' ? now() : null,
            ]);

            $user->roles()->attach(Role::where('name', 'customer')->first());

            event(new Registered($user));

            Auth::login($user);

            unset($validated['billing']['password'], $validated['billing']['password_confirmation']);
        }


        $order = $this->orderService->create(
            $this->cartService,
            $validated,
            auth()->user()->getAuthIdentifier() ?? 0
        );

        // Process payment using the selected gateway
        return $this->gatewayManager->getGateway(\request('payment_method'))->processPayment($order);
    }

    public function completed(Request $request, $id)
    {
        $order = $this->orderService->getOrderByEncryptedId($id);

        $order_key = '';

        if (\session('order')) {
            $this->gatewayManager->getGateway($order->payment_method)->completePurchase($order);

            if ($order->status === getConstant('ORDER_STATUS_COMPLETED') && $order->order_type == getConstant('BILLING_SUBSCRIPTION')) {
                $subscription = $this->subscriptionService->find($order->subscription_id);
                $this->subscriptionService->activateSubscription($subscription);
            }

            $request->session()->forget('order');
            Session::save();
        }

        // Allow module listeners (fired inside activateSubscription) to override
        // the post-payment destination by writing to the 'redirect_after_order' session key.
        if ($request->session()->has('redirect_after_order')) {
            $destination = $request->session()->pull('redirect_after_order');
            return redirect($destination);
        }

        $pageHeader = [
            'title' => __('checkout.Order Completed'),
            'subtitle' => __('checkout.Thank you for your purchase'),
            'breadcrumbs' => [
                ['label' => __('general.Home'), 'url' => url('/')],
                ['label' => __('checkout.Order Complete')],
            ]
        ];

        if (isset($_GET['payment_success'])) {
            return view('theme::pages.checkout.thankyou', compact('order', 'pageHeader'));
        }

        return view('theme::pages.checkout.thankyou', compact('order', 'order_key', 'pageHeader'));
    }

    public function cancel(Request $request, $id)
    {
        if (session('order')) {
            $order = \Auth::user()->orders()->find($request->session()->get('order'));
            $order->update(['status' => getConstant('ORDER_STATUS_CANCELLED')]);;
            $request->session()->forget('order');
            Session::save();
            $pageHeader = [
                'title' => __('checkout.Payment Cancelled'),
                'subtitle' => __('checkout.Your payment was not completed'),
                'breadcrumbs' => [
                    ['label' => __('general.Home'), 'url' => url('/')],
                    ['label' => __('checkout.Payment Cancelled')],
                ]
            ];
            return view('theme::pages.checkout.cancel', compact('order', 'pageHeader'));
        } else {
            return redirect('/');
        }
    }

    public function failed(Request $request, $id)
    {
        if (session('order')) {
            $order = \Auth::user()->orders()->find($request->session()->get('order'));
            $request->session()->forget('order');
            Session::save();
            $failed = true;
            $pageHeader = [
                'title' => __('checkout.Payment Failed'),
                'subtitle' => __('checkout.Your payment could not be processed'),
                'breadcrumbs' => [
                    ['label' => __('general.Home'), 'url' => url('/')],
                    ['label' => __('checkout.Payment Failed')],
                ]
            ];
            return view('theme::pages.checkout.cancel', compact('order', 'failed', 'pageHeader'));
        } else {
            return redirect('/');
        }
    }

    public function payOrderSubmit(Request $request, $order_id)
    {
        ch_verify_recaptcha();

        $order = Order::where('user_id', \auth()->id())->where('id', $order_id)->whereIn('status', [
            getConstant('ORDER_STATUS_PENDING'),
            getConstant('ORDER_STATUS_FAILED'),
        ])->first();

        if (!$order) {
            abort(404, __('checkout.Order not found or already paid'));
        }

        Session::put('order', $order->id);
        Session::put('order_payment', true);
        Session::save();

        return $this->gatewayManager->getGateway(\request('payment_method'))->processPayment($order);
    }
    public function attachment($id)
    {
        if (! request()->hasValidSignature()) {
            abort(401);
        }

        $path = decrypt($id);

        if (!Storage::disk('local')->exists($path)) {
            abort(404);
        }

        return Storage::disk('local')->download($path);
    }

    public function getOrderSummary($order_id)
    {
        $order = Order::where('user_id', auth()->id())->where('id', $order_id)->firstOrFail();

        $cartItems = $order->items->map(function ($item) {
            return [
                'name' => $item->name,
                'price' => $item->price,
                'priceFormatted' => ch_format_price($item->price),
                'options' => [
                    'price_label' => ch_format_price($item->price),
                ]
            ];
        });

        return response()->json([
            'cartItems' => $cartItems,
            'discount' => $order->discount_amount > 0 ? ch_format_price($order->discount_amount) : null,
            'tax' => $order->tax > 0 ? ch_format_price($order->tax) : null,
            'subtotal' => ch_format_price($order->subtotal),
            'total' => ch_format_price($order->total),
        ]);
    }
}
