<?php

namespace App\Http\Controllers\Api\V1;

use App\Models\Cart;
use App\Models\Item;
use Illuminate\Http\Request;
use App\CentralLogics\Helpers;
use App\Http\Controllers\Controller;
use App\Models\ItemCampaign;
use App\Services\DeliveryChargeService;
use Illuminate\Support\Facades\Validator;

class CartController extends Controller
{
    private function normalizeCartPayload($carts)
    {
        return $carts->map(function ($data) {
            $data->add_on_ids = Helpers::normalizeNestedJsonArray($data->add_on_ids);
            $data->add_on_qtys = Helpers::normalizeNestedJsonArray($data->add_on_qtys);
            $data->variation = Helpers::normalizeNestedJsonArray($data->variation);
            $data->item = Helpers::cart_product_data_formatting($data->item, $data->variation, $data->add_on_ids,
                $data->add_on_qtys, false, app()->getLocale());
            return $data;
        });
    }

    private function cartResponse($carts)
    {
        $carts = $this->normalizeCartPayload($carts);
        $deliveryChargeService = app(DeliveryChargeService::class);
        $settings = $deliveryChargeService->settings();
        $calculatedDeliveryCharge = $deliveryChargeService->calculateItemWise($carts);
        $limitedDeliveryCharge = $deliveryChargeService->applyMaximumLimit($calculatedDeliveryCharge, $settings);
        $maximumLimitApplied = $limitedDeliveryCharge < $calculatedDeliveryCharge;

        $carts->each(function ($cart) use ($calculatedDeliveryCharge, $limitedDeliveryCharge, $maximumLimitApplied, $settings) {
            $cart->setAttribute('calculated_delivery_charge', $calculatedDeliveryCharge);
            $cart->setAttribute('limited_delivery_charge', $limitedDeliveryCharge);
            $cart->setAttribute('maximum_delivery_charge_limit_applied', $maximumLimitApplied);
            $cart->setAttribute('maximum_delivery_charge_limit', (float) ($settings['maximum_delivery_charge_limit'] ?? 0));
        });

        return response()->json($carts, 200);
    }

