<?php

namespace App\Http\Controllers;

use App\Models\Discount;
use App\Models\DiscountType;
use App\Models\Package;
use Closure;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

class CheckoutController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth');
    }

    protected function _calcWithDiscount($priceOfOrder, $discountType = DiscountType::PRICE, $discountValue = 0): array
    {
        $priceOfOrder = (float) $priceOfOrder;
        $totalPrice = 0;
        $discountOfOrder = 0;

        if ($discountType == DiscountType::PRICE) {
            $discount = (float) $discountValue;
            $discountOfOrder = $discount;
            $totalPrice = ($priceOfOrder - $discount);
            if ($totalPrice <= 0) {
                $totalPrice = 0;
            }
        }

        if ($discountType == DiscountType::PERCENT) {
            $discount = (int) $discountValue;
            $discountOfOrder = ($discount / 100) * $priceOfOrder;
            $totalPrice = ($priceOfOrder - $discountOfOrder);
        }

        return [
            'total_price' => (float) number_format($totalPrice, 2, '.', ''),
            'discount_value' => (float) number_format($discountOfOrder, 2, '.', ''),
        ];
    }

    /**
     * request {
     *      package_id
     *      discount_code
     * }
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function calcTotalByAjax(Request $request): JsonResponse
    {
        $status = false;

        $package = Package::getByCache()
            ->where('id', $request->get('package_id'))
            ->first();

        $discount = Discount::getByCache()
            ->whereNull('date_used')
            ->where('code', $request->get('discount_code'))
            ->first();

        if (!$package) {
            return response()->json([
                'status' => $status,
                'message' => 'Package not exist, please contact with admin to check this package.'
            ], 422);
        }

        // NOTE: Has discount
        if ($package && $discount) {
            $calcOrder = $this->_calcWithDiscount(
                priceOfOrder: $package->price,
                discountValue: $discount->value,
                discountType: $discount->discount_type_id
            );

            return response()->json([
                'data' => [
                    'price' => $package->price,
                    'discount' => $discount->discount_type_id == DiscountType::PERCENT
                        ? $discount->value . DiscountType::getUnit($discount)
                        : DiscountType::getUnit($discount) . $discount->value,
                    'total_price' => $calcOrder['total_price'],
                    'discount_value' => $calcOrder['discount_value'],
                ],
                'message' => 'Successful calculation with your current discount is.',
                'status' => true,
            ]);
        }

        // NOTE: Without discount
        if ($package && !$discount) {
            return response()->json([
                'data' => [
                    'total_price' => $package->price,
                    'discount_value' => 0
                ],
                'message' => 'Successful calculation without your current discount is.',
                'status' => true,
            ]);
        }

        return response()->json([
            'status' => false,
            'message' => "It seems you were missing something"
        ]);
    }

    public function package($id, Request $request)
    {
        $request->merge([
            'package_id' => $request->route('id')
        ]);

        $this->validate($request, [
            'package_id' => [
                'required',
                function (string $attribute, mixed $value, Closure $fail) use ($id) {
                    $package = Package::firstActiveById($id);
                    if (!$package) {
                        $fail('Package not exist!');
                    }
                }
            ]
        ]);

        $package = Package::getByCache()->find(
            $request->get('package_id')
        );

        return view('client.pages.checkout', [
            'package' => $package,
        ]);
    }

    /**
     * Payment submit
     *
     * @param Request $request
     * @return \Illuminate\Routing\Redirector|\Illuminate\Http\RedirectResponse
     */
    public function payment(Request $request, $packageId)
    {
        // HACK fix security check value discount input
        $discountCode = $request->get('discount_code');
        $package = Package::find($packageId);
        $discount = Discount::firstActiveByCode($discountCode);

        if ($discount) {
            $discount->status = 0;
            $discount->save();
        } else if ($discountCode){
            return redirect()->back()->withErrors([
                'Discount code was used, please contact with admin to check this discount.'
            ]);
        }

        if (module_exist('Paypal')) {
            if ($discount) {
                $order = $this->_calcWithDiscount(
                    priceOfOrder: $package->price,
                    discountValue: $discount->value,
                    discountType: $discount->discount_type_id
                );
            } else {
                $order = $this->_calcWithDiscount(
                    priceOfOrder: $package->price,
                    discountValue: 0,
                );
            }
            $request->merge([
                ...$order,
                'discount_code' => $discount?->code,
                'package_id' => $packageId,
                'user_id' => auth()->user()->id
            ]);
            $action = Route::getRoutes()->getByName('payment.create')->getAction();
            return app()->call($action['controller'], [$request]);
        } else {
            return redirect()->back()->withErrors([
                'Sorry, module "Paypal" not exist. Please check again!'
            ]);
        }
    }

    public function checkDiscountByAjax(Request $request): JsonResponse
    {
        $this->validate($request, [
            'code' => 'required|max:10'
        ]);

        $discount = Discount::firstActiveByCode($request->get('code'));

        if ($discount) {
            return response()->json([
                'status' => true,
                'message' => 'Congratulations, you have successfully entered the discount code',
                'data' => [
                    'value' => (float) $discount->value,
                    'unit' => DiscountType::getUnit($discount),
                    'discount_type' => $discount->discount_type_id,
                    'code' => $request->get('code')
                ]
            ]);
        } else {
            return response()->json([
                'status' => false,
                'message' => 'Discount code not exist, please contact with admin to check this discount.'
            ], 422);
        }
    }
}
