<?php

namespace Modules\Cart\Http\Controllers;

use App\Functions\ResponseHelper;
use App\Http\Controllers\BasicController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Modules\Address\Entities\Model as Address;
use Modules\Address\Http\Resources\AddressResource;
use Modules\Cart\Entities\Model;
use Modules\Client\Entities\Model as Client;
use Modules\Client\Http\Resources\ClientResource;
use Modules\Country\Entities\Country;
use Modules\Coupon\Entities\Model as Coupon;
use Modules\Product\Entities\Model as Product;
use Modules\Product\Http\Resources\ProductResource;

class APIController extends BasicController
{
    public function client_id()
    {
        if (auth('sanctum')->check()) {
            return auth('sanctum')->id();
        } elseif (request()->client_id) {
            return request()->client_id;
        } else {
            return null;
        }
    }
    
    public function calc()
    {
        $Cart = [];
    
        $Products = [];
        $pre_order = false;
        $total_exclusive_vat = 0;
        $total_inclusive_vat = 0;
        $Models = Model::with('Product', 'Items.Section')->where('client_id', $this->client_id())->get();
    
        $total_discount = 0;
        $total_before_discount = 0;
        $total_after_discount = 0;
    
        foreach ($Models as $key => $Model) {
            if($Model->Product->pre_order && $pre_order == false){
                $pre_order = true;
            }
            $price_before_discount = $Model->Product->Price();
            $price_after_discount = $Model->Product->CalcPrice();
    
            $discount = 0;
            $Items = [];
            foreach ($Model->Items as $Item) {
                $price_before_discount += $Item->Price();
                $price_after_discount += $Item->CalcPrice();
                $Items[] = [
                    'id' => $Item->id,
                    'key' => $Item->Section->title(),
                    'value' => $Item->title(),
                ];
            }
            $discount = $price_before_discount - $price_after_discount;
            $total_discount += $discount * $Model->quantity;
            $total_before_discount += $Model->quantity * $price_before_discount;
            $total_after_discount += $Model->quantity * $price_after_discount;
    
            $Products[$key]['id'] = $Model->id;
            $Products[$key]['product_id'] = $Model->product_id;
            $Products[$key]['has_discount'] = $Model->Product->HasDiscount();
            if ($Model->Product->HasDiscount()) {
                $Products[$key]['discount'] = $Model->Product->HasDiscount() ? (string) $Model->Product->discount : null;
                $Products[$key]['price_before_discount'] = format_number($price_before_discount).' '.Country()->currancy_code;
                $Products[$key]['price_before_discount_value'] = format_number($price_before_discount);
                $Products[$key]['price_after_discount'] = format_number($price_after_discount).' '.Country()->currancy_code;
                $Products[$key]['price_after_discount_value'] = format_number($price_after_discount);
                $Products[$key]['discount'] = format_number($discount).' '.Country()->currancy_code;
            } else {
                $Products[$key]['price'] = format_number($price_after_discount).' '.Country()->currancy_code;
                $Products[$key]['price_value'] = format_number($price_after_discount);
            }
    
            // Calculate VAT based on quantity
            if ($Model->Product->VAT == 'exclusive') {
                $total_exclusive_vat += $price_after_discount * $Model->quantity;
            }elseif ($Model->Product->VAT == 'inclusive') {
                $total_inclusive_vat += $price_after_discount * $Model->quantity;
            }
    
            $Products[$key]['quantity'] = $Model->quantity;
            $Products[$key]['total'] = format_number($price_after_discount * $Model->quantity).' '.Country()->currancy_code;
            $Products[$key]['note'] = $Model->note;
            $Products[$key]['Items'] = $Items;
            $Products[$key]['Product'] = ProductResource::make($Model->Product);
        }
    
        // Calculate VAT after applying quantity
        $vat_exclusive = $total_exclusive_vat / 100 * setting('vat');
        $vat_inclusive = $total_inclusive_vat / 100 * setting('vat');
        
        $discount = format_number($total_discount);
        
        $Cart['pre_order'] = $pre_order;
        
        
    
        $Cart['coupon_valid'] = false;
        $Cart['coupon'] = format_number(0).' '.Country()->currancy_code;
        $Cart['code_message'] = '';
    
        $coupon_value = 0;
        if (request('coupon')) {
            $Coupon = Coupon::whereDate('from', '<=', now())->whereDate('to', '>=', now())->where('code', request('coupon'))->first();
            if ($Coupon) {
                if ($Coupon->percent_off) {
                    $coupon_value = number_format($total_after_discount * $Coupon->percent_off / 100, Country()->decimals, '.', '');
                } elseif ($Coupon->discount) {
                    $coupon_value = number_format($Coupon->discount, Country()->decimals, '.', '');
                }
                if ($coupon_value > 0 && $coupon_value < $total_after_discount) {
                    $Cart['coupon_valid'] = true;
                    $Cart['coupon_text'] = $Coupon->code;
                    $Cart['coupon'] = format_number($coupon_value).' '.Country()->currancy_code;
                    $Cart['code_message'] = __('trans.code_applied', ['coupon_value_number' => $coupon_value]).Country()->currancy_code;
                    
                    if($Coupon->percent_off){
                        $vat_exclusive -= $vat_exclusive * $Coupon->percent_off / 100;
                        $vat_inclusive -= $vat_inclusive * $Coupon->percent_off / 100;
                    } elseif ($Coupon->discount) {
                        // Calculate the proportion of discount that applies to each VAT type
                        if ($total_after_discount > 0) {
                            // Proportionally reduce VAT based on the discount ratio
                            $discount_ratio = $coupon_value / $total_after_discount;
                            $vat_exclusive -= $vat_exclusive * $discount_ratio;
                            $vat_inclusive -= $vat_inclusive * $discount_ratio;
                        }
                    }
                    
                } else {
                    $coupon_value = 0;
                }
            }
        }
        $netTotal = $total_after_discount + $vat_exclusive - $coupon_value ;
    
        $Address = NULL;
        $charge_cost = 0;
        
        if (request('address_id')) {
            $Address = Address::with('Region')->where('id',request('address_id'))->first();
            if($Address){
                $totalWeight = 0 ;
                foreach($Models as $cartItem){
                    $quantity = $cartItem->quantity ;
                    $weight = $cartItem->product->weight;
                    $totalWeight += $quantity * $weight ;
                }
                $WeightPrice = DB::table('weight')->orderby('weight')->where('weight','>=',$totalWeight)->where('country_id', $Address->country_id)->first();
                $charge_cost = $WeightPrice->price * Country()->currancy_value;
                if($Address->Country->free_delivery * Country()->currancy_value <= $netTotal){
                    $charge_cost = 0;
                }
            }
        }
    
        $netTotal += $charge_cost;
        
        $points_number = 0;
        $points_value = 0;
        $points_discount = 0;
        
        if(auth('sanctum')->check() && setting('loyalty_enabled') && auth('sanctum')->user()->AvailableLoyaltyPoints()){
            $points_number = auth('sanctum')->user()->AvailableLoyaltyPoints();
            
            if(request('use_points')){
                $pointsPerBHD = floatval(setting('loyalty_redeem_points_per_bhd') ?? 100); // 100 points = 1 BHD
                $maxRedeemPercent = floatval(setting('loyalty_max_redeem_percent') ?? 50); // max % of total
                
                $maxRedeemAmount = $netTotal * $maxRedeemPercent / 100;
                
                $maxPointsUsable = $maxRedeemAmount * $pointsPerBHD;
                
                $pointsToUse = min($points_number, $maxPointsUsable);
                
                $points_discount = ($pointsToUse / $pointsPerBHD) * Country()->currancy_value;
                $points_value = $points_discount;
            }
        }
        
        $netTotal -= $points_discount;
        
        $Cart['subTotal_display'] = $total_after_discount > 0;
        $Cart['subTotal_value'] = format_number($total_after_discount);
        $Cart['subTotal'] = format_number($total_after_discount).' '.Country()->currancy_code;
        
        $Cart['coupon_display'] = $coupon_value > 0;
        $Cart['coupon_value'] = format_number($coupon_value);
    
        $Cart['discount_display'] = $discount > 0;
        $Cart['discount_value'] = format_number($discount);
        $Cart['discount'] = format_number($discount).' '.Country()->currancy_code;
        
        $Cart['charge_cost_display'] = $charge_cost > 0;
        $Cart['charge_cost_value'] = format_number($charge_cost);
        $Cart['charge_cost'] = format_number($charge_cost).' '.Country()->currancy_code;
        
        $Cart['vat_percentage'] = setting('vat') . '%';
        $Cart['vat_value'] = format_number($vat_exclusive + $vat_inclusive);
        $Cart['vat'] = format_number($vat_exclusive + $vat_inclusive).' '.Country()->currancy_code;
        
        $Cart['points_number'] = $points_number;
        $Cart['points_discount_display'] = $points_discount > 0;
        $Cart['points_discount_value'] = format_number($points_discount);
        $Cart['points_discount'] = format_number($points_discount).' '.Country()->currancy_code;
        
        $Cart['netTotal_value'] = format_number($netTotal);
        $Cart['netTotal'] = format_number($netTotal).' '.Country()->currancy_code;
        
        
        $Cart['products'] = $Products;
        
        $Cart['Address'] = $Address ? AddressResource::make($Address) : null;
    
        return $Cart;
    }