    public function get_carts(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'guest_id' => $request->user ? 'nullable' : 'required',
        ]);

        if ($validator->fails()) {
            return response()->json(['errors' => Helpers::error_processor($validator)], 403);
        }
        $user_id = $request->user ? $request->user->id : $request['guest_id'];
        $is_guest = $request->user ? 0 : 1;
        return $this->cartResponse(
            Cart::where('user_id', $user_id)->where('is_guest',$is_guest)->where('module_id',getModuleId($request->header('moduleId')))->get()
        );
    }

    public function add_to_cart(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'guest_id' => $request->user ? 'nullable' : 'required',
            'item_id' => 'required|integer',
            'model' => 'required|string|in:Item,ItemCampaign',
            'price' => 'required|numeric',
            'quantity' => 'required|integer|min:1',
        ]);

        if ($validator->fails()) {
            return response()->json(['errors' => Helpers::error_processor($validator)], 403);
        }

        $user_id = $request->user ? $request->user->id : $request['guest_id'];
        $is_guest = $request->user ? 0 : 1;
        $model = $request->model === 'Item' ? 'App\Models\Item' : 'App\Models\ItemCampaign';
        $item = $request->model === 'Item' ? Item::find($request->item_id) : ItemCampaign::find($request->item_id);
        $addOnIds = Helpers::normalizeNestedJsonArray($request->input('add_on_ids', []));
        $addOnQtys = Helpers::normalizeNestedJsonArray($request->input('add_on_qtys', []));
        $variation = Helpers::normalizeNestedJsonArray($request->input('variation', []));


        $cart = Cart::where('item_id',$request->item_id)->where('item_type',$model)->where('user_id', $user_id)->where('is_guest',$is_guest)->where('module_id',getModuleId($request->header('moduleId')))->first();

        if ($cart && Helpers::normalizeNestedJsonArray($cart->variation) == $variation) {

            return response()->json([
                'errors' => [
                    ['code' => 'cart_item', 'message' => translate('messages.Item_already_exists')]
                ]
            ], 403);
        }

        if($item->maximum_cart_quantity && ($request->quantity>$item->maximum_cart_quantity)){
            return response()->json([
                'errors' => [
                    ['code' => 'cart_item_limit', 'message' => translate('messages.maximum_cart_quantity_exceeded')]
                ]
            ], 403);
        }

        $cart = new Cart();
        $cart->user_id = $user_id;
        $cart->module_id = getModuleId($request->header('moduleId'));
        $cart->item_id = $request->item_id;
        $cart->is_guest = $is_guest;
        $cart->add_on_ids = json_encode($addOnIds);
        $cart->add_on_qtys = json_encode($addOnQtys);
        $cart->item_type = $request->model;
        $cart->price = $request->price;
        $cart->quantity = $request->quantity;
        $cart->variation = json_encode($variation);
        $cart->save();

        $item->carts()->save($cart);

        return $this->cartResponse(
            Cart::where('user_id', $user_id)->where('is_guest',$is_guest)->where('module_id',getModuleId($request->header('moduleId')))->get()
        );
    }

    public function update_cart(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'cart_id' => 'required',
            'guest_id' => $request->user ? 'nullable' : 'required',
            'price' => 'required|numeric',
            'quantity' => 'required|integer|min:1',
        ]);

        if ($validator->fails()) {
            return response()->json(['errors' => Helpers::error_processor($validator)], 403);
        }

        $user_id = $request->user ? $request->user->id : $request['guest_id'];
        $is_guest = $request->user ? 0 : 1;
        $cart = Cart::find($request->cart_id);
        $item = $cart->item_type === 'App\Models\Item' ? Item::find($cart->item_id) : ItemCampaign::find($cart->item_id);
        $addOnIds = $request->has('add_on_ids')
            ? Helpers::normalizeNestedJsonArray($request->input('add_on_ids', []))
            : Helpers::normalizeNestedJsonArray($cart->add_on_ids);
        $addOnQtys = $request->has('add_on_qtys')
            ? Helpers::normalizeNestedJsonArray($request->input('add_on_qtys', []))
            : Helpers::normalizeNestedJsonArray($cart->add_on_qtys);
        $variation = $request->has('variation')
            ? Helpers::normalizeNestedJsonArray($request->input('variation', []))
            : Helpers::normalizeNestedJsonArray($cart->variation);
        if($item->maximum_cart_quantity && ($request->quantity>$item->maximum_cart_quantity)){
            return response()->json([
                'errors' => [
                    ['code' => 'cart_item_limit', 'message' => translate('messages.maximum_cart_quantity_exceeded')]
                ]
            ], 403);
        }

        $cart->user_id = $user_id;
        $cart->module_id = getModuleId($request->header('moduleId'));
        $cart->is_guest = $is_guest;
        $cart->add_on_ids = json_encode($addOnIds);
        $cart->add_on_qtys = json_encode($addOnQtys);
        $cart->price = $request->price;
        $cart->quantity = $request->quantity;
        $cart->variation = json_encode($variation);
        $cart->save();

        return $this->cartResponse(
            Cart::where('user_id', $user_id)->where('is_guest',$is_guest)->where('module_id',getModuleId($request->header('moduleId')))->get()
        );
    }

    public function remove_cart_item(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'cart_id' => 'required',
            'guest_id' => $request->user ? 'nullable' : 'required',
        ]);

        if ($validator->fails()) {
            return response()->json(['errors' => Helpers::error_processor($validator)], 403);
        }

        $user_id = $request->user ? $request->user->id : $request['guest_id'];
        $is_guest = $request->user ? 0 : 1;

        $cart = Cart::find($request->cart_id);
        $cart?->delete();

        return $this->cartResponse(
            Cart::where('user_id', $user_id)->where('is_guest',$is_guest)->where('module_id',getModuleId($request->header('moduleId')))->get()
        );
    }

    public function remove_cart(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'guest_id' => $request->user ? 'nullable' : 'required',
        ]);

        if ($validator->fails()) {
            return response()->json(['errors' => Helpers::error_processor($validator)], 403);
        }

        $user_id = $request->user ? $request->user->id : $request['guest_id'];
        $is_guest = $request->user ? 0 : 1;

        $carts = Cart::where('user_id', $user_id)->where('is_guest',$is_guest)->where('module_id',getModuleId($request->header('moduleId')))->get();

        foreach($carts as $cart){
            $cart?->delete();
        }


        return $this->cartResponse(
            Cart::where('user_id', $user_id)->where('is_guest',$is_guest)->where('module_id',getModuleId($request->header('moduleId')))->get()
        );
    }
}
