<?php

namespace API\Product\Http\Controllers;

use API\Product\Http\Resources\CartResource;
use API\Product\Http\Resources\GroupProductResource;
use App\Http\Controllers\Controller;
use Mamad\Brand\Models\Brand;
use Mamad\Cart\Repository\CartRepository;
use Mamad\Category\Repositories\CategoryRepository;
use Mamad\Club\Services\ClubService;
use Mamad\Group_Product\Models\GroupProduct;
use Mamad\Group_Product\Repository\GroupProductRepository;
use Mamad\Marketing\Services\AffiliateService;
use Mamad\Order\Models\Order;
use Mamad\Order\Repository\OrderRepository;
use Mamad\PostMeta\Repository\PostMetaRepository;
use Mamad\Product\Models\Product;
use Illuminate\Http\Request;
use API\Product\Http\Resources\ProductResource;
use Mamad\Product\Repository\ProductRepository;
use API\Product\Repositories\APIProductRepository;
use Mamad\Product\Service\CouponService;
use Mamad\Product\Service\ProductService;
use Mamad\Shop\Service\ShopService;
use Mamad\Transaction\Events\TransactionSucceed;
use Mamad\Transaction\Models\Transaction;
use Mamad\Transaction\Repository\TransactionRepository;
use Mamad\User\Repositories\UserRepository;
use Mamad\Wallet\Services\WalletService;
use Mehrab\OrderService\Models\OrderService;
use Mehrab\OrderService\Repositories\OrderServiceRepo;
use Shetabit\Multipay\Exceptions\InvalidPaymentException;
use Shetabit\Payment\Facade\Payment;


class ProductController extends Controller
{
    public function recent_products(){
        $products=Product::query()->where("product_type","product")->orderByDesc("created_at")->paginate((int) request()->limit,['*'],"page",\request()->page??1);
        $group_products=GroupProduct::query()->orderByDesc("created_at")->paginate((int) request()->limit,['*'],"page",\request()->page??1);
        return [
            "products"=>ProductResource::collection($products),
            "group_products"=>GroupProductResource::collection($group_products),
        ];
    }
    public function product_detail(){

        $product=ProductRepository::find_by_slug(request()->slug);
        $related=ProductRepository::get_related_product_by_category($product);
        return [
            "product"=>new ProductResource($product),
            "related_products"=> ProductResource::collection($related)
        ];
    }
    public function group_product_detail(){

        $product=GroupProductRepository::find_by_slug(request()->slug);
        $related=ProductRepository::get_related_product_by_category($product);
        return [
            "product"=>new GroupProductResource($product),
            "related_products"=> GroupProductResource::collection($related)
        ];
    }
    public function search(){
        if(!empty(request()->s)){
            $products=ProductRepository::like_not_paginate(request()->s);
        }
        if(!empty(request()->code)){
            $products=PostMetaRepository::find_by_key_like("technicalCodes",(new Product())->getMorphClass(),request()->code,Product::class);
            $products=$products->get()->pluck("metaable")->filter();
        }
        if(!empty(\request()->filter) || !empty(\request()->type)|| !empty(\request()->brand)){
            $brandId=null;
            if(\request()->brand){
                $brand=Brand::query()->where("name",\request()->brand)->first();
                if($brand){
                    $brandId=$brand->id;
                }
            }
            $products=ProductRepository::get_products_by_categories(false,request()->filter,request()->type,$brandId);

        }


        if($products->isNotEmpty()){
            return ProductResource::collection($products);

        }
    }

    public function get_cart(Request $request){
        $user=request()->user();
        $cart=CartRepository::get_cart($user);

        //return $user->cart->cart_item;
        return  CartResource::collection($user->cart->cart_item);
    }

    public function add_to_cart(Request $request){
        $user=request()->user();
        CartRepository::add_cart_item_to_database($request->product_id,null,$request->quantity,$request->group_product_id,$user);
    }

    public function delete_from_cart(Request $request){
        $user=request()->user();
        CartRepository::delete_cart_item($request->product_id,$user);
    }
    public function increase_cart(Request $request){
        $user=request()->user();
        CartRepository::increase_cart($request->product_id,null,$user);
    }
    public function decrease_cart(Request $request){
        $user=request()->user();
        CartRepository::decrease_cart($request->product_id,$user);
    }