    public function index()
    {
        return ResponseHelper::make($this->calc());
    }

    public function store(Request $request)
    {
        $Product = Product::findOrFail($request->product_id);

        if ($Product->status == 0) {
            return ResponseHelper::make(null, __('trans.notAvailable'), false);
        }

        // Check if there is an existing cart item with the same product_id and identical items
        $existingCart = Model::where('client_id', $this->client_id())
            ->where('product_id', $request->product_id)
            ->where('branch_id', $request->branch_id)
            ->when($request->items && count($request->items), function ($query) use ($request) {
                return $query->whereHas('Items', function ($q) use ($request) {
                    $q->whereIn('item_id', $request->items)->groupBy('cart_id')->havingRaw('COUNT(*) = ?', [count($request->items)]);
                });
            })

            ->first();

        if ($existingCart) {
            // If the item exists, just update the quantity
            $existingCart->quantity += $request->quantity;
            $existingCart->save();
        } else {
            // If the item does not exist, create a new one
            $Model = Model::create([
                'client_id' => $this->client_id(),
                'branch_id' => $request->branch_id,
                'product_id' => $request->product_id,
                'quantity' => $request->quantity,
                'note' => $request->note,
            ]);

            if ($request->items) {
                $Model->Items()->sync($request->items);
            }
        }

        Model::where('client_id', $this->client_id())
            ->whereNot('branch_id', $request->branch_id)
            ->delete();

        return ResponseHelper::make($this->calc(), __('trans.addedSuccessfully'));
    }