    public function add_order(Request $request){
        $data=[];
        foreach ($request->all() as $key=>$item) {


                $data[]=[
                    "name"=>$key,
                    "value"=>$item,
                ];

        }

        UserRepository::add_meta($data);


        $cart=CartRepository::get_cart($request->user());
        if($cart){


            $cart_products=ProductService::get_cart_products($cart);

            $amount=ShopService::get_order_total_price();
            $gateway_name="zarinpal";
            $data=["user_id"=>auth()->id(),"products_id"=>$cart,"price"=>$amount,"payment_type"=>$gateway_name];
            if($gateway_name=="home"){
                $status=Order::$PROCESSING;
            }
            else{
                $status=Order::$PENDING;
            }
            $order=OrderRepository::add_order($data,$status);


            if($amount > 0 && $gateway_name!="home"){
                CouponService::remove_coupon_session();
                return ShopService::send_to_gateway($gateway_name,$amount,$order);

            }

            else{
                CouponService::remove_coupon_session();
                event(new TransactionSucceed($order));
                ProductService::if_product_in_stock_decrease_stock_number($cart_products,$cart);
                //todo send success order email
                return ShopService::transaction_succeed_redirection($order);
            }

        }
    }


    public function verify_payment(Request $request){
            $transaction_id=$request->transaction;

        $transaction=TransactionRepository::find_by_transaction_id($transaction_id);
        if($transaction->status=="pending"){
            try {
                $receipt = Payment::amount((integer) $transaction->price)->transactionId($transaction_id)->verify();
                TransactionRepository::updateErrorText($transaction," ");
                if($transaction->transactionAble instanceof Order ){
                    TransactionRepository::updateStatus($transaction,Transaction::$PROCESSING);
                    TransactionRepository::update_transactionAble_Status($transaction->transactionable,Transaction::$PROCESSING);

                    $this->order_codes($transaction);
                } elseif($transaction instanceof Order){
                    $this->order_codes($transaction);
                }


                if($transaction->transactionAble instanceof OrderService ){

                        if(isset($transaction->transactionAble->meta["factor"])){
                            $order_factor=$transaction->transactionAble->meta["factor"];
                            $expert_percent_price=0;
                            $team_leader_percent_price=0;
                            $team_leader=$transaction->transactionAble->team_leader;
                            $expert=$transaction->transactionAble->expert;

                            foreach ($order_factor as $factor_item) {
                                $factor_item_price=$factor_item["amount"];
                                if(isset($factor_item["expert_percent"]) && $factor_item["expert_percent"] > 0){
                                    $expert_percent_price+=(int) floor(($factor_item["expert_percent"] / 100) * $factor_item_price);
                                }

                                if(isset($factor_item["team_leader_percent"]) && $factor_item["team_leader_percent"] > 0){
                                    $team_leader_percent_price+=(int) floor(($factor_item["team_leader_percent"] / 100) * $factor_item_price);
                                }
                            }

                            if($team_leader && $team_leader_percent_price > 0){
                                $team_leader->amount += $team_leader_percent_price ;
                                $team_leader->save();
                            }
                            if($expert && $expert_percent_price > 0){
                                $expert->amount += $expert_percent_price ;
                                $expert->save();
                            }
                        }









                    TransactionRepository::updateStatus($transaction,Transaction::$PROCESSING);

                    ClubService::increase($transaction->price,"service");
                    $affiliate_price=AffiliateService::calculate_service_affiliate_percent($transaction->transactionAble->service,$transaction->price);
                    AffiliateService::affiliate_update_amount($affiliate_price);
                    if($transaction->transactionAble){
                        resolve(OrderServiceRepo::class)->doneOrderService($transaction->transactionAble);

                    }
                }

                return "success";
            }
            catch (InvalidPaymentException $exception) {
                TransactionRepository::updateStatus($transaction,Transaction::$FAILED);
                TransactionRepository::updateErrorText($transaction,$exception->getMessage());

                TransactionRepository::update_transactionAble_Status($transaction->transactionable,Transaction::$FAILED);



                return "error";
            }
        } else{
            return "success";
        }

    }


    public function order_codes($transaction){
        $total_price=ShopService::get_order_total_price(false);
        $cart=CartRepository::get_cart(request()->user());
        if($cart) {
            $cart_products = ProductService::get_cart_products($cart);
            $affiliate_price=AffiliateService::calculate_affiliate_percent($cart_products);
            AffiliateService::affiliate_update_amount($affiliate_price);
            ProductService::if_product_in_stock_decrease_stock_number($cart_products, $cart);
        }
        session()->forget("cart");
        if($user_cart=request()->user()->cart()){
            $user_cart->delete();
        }

    }

}