    public function update($lang, $id, Request $request)
    {
        $Model = Model::where('id', $id)->where('client_id', $this->client_id())->firstorfail();
        $Product = Product::findorfail($Model->product_id);

        Model::where('id', $id)->where('client_id', $this->client_id())->update([
            'quantity' => $request->quantity,
        ]);

        return ResponseHelper::make($this->calc(), __('trans.updatedSuccessfully'));
    }

    public function destroy($lang, $id)
    {
        if ($id == 1) {
            Model::where('client_id', $this->client_id())->delete();
        } else {
            Model::where('id', $id)->where('client_id', $this->client_id())->delete();
        }

        return ResponseHelper::make($this->calc(), __('trans.DeletedSuccessfully'));
    }

    public function assign_cart_to_client(Request $request)
    {
        $phone_code = str_replace('+', '', $request->phone_code);
        $Country = Country::where('phone_code', 'LIKE', "%{$phone_code}%")->first();

        $Model = Client::where('phone', $request->phone)->where('phone_code', $phone_code)->withTrashed()->first();
        if ($Model) {
            $Model->name = $request->name;
            $Model->status = 1;
            $Model->deleted_at = null;
            $Model->save();
            $Model = Client::where('phone', $request->phone)->where('phone_code', $phone_code)->first();
        } else {
            $Model = Client::create([
                'name' => $request->name,
                'phone' => $request->phone,
                'phone_code' => $phone_code,
                'country_code' => $Country->country_code,
                'country_id' => $Country->id,
                'status' => 1,
            ]);
        }
        auth('client')->login($Model);

        if (! $Model->DeviceTokens()->where(['device_token' => $request->device_token])->exists()) {
            $Model->DeviceTokens()->create([
                'device_token' => $request->device_token,
            ]);
        }

        Model::where('client_id', auth('sanctum')->id())->delete();
        Model::where('client_id', $request->client_id)->update([
            'client_id' => auth('sanctum')->id(),
        ]);

        $success['token'] = $Model->createToken('ClientToken')->plainTextToken;
        $success['client'] = ClientResource::make($Model);
        $success['cart'] = $this->calc();

        return ResponseHelper::make($success, __('trans.addedSuccessfully'));
    }
}
