<?php

namespace App\Http\Controllers;

use App\Helpers\AppDataFormatter;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Yajny\Controller\StoreCtrl;
use Yajny\EventsYj\Events\NewBonusNew;
use Yajny\EventsYj\Events\PayoutModeNew;
use Yajny\EventsYj\Events\PayoutNew;
use Yajny\EventsYj\Events\SendOTP;
use Yajny\EventsYj\Listeners\RecalculateUserBalance;
use Yajny\Helpers\LoyaltyProgram\TierCalculator;
use Yajny\Helpers\StringReplacer;
use Yajny\MailYj\Mails\Email;
use Yajny\MailYj\Mails\Emailverification;
use Yajny\MailYj\Mails\ExtensionInstallation;
use Yajny\MailYj\Mails\ReferralInviteEmail;
use Yajny\MailYj\Mails\VerifyPayoutEmail;
use Yajny\Member\Models\BonusType;
use Yajny\Member\Models\Click;
use Yajny\Member\Models\Currencies;
use Yajny\Member\Models\CurrencyRate;
use Yajny\Member\Models\LoyaltyProgram;
use Yajny\Member\Models\Member;
use Yajny\Member\Models\NewBonusType;
use Yajny\Member\Models\OtpVerification;
use Yajny\Member\Models\PayoutMethods;
use Yajny\Member\Models\ReferralInvites;
use Yajny\Member\Models\Sale;
use Yajny\Member\Models\UserClaim;
use Yajny\Member\Models\UserClaimComment;
use Yajny\Member\Models\UserFavourite;
use Yajny\Member\Models\UserNewBonus;
use Yajny\Member\Models\UserNotification;
use Yajny\Member\Models\UserPayoutMethods;
use Yajny\Member\Models\UserPayouts;
use Yajny\Member\Models\UsersBalance;
use Yajny\Models\Country;
use Yajny\Models\Store;

class MemberController extends Controller
{
    /**
     * @var mixed
     */
    public $user_id;

    /** @var Member $member */
    public $member;

    /**
     * Create a new controller instance.
     *
     * @param Request $request
     */
    public function __construct(Request $request)
    {

        //  dd($request->get('user_id'));
        $is_valid = true;
        $user_id = $request->get('user_id');
        if (!$user_id)
            $is_valid = false;

        $this->user_id = $user_id;
        if (!$this->user_id > 0)
            $is_valid = false;

        $this->member = Member::find($this->user_id);
        if (!$this->member)
            $is_valid = false;

        if (!$is_valid) {
            echo '[]';
            die;
        }
    }

    /**
     * @param Request $req
     * @return mixed
     */
    public function getRecentClicks(Request $req)
    {

        $limit = $req->get('limit');
        return $this->member->getRecentClicks($limit);

    }

    /**
     * @param Request $req
     * @param $object
     * @return mixed
     */
    public function getHistoryClicks(Request $req, $object)
    {

        $page = $req->get('page') ? $req->get('page') : 1;

        if ($page && filter_var($page, FILTER_VALIDATE_INT) !== false && $page >= 1) {
            $limit = $req->get('limit');
            $clicks = $this->member->getHistoryClicks($object, $limit, $page);

            return [
                'history' => $clicks,
                'current_page' => $page,
                'last_page' => $page >= $clicks->lastPage()
            ];
        } else
            return;

    }

    /**
     * @param Request $req
     * @param $monthYear
     * @return mixed
     */
    public function getClicks(Request $req, $monthYear)
    {
        return $this->member->filteredClicks($monthYear);

    }

    /**
     * @param Request $req
     * @param $monthYear
     * @return mixed
     */
    public function getBonus(Request $req, $monthYear)
    {
        $status = 'all';

        return $this->member->filteredBonuses($monthYear, $status);

    }

    /**
     * @param Request $req
     * @param $monthYear
     * @return mixed
     */
    public function getBonusFormatted(Request $req, $monthYear)
    {
        $bonuses = $this->getBonus($req, $monthYear);
        $memberCurrency = $this->member->getUserCurrency();
        foreach ($bonuses as $bonus) {
            $bonus->applyCurrencyConversion($memberCurrency);
        }
        return $bonuses;
    }

    public function updateNotificationSetting(Request $req)
    {
        $notification_enabled = $req->post('notification_enabled');
        if ($notification_enabled == "true") {
            $this->member->notification_enabled = true;
        } else {
            $this->member->notification_enabled = false;
        }
        $this->member->save();
        return $this->member;
    }

    public function getNotifications(Request $req)
    {
        $limit = $req->get('limit');
        $page = $req->get('page');
        $notifs = $this->member->getNotifications($limit, $page);

        return $notifs;
    }

    public function updateNotification(Request $req, $notification_id, $is_read = 1)
    {
        $notification = UserNotification::find($notification_id);
        if (!is_null($notification)) {
            $notification->seen_date = $notification->is_read ? null : Carbon::now()->format('d-m-Y H:i:s');
            $notification->is_read = $is_read;
            $notification->save();
            return $notification;
        }
        return new NotFoundHttpException();
    }

    /**
     * @param Request $req
     * @param $monthYear
     * @return mixed
     */
    public function getSales(Request $req, $monthYear)
    {
        $status = 'all';

        return $this->member->filteredSales($monthYear, $status);
    }

    /**
     * @param Request $req
     * @param $monthYear
     * @return mixed
     */
    public function getSalesFormatted(Request $req, $monthYear)
    {
        $sales = $this->getSales($req, $monthYear);
        $memberCurrency = $this->member->getUserCurrency();
        foreach ($sales as $sale) {
            $sale->applyCurrencyConversion($memberCurrency);
        }
        return $sales;
    }

    /**
     * @param Request $req
     * @param $monthYear
     * @return mixed
     */
    public function getReferralSales(Request $req, $monthYear)
    {
        $status = 'all';

        return $this->member->filteredReferralSales($monthYear, $status);

    }

    /**
     * @param Request $req
     * @param $monthYear
     * @return mixed
     */
    public function getReferralSalesFormatted(Request $req, $monthYear)
    {
        $sales = $this->getReferralSales($req, $monthYear);
        $memberCurrency = $this->member->getUserCurrency();
        foreach ($sales as $sale) {
            $sale->applyCurrencyConversion($memberCurrency);
        }
        return $sales;
    }

    /** Get All Favourite Stores **/
    public function allFavouriteStores(Request $req)
    {
        $fav_object = "store";

        $StoreCtrl = new StoreCtrl;
        return $favorateObj = $StoreCtrl->getAllFavorateStores($this->user_id, $fav_object);

        // return response()->json($favorateObj);
    }

    /**
     * @param Request $req
     * @return mixed
     */
    public function allFavouriteOffers(Request $req)
    {

        $fav_object = "coupon";

        $StoreCtrl = new StoreCtrl;
        return $favorateOffer = $StoreCtrl->getAllFavorateStores($this->user_id, $fav_object);
        // return response()->json($favorateOffer);

    }

    // TODO: To Be Removed in new Release

    /**
     * @param Request $req
     * @return int
     */
    public function favouriteAction(Request $req)
    {
        try {
            if ($req->action == 'add')
                $this->member->favourites()->save(new UserFavourite(["fav_object" => $req->fav_object, "object_id" => $req->object_id]));
            else
                $this->member->favourites()->where('fav_object', $req->fav_object)->where('object_id', $req->object_id)->delete();
        } catch (\Illuminate\Database\QueryException $ex) {

        }
        return 1;
    }

    // TODO: To Be Removed in new Release

    /**
     * @param Request $req
     * @return array
     */
    public function getFavourites(Request $req)
    {
        return array_merge(
            ['store' => [], 'coupon' => []],
            UserFavourite::where('user_id', $this->user_id)
                ->groupBy('fav_object')
                ->selectRaw("fav_object,GROUP_CONCAT(object_id) as list ")
                ->get()->mapWithKeys(function ($favData) {
                    return [$favData->fav_object => array_map('intval', explode(',', $favData->list))];
                })
                ->toArray()
        );
    }

    /** Get All Favourite Stores , Coupons , Brands  **/
    public function getFavouritesWithData($fav_object)
    {
        $favorateData = new UserFavourite;
        if ($fav_object == 'store') {
            $favorateData = $favorateData->with(['store' => function ($q) {
                $q->selectRaw(\Yajny\Models\Store::colSelect());
            }]);
        } else if ($fav_object == 'brand') {

            $favorateData = $favorateData->with(['brand' => function ($q) {
                $q->selectRaw(\Yajny\Models\Brand::colSelect());
            }]);
        } else if ($fav_object == 'coupon') {
            $favorateData = $favorateData->with(['coupon' => function ($q) {
                $q->selectRaw(\Yajny\Models\Coupon::colSelect());
                $q->with(['coupon_store' => function ($q) {
                    $q->selectRaw(\Yajny\Models\Store::colSelect());
                }]);
            }]);
        }
        $favorateData = $favorateData->where('user_id', $this->user_id);
        if ($fav_object != null) {
            $favorateData = $favorateData->where('fav_object', $fav_object);
        }

        $favorateData = $favorateData->limit(20)->get();
        return $favorateData;
    }

    /**
     * @param $object
     */
    public function hasFavoritesObject($fav_object)
    {
        $favorateData = new UserFavourite;
        $favorateData = $favorateData->where('user_id', $this->user_id);
        if ($fav_object != null) {
            $favorateData = $favorateData->where('fav_object', $fav_object);
        }

        $favorateData = $favorateData->count();
        return ($favorateData) ? true : false;
    }

    /**
     * @param Request $req
     * @return \Illuminate\Database\Eloquent\Collection
     */
    public function getClaims(Request $req)
    {
        return $this->member->getClaims();
    }

    /**
     * @param Request $req
     * @return \Illuminate\Database\Eloquent\Collection
     */
    public function getClaimsFormatted(Request $req)
    {
        $claims = $this->getClaims($req);
        foreach ($claims as $claim) {
            $claim->applyCurrencyConversion();
        }
        return $claims;
    }

    /**
     * @param Request $req
     * @param $claim_id
     * @return \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Relations\HasMany|object|null
     */
    public function getClaimInfo(Request $req, $claim_id)
    {
        return $this->member->getClaimInfo($claim_id);
    }

    /**
     * @param Request $req
     * @param $claim_id
     * @return \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Relations\HasMany|object|null
     */
    public function getClaimInfoFormatted(Request $req, $claim_id)
    {
        $claim = $this->getClaimInfo($req, $claim_id);
        if (!$claim)
            abort(404);
        $claim->applyCurrencyConversion();
        return $claim;
    }

    /**
     * @param Request $request
     * @param $claim_id
     * @return int
     * @throws ValidationException
     */
    public function makeComment(Request $request, $claim_id)
    {
        $userClaim = UserClaim::find($claim_id);
        if (!$userClaim)
            throw ValidationException::withMessages(['claim_id' => ['invalid']]);

        $validator = Validator::make($request->all(), [
            'comment' => 'required',
            'attachments.*' => 'file|mimes:jpeg,bmp,png,gif,svg,jpg|max:1000'
        ]);

        $validatorErrors = $validator->errors()->messages();
        foreach ($validatorErrors as $key => $value) {
            if (substr($key, 0, strlen('attachments')) === 'attachments') {
                unset($validatorErrors[$key]);
                $validatorErrors['attachments'] = 'invalid';
            }
        }

        if ($validator->fails())
            throw ValidationException::withMessages($validatorErrors);

        $comment = new UserClaimComment(['claim_id' => $claim_id, 'comment' => $request->comment, 'commented_by' => 'user']);
        $comment->save();

        $attachmentsUrls = [];
        if ($request->has('attachments') && !empty($request->attachments)) {
            foreach ($request->attachments as $attachment)
                $attachmentsUrls[] = Storage::disk('do-spaces')->putFile("claims/{$comment->claim->id}", $attachment);
        }

        if (!empty($attachmentsUrls)) {
            $comment->attachments = json_encode($attachmentsUrls);
            $comment->save();
        }

        return 1;
    }

    /**
     * @param Request $req
     * @return mixed
     */
    public function getClaimableStores(Request $req)
    {
        // \DB::enableQueryLog();
        return $this->member->getClaimableStores();
        //  return (\DB::getQueryLog());

    }

    /**
     * @param Request $req
     * @param $store_id
     * @return mixed
     */
    public function getClaimableClicks(Request $req, $store_id)
    {
        return $this->member->getClaimableClicks($store_id);
    }

    /**
     * @param Request $request
     * @return array|UserClaim
     * @throws ValidationException
     */
    public function makeClaim(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'store_id' => 'required|exists:stores,id',
            'click_id' => 'required|unique:user_claims,click_id',
            'platform' => 'required',
            'order_id' => "required|unique:user_claims,order_id,NULL,id,store_id,{$request->store_id}",
            'order_amount' => 'required|numeric',
            'currency_iso' => 'required',
            'transaction_date' => 'required',
            'attachments.*' => 'file|mimes:jpeg,bmp,png,gif,svg,jpg|max:1000'
        ]);

        if ($validator->fails()) {
            return ['errors' => $validator->errors()];
        }

        if (strtotime($request->transaction_date) < strtotime(date('Y-m-d', strtotime('now - ' . (config('settingConfig.missing_cb_max_days')) . ' days'))))
            $dateError = 'Date < allowed';
        else if (strtotime($request->transaction_date) > strtotime(date('Y-m-d', strtotime('now - ' . (config('settingConfig.missing_cb_min_days')) . ' days'))))
            $dateError = 'Date > Allowed';
        else
            $dateError = false;

        if ($dateError)
            throw ValidationException::withMessages(['transaction_date' => ['invalid']]);

        $claim = $this->member->makeClaim($request->all());

        $attachmentsUrls = [];
        $attachments = $request->attachments;
        foreach ($attachments as $attachment)
            $attachmentsUrls[] = Storage::disk('do-spaces')->putFile("claims/{$claim->id}", $attachment);

        if (!empty($attachmentsUrls)) {
            $claim->attachments = json_encode($attachmentsUrls);
            $claim->save();
        }

        return $claim;
    }

    /**
     * @param Request $req
     * @param $monthYear
     * @return mixed
     */
    public function getPayouts(Request $req, $monthYear)
    {
        return $this->member->getPayouts($monthYear);
    }

    /**
     * @param Request $req
     * @param $monthYear
     * @return mixed
     */
    public function getPayoutsFormatted(Request $req, $monthYear)
    {
        $payouts = $this->getPayouts($req, $monthYear);
        $memberCurrency = $this->member->getUserCurrency();
        foreach ($payouts as $payout) {
            $payout->applyCurrencyConversion($memberCurrency);
        }
        return $payouts;
    }

    /**
     * @param Request $req
     * @return \Illuminate\Database\Eloquent\Collection
     */
    public function getLinks(Request $req)
    {
        return $this->member->links()->with(['stores' => function ($q) {
            $q->selectRaw(\Yajny\Models\Store::colSelect());
        }])
            ->get();
    }

    /**
     * @param Request $req
     * @return mixed
     */
    public function getShareableStores(Request $req)
    {
        return StoreCtrl::getCashbackStores($req->keyword);
    }

    /**
     * @param Request $req
     * @param $dataFor
     * @return array|\Illuminate\Database\Eloquent\Collection|\Illuminate\Support\Collection
     */
    public function getPassbook(Request $req, $dataFor)
    {
        if ($dataFor == 'sales')
            return $this->member->sales()->select('id', 'cashback as amount', 'transaction_time as action_date')->selectRaw("'cashback' as action")->ByStatus('confirmed')->orderBy('id', 'DESC')->get();
        elseif ($dataFor == 'bonus')
            return $this->member->bonuses()->orderBy('id', 'DESC')->ByStatus('confirmed')->select('id', 'amount', 'awarded_on as action_date')->selectRaw("'bonus' as action")->get();
        elseif ($dataFor == 'referrals')
            return $this->member->referral_sales()->ByStatus('confirmed')->orderBy('id', 'DESC')->select('id', 'referral_amount as amount', 'created_at as action_date')->selectRaw("'referal' as action")->get();
        elseif ($dataFor == 'payouts')
            return $this->member->payouts()->orderBy('id', 'DESC')->where('status', '<>', 'declined')->select('id', 'amount', 'created_at as action_date')->selectRaw("'payout' as action")->get();
        else
            return [];
    }

    /**
     * @param Request $req
     * @param $dataFor
     * @return array|\Illuminate\Database\Eloquent\Collection|\Illuminate\Support\Collection
     */
    public function getPassbookFormatted(Request $req, $dataFor)
    {
        $passbookData = $this->getPassbook($req, $dataFor);
        $memberCurrency = $this->member->getUserCurrency();
        foreach ($passbookData as $passbookRecord) {
            $passbookRecord->applyCurrencyConversion($memberCurrency);
        }
        return $passbookData;
    }

    /**
     * @return array
     */
    public function getBalance(): array
    {
        return $this->member->getBalances();
    }

    /**
     * @return array
     */
    public function getBalanceFormatted(): array
    {
        $balance = $this->getBalance();
        $balance['cashback']['total'] = ($balance['cashback']['pending'] ?? 0) + ($balance['cashback']['confirmed'] ?? 0);
        $balance['cashback']['available'] = ($balance['cashback']['confirmed'] ?? 0) - ($balance['paid']['cashback'] ?? 0);
        $balance['reward']['total'] = ($balance['reward']['pending'] ?? 0) + ($balance['reward']['confirmed'] ?? 0);
        $balance['reward']['available'] = ($balance['reward']['confirmed'] ?? 0) - ($balance['paid']['reward'] ?? 0);
        $balance['available'] = $this->member->confirmed_balance;
        $memberCurrency = $this->member->getUserCurrency();
        foreach ($balance as $key => $valueTypes) {
            if (is_array($valueTypes)) {
                foreach ($valueTypes as $type => $valueType) {
                    $balance[$key][$type] = round($valueType * $memberCurrency->conversion_rate, 2);
                    $balance[$key]["{$type}_formatted"] = $this->currencyValueFormatted($valueType * $memberCurrency->conversion_rate, $memberCurrency);
                }
            } else {
                $balance[$key] = round($valueTypes * $memberCurrency->conversion_rate, 2);
                $balance["{$key}_formatted"] = $this->currencyValueFormatted($valueTypes * $memberCurrency->conversion_rate, $memberCurrency);
            }
        }
        return $balance;
    }

    /**
     * @return array
     */
    public function getBalanceDetails(): array
    {
        $balance = [];
        $balanceDetails = $this->getBalance();
        $balance['balance'] = $this->member->pending_balance + $this->member->confirmed_balance;
        $balance['pending'] = $this->member->pending_balance;
        $balance['available'] = $this->member->confirmed_balance;
        $balance['bonus'] = ($balanceDetails['reward']['pending'] ?? 0) + ($balanceDetails['reward']['confirmed'] ?? 0);
        $balance['paid'] = ($balanceDetails['paid']['cashback'] ?? 0) + ($balanceDetails['paid']['reward'] ?? 0);
        $memberCurrency = $this->member->getUserCurrency();
        foreach ($balance as $balanceType => $value) {
            $balance[$balanceType] = round($value * $memberCurrency->conversion_rate, 2);
            $balance["{$balanceType}_formatted"] = $this->currencyValueFormatted($value * $memberCurrency->conversion_rate, $memberCurrency);
        }
        $balance['orders'] = $this->member->sales()->count();
        return $balance;
    }

    /**
     * @return array
     */
    public function getOrders(): array
    {
        $memberSales = $this->member->sales()->with(['store' => function ($q) {
            $q->selectRaw(Store::colSelect());
        }])->orderByDesc('transaction_time')->get();
        $memberCurrency = $this->member->getUserCurrency();
        $totalCashback = 0;
        foreach ($memberSales as $sale) {
            if ($sale->currency == $memberCurrency->iso_code) {
                $memberCurrency->conversion_rate = 1;
                $order_amount_formatted = ($sale->local_order_amount) . ' ' . $memberCurrency->iso_code;
                $cashback_formatted = ($sale->user_cashback_amount) . ' ' . $memberCurrency->iso_code;
            } else {
                $currencyRate = CurrencyRate::where('start_date', '<', $sale->transaction_time)
                    ->where('currency_code', $memberCurrency->iso_code)
                    ->orderBy('start_date', 'desc')->first();
                if (is_null($currencyRate)) $currencyRate = CurrencyRate::where('currency_code', $memberCurrency->iso_code)->first();
                $memberCurrency->conversion_rate = $currencyRate->conversion_rate;
                $order_amount_formatted = round($sale->order_amount * $memberCurrency->conversion_rate, 2) . ' ' . $memberCurrency->iso_code;
                $cashback_formatted = round($sale->cashback * $memberCurrency->conversion_rate, 2) . ' ' . $memberCurrency->iso_code;

            }
            $sale->applyCurrencyConversion($memberCurrency);
            $totalCashback += ($sale->cashback * $memberCurrency->conversion_rate);
            $sale->order_amount_formatted = $order_amount_formatted;
            $sale->cashback_formatted = $cashback_formatted;
        }
        return [
            'orders' => $memberSales,
            'total_count' => $memberSales->count(),
            'total_cashback' => round($totalCashback, 2),
            'total_cashback_formatted' => $this->currencyValueFormatted($totalCashback, $memberCurrency)
        ];
    }

    /**
     * @param Request $req
     * @return array|string[]
     */
    public function createLink(Request $req)
    {
        if ($req->offer_title && $req->offer_link) {
            $store = Store::whereRaw(" '{$req->offer_link}'  REGEXP domain_name ")->selectRaw(\Yajny\Models\Store::colSelect())->first();
            if (!$store)
                return ['error' => 'NO_STORE'];

            $link = $this->member->createLink($req->offer_title, $req->offer_link, $store->id);

            return [
                'linkCode' => $link->code,
                'offerTitle' => $req->offer_title,
                'store' => $store
            ];
        } else
            return ['error' => 'NO_LINK_OR_TITLE'];
    }

    /**
     * @param Request $request
     * @return UserClaim
     * @throws ValidationException
     */
    public function createClaim(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'store_id' => 'required|exists:stores,id',
            'click_id' => 'required|unique:user_claims,click_id',
            'platform' => 'required',
            'order_id' => "required|unique:user_claims,order_id,NULL,id,store_id,{$request->store_id}",
            'order_amount' => 'required|numeric',
            'currency_iso' => 'required',
            'transaction_date' => 'required',
            'attachments.*' => 'file|mimes:jpeg,bmp,png,gif,svg,jpg|max:1000'
        ]);

        $validatorErrors = $validator->errors()->messages();
        foreach ($validatorErrors as $key => $value) {
            if (substr($key, 0, strlen('attachments')) === 'attachments') {
                unset($validatorErrors[$key]);
                $validatorErrors['attachments'] = 'invalid';
            }
        }

        if ($validator->fails())
            throw ValidationException::withMessages($validatorErrors);

        if (strtotime($request->transaction_date) < strtotime(date('Y-m-d', strtotime('now - ' . (config('settingConfig.missing_cb_max_days')) . ' days'))))
            $dateError = 'Date < allowed';
        else if (strtotime($request->transaction_date) > strtotime(date('Y-m-d', strtotime('now - ' . (config('settingConfig.missing_cb_min_days')) . ' days'))))
            $dateError = 'Date > Allowed';
        else
            $dateError = false;

        if ($dateError)
            throw ValidationException::withMessages(['transaction_date' => ['invalid']]);

        $claim = $this->member->makeClaim($request->all());

        $attachmentsUrls = [];
        if ($request->has('attachments') && !empty($request->attachments)) {
            foreach ($request->attachments as $attachment)
                $attachmentsUrls[] = Storage::disk('do-spaces')->putFile("claims/{$claim->id}", $attachment);
        }

        if (!empty($attachmentsUrls)) {
            $claim->attachments = json_encode($attachmentsUrls);
            $claim->save();
        }

        return $claim;
    }

    /**
     * @param Request $req
     * @return array
     */
    public function getPayoutMethods(Request $req)
    {
        $methodsQuery = PayoutMethods::where('enabled', true)->selectRaw(PayoutMethods::colSelect());
        if (isset($this->member->country_code)) {
            $methodsQuery->whereJsonContains('country', $this->member->country_code);
        } else {
            $methodsQuery->whereNull('country');
        }
        $methods = $methodsQuery->get();
        if ($methods->isEmpty() && isset($this->member->country_code)) {
            $methodsQuery = PayoutMethods::where('enabled', true)->whereNull('country')->selectRaw(PayoutMethods::colSelect());
            $methods = $methodsQuery->get();
        }
        $user_methods = $this->member->payout_methods()->orderBy('id', 'DESC')->get();

        return [
            'methods' => $methods,
            'userMethods' => $user_methods
        ];
    }

    /**
     * @param Request $req
     * @return array
     */
    public function getPayoutMethodsFormatted(Request $req)
    {
        $data = $this->getPayoutMethods($req);
        foreach ($data['methods'] as $method) {
            $method->applyCurrencyConversion();
        }
        return $data;
    }

    /*
     * @return array
     */
    public function getNewBonuses()
    {
        $user_id = $this->member->user_id;
        $bonusTypes = [];

        $bonusTypes['finished'] = NewBonusType::whereHas('userBonuses', function ($query) use ($user_id) {
            $query->where('user_id', $user_id);
        })->where('is_referral', 0)->get();
        if ($this->member->has_old_orders == true) {
            $bonusTypes['not_finished'] = NewBonusType::where('id', '<>', 2)->whereDoesntHave('userBonuses', function ($query) use ($user_id) {
                $query->where('user_id', $user_id);
            })->where('is_referral', 0)->get();
        } else {
            $bonusTypes['not_finished'] = NewBonusType::whereDoesntHave('userBonuses', function ($query) use ($user_id) {
                $query->where('user_id', $user_id);
            })->where('is_referral', 0)->get();
        }
        return $bonusTypes;
    }

    /*
    * @return array
    */
    public function getRewardedBonuses()
    {
        $user_id = $this->member->user_id;
        $bonuses = UserNewBonus::with('newBonusType')->where([['user_id', $user_id], ['expiration_date', '>', now()]])->get();
        $memberCurrency = $this->member->getUserCurrency();
        foreach ($bonuses as $bonus) {
            $memberCurrency->conversion_rate = AppDataFormatter::getCurrencyRate($memberCurrency, $bonus->awarded_on);
            $bonus->applyCurrencyConversion($memberCurrency);
        }
        return $bonuses;
    }

    /**
     * @param Request $req
     * @return array
     */
    public function assignNewBonus(Request $req)
    {
        $validator = Validator::make($req->all(), [
            'bonus_id' => 'required',
        ]);

        $validatorErrors = $validator->errors()->messages();
        if ($validator->fails())
            throw ValidationException::withMessages($validatorErrors);
        $oldCount = UserNewBonus::where([['user_id', $this->member->user_id], ['bonus_type_id', $req->bonus_id]])->count();
        if ($oldCount) return [];
        $bonus = NewBonusType::find($req->bonus_id);
        $user_bonus = new UserNewBonus();
        $user_bonus->user_id = $this->member->user_id;
        $user_bonus->bonus_type_id = $bonus->id;
        $user_bonus->awarded_points = $bonus->points;
        $user_bonus->awarded_on = now();
        $user_bonus->save();
        event(new NewBonusNew($this->member, $bonus));
        return $bonus;
    }

    /**
     * @param Request $req
     * @return boolean
     */
    public function hasPayoutMethodsFormatted(Request $req)
    {
        $data = $this->getPayoutMethods($req);
        return (bool)$data['userMethods'];
    }

    /**
     * @param Request $request
     * @return array
     * @throws ValidationException
     */
    public function addPayMethod(Request $request)
    {
        $request->account = str_replace(' ', '', $request->account);
        $request->request->add(['method_code' => $request->code]);
        $request->account = StringReplacer::replaceArabicNumber($request->account);
        $payoutMethod = PayoutMethods::where('code', $request->code)->first();
        $validationAttributes = [];
        foreach ($payoutMethod->fields as $field) {
            $field_label = (array)$field->label;
            $validationAttributes[$field->key] = $field_label[$request->lang];
        }
        $validator = Validator::make($request->all(), [
            'name' => 'required',
            'method_code' => 'required',
            'account' => 'unique:user_payout_methods,account,NULL,id,deleted_at,NULL'
        ], [], $validationAttributes);
        $payout_data = [];
        $payoutMethod = PayoutMethods::where('code', $request->code)->first();
        if ($payoutMethod) {
            foreach ($payoutMethod->fields as $field) {
                $validator->sometimes($field->key, 'required', function () use ($field) {
                    return $field->required;
                });
                if ($field->type == 'number' && isset($field->length)) {
                    $validator->sometimes($field->key, 'digits:' . $field->length, function () use ($field) {
                        return $field->length;
                    });
                }
                $payout_data[$field->key] = $request->{$field->key} ?? '';
            }
        }

        if ($validator->fails())
            throw ValidationException::withMessages($validator->errors()->toArray());

        $new_method = new UserPayoutMethods([
            'method_code' => $request->code,
            'account' => $request->account,
            'name' => $request->name,
            'verify_code' => time(),
            'payout_data' => $payout_data
        ]);

        event(new PayoutModeNew($this->member, $this->member->payout_methods()->save($new_method)));
        return ['email' => 'sent', 'id' => $new_method->id];
    }

    /**
     * @param Request $request
     * @return array|array[]
     */
    public function raisePayout(Request $request)
    {
        $method = PayoutMethods::where('code', $request->code)->where('enabled', true)->first();
        $userPayouts=UserPayouts::where("user_id",$this->member->user_id)
            ->whereIn("status",['pending',"processing","created","approved_manually"])
            ->first();
        if ($userPayouts){
            return ['error' =>['payment_declined' => " already you  have already create a payout request "]];
        }
        else{
        //get user country because the mobile is currently sending USD only
        $countryCode = $this->member->country_code;
        $conversionRate = 1;
        if ($countryCode) {
            $country = Country::where('code', $countryCode)->first();
            $currency = Currencies::where('iso_code', $country->default_currency ?? 'USD')->first();
            $conversionRate = $currency->conversion_rate;
        }
        $userBalance=UsersBalance::where('user_id',$this->member->user_id)->first();
        if ($method->default_currency == "USD") {
            // check for cashback more than bonus
            if ($userBalance->confirmed_cashback < $userBalance->confirmed_bonus) {
                if ($request->withdrawal_amount > 2 * $userBalance->confirmed_cashback)
                    return ['payment_declined' => "cashback amount less than min amount"];
            }

            if ($userBalance->available_amount < $request->withdrawal_amount) {
                return ['payment_declined' => "cashback amount less than min amount"];
            }
        } // payout method used is different from USD
        else {
            // check for cashback more than bonus

            if ($userBalance->confirmed_cashback_. strtolower($method->default_currency) < $userBalance->confirmed_bonus_. strtolower($method->default_currency)) {
                if ($request->withdrawal_amount > 2 * $userBalance->confirmed_cashback_. strtolower($method->default_currency))
                    return ['payment_declined' => "cashback amount less than min amount"];
            }
        }
        $payout_response = $this->member->raisePayout($request->withdrawal_amount * $conversionRate, $request->code, $request->account);
        if (is_array($payout_response))
            return ['error' => $payout_response];
        else
            return ['payout_id' => $payout_response];
        }
    }

    /**
     * @param Request $request
     * @return array|array[]
     */
    public function raisePayoutFormatted(Request $request)
    {
        $method = PayoutMethods::where('code', $request->code)->where('enabled', true)->first();
        $userPayouts=UserPayouts::where("user_id",$this->member->user_id)
            ->whereIn("status",['pending',"processing","created","approved_manually","approved_automatically"])
            ->first();
        if ($userPayouts){
            return ['error' =>['payment_declined' => " already you  have already create a payout request "]];
        }else{
        $userPayout=UserPayouts::where([['amount',$request->withdrawal_amount],['method_code',$request->code],['account',$request->account],["user_id",$this->member->user_id],["created_at",'>',Carbon::now()->subMinute()->format("y-m-d H:i:s")]])->first();
        if ($userPayout)
            return $userPayout;
        $userBalance=UsersBalance::where('user_id',$this->member->user_id)->first();
            if ($method->default_currency == "USD") {
                // check for cashback more than bonus
                    if ($userBalance->confirmed_cashback < $userBalance->confirmed_bonus) {
                        if ($request->withdrawal_amount > 2 * $userBalance->confirmed_cashback)
                            return ['payment_declined' => "cashback amount less than min amount"];
                    }

                if ($userBalance->available_amount < $request->withdrawal_amount) {
                    return ['payment_declined' => "cashback amount less than min amount"];
                }
            } // payout method used is different from USD
            else {
                // check for cashback more than bonus

                if ($userBalance->confirmed_cashback_. strtolower($method->default_currency) < $userBalance->confirmed_bonus_. strtolower($method->default_currency)) {
                    if ($request->withdrawal_amount > 2 * $userBalance->confirmed_cashback_. strtolower($method->default_currency))
                        return ['payment_declined' => "cashback amount less than min amount"];
                }
            }
        $payout_response = $this->member->raisePayout($request->withdrawal_amount, $request->code, $request->account);
        if (is_array($payout_response))
            return ['error' => $payout_response];
        else
            return ["success"=>[
                "payout_id" => $payout_response['payout_id'],
                "method_info" => $payout_response['method_info']->name,
                "account" => $payout_response['account'],
                "status" => $payout_response['status'],
                "note" => $payout_response['note']
            ]
            ];
        }

    }

    /**
     * @param Request $request
     * @return array|array[]
     */
    public function Payout(Request $request)
    {
        $amount=$request->withdrawal_amount;
        $account=$request->account;
        $method_code=$request->code;
        $Confirmed_balance = UsersBalance::where('user_id',  $this->member->user_id)->first();
        $method = PayoutMethods::where('code', $method_code)->where('enabled', true)->first();
        if (!$method) {
            // return error -> Method not found
            return ['payment_method' => "method_error"];
        }
        $userPayMode = $this->member->payout_methods()->where('method_code', $method_code)->where('account', $account)->first();
        if (!$userPayMode) {
            // return error -> Method not found
            return ['payment_mode' => "mode_error"];
        }
        $conversionRate = 1;
        if (isset($method->default_currency) && strtoupper($method->default_currency) != 'USD') {
            $payoutCurrency = Currencies::where('iso_code', strtoupper($method->default_currency))->first();
            if ($payoutCurrency) {
                $conversionRate = $payoutCurrency->conversion_rate;
            }
        }
        $amountInUSD = $amount / $conversionRate;

        if ($amount < $method->minimum_amount) {
            // return error -> Requesting less than Minuimum amount
            return ['payment_declined' => __('validation.less_than_min_amount')];
        }

        if ($amountInUSD > $Confirmed_balance) {
            // error -> requesting amount > available amount
            return ['payment_declined' => __('validation.more_than_max_amount')];
        }
        $fees = null;
        $methodFee = $method->fee;
        if ($methodFee) {
            if ($methodFee->type == 'percentage')
                $fees = $amount * $methodFee->amount / 100;
            else
                $fees = $methodFee->amount;

            if ($methodFee->min_amount)
                $fees = max($fees, $methodFee->min_amount);
        }

        $payout = new UserPayouts;
        $payout->method_code = $method_code;
        $payout->amount = $amountInUSD;
        $payout->final_amount = $amountInUSD;
        $payout->cashback_amount = 0;
        $payout->reward_amount = 0;
        $payout->account = $account;
        $payout->currency_rate = $conversionRate;
        $payout->local_currency = $method->default_currency;
        $payout->local_amount = $amount;
        $payout->local_final_amount = $amount;
        $payout->status = 'created';

        if ($fees) {
            $feesInUSD = $fees / $conversionRate;
            $payout->fees_amount = $feesInUSD;
            $payout->local_fees_amount = $fees;
            $payout->final_amount = $amountInUSD - $feesInUSD;
            $payout->local_final_amount = $amount - $fees;
            $payout->fees_data = json_encode([
                'amount' => $methodFee->amount,
                'type' => $methodFee->type,
                'min_amount' => $methodFee->min_amount
            ]);
        }

        $this->member->payouts()->save($payout);
        event(new  PayoutNew($this->member, $payout));
        return [
            "payout_id" => $payout->payout_id,
            "method_info" => $payout->method_info->name,
            "account" => $payout->account,
            "amount" => \App\Helpers\FormateHelper::currencyFormat($payout->local_amount, $payoutCurrency),
            "status" => $payout->status,
            "note" => $payout->note
        ];

    }


    /**
     * @param Request $request
     * @return Member
     */
    public function updateProfile(Request $request)
    {
        $countries = Country::where('for_otp', 1)->pluck('valid_prefixes');
        $validPrefixes = [];
        foreach ($countries as $country) {
            $validPrefixes = array_merge_recursive($validPrefixes, json_decode($country));
        }
        Validator::make($request->all(), [
            'gender' => 'sometimes|in:Male,Female',
            'photo' => 'sometimes|mimes:jpeg,jpg,png',
            'phone_number' => 'sometimes|unique:users,phone_number,' . $this->member->user_id . ',user_id|starts_with:' . implode(',', $validPrefixes)
        ])->validate();
        $this->member->first_name = isset($request->first_name) ? substr($request->first_name, 0, 100) : $this->member->first_name;
        $this->member->last_name = isset($request->last_name) ? substr($request->last_name, 0, 100) : $this->member->last_name;
        $this->member->user_lang = isset($request->user_lang) ? $request->user_lang : $this->member->user_lang;
        $this->member->phone_number = isset($request->phone_number) ? substr($request->phone_number, 0, 20) : $this->member->phone_number;
        if (isset($request->phone_number)) {
            $this->member->phone_number_verified = 1;
        }
        if ($request->gender) {
            $this->member->gender = $request->gender;
        }
        if ($request->photo) {
            $photoURL = $request->file('photo')->store('/public/user/photos', ['visibility' => 'public']);
            if ($this->member->photo && !filter_var($this->member->photo, FILTER_VALIDATE_URL)) {
                Storage::disk()->delete($this->member->photo);
            }
            $this->member->photo = $photoURL;
        }
        $this->member->country_code = $request->country_code ?? $this->member->country_code;
        $this->member->save();
        return $this->member;
    }

    /**
     * @return string[]
     */
    public function reVerifyEmail()
    {
        $this->member->sendEmailVerificationNotification();
        return ['sent' => 'yes'];
    }

    /**
     * @param Request $request
     * @return string[]
     * @throws ValidationException
     */
    public function updatePassword(Request $request)
    {

        Validator::make($request->all(), [
            'current_password' => 'required|min:8',
            'password' => 'required|min:8|different:current_password',
            'password_confirmation' => 'required|same:password',
        ])->validate();

        if (!Hash::check($request->current_password, $this->member->password)) {
            throw ValidationException::withMessages(['current_password' => ['invalid']]);
        }

        $this->member->password = Hash::make($request->password);
        $this->member->save();
        /**  TODO:  Send Notice of password cahnge */
        return ['updated' => 'yes'];

    }

    /**
     * @param Request $request
     * @return string[]
     * @throws ValidationException
     */
    public function updateNewPassword(Request $request)
    {

        Validator::make($request->all(), [
            'current_password' => 'required|min:8',
            'password' => 'required|min:8|different:current_password'
        ])->validate();
        if (!Hash::check($request->current_password, $this->member->password)) {
            throw ValidationException::withMessages(['current_password' => ['invalid']]);
        }
        $this->member->password = Hash::make($request->password);
        $this->member->save();
        return ['updated' => 'yes'];
    }

    /**
     * @param Request $request
     * @return \string[][]
     * @throws ValidationException
     */
    public function checkPassword(Request $request)
    {
        Validator::make($request->all(), [
            'current_password' => 'required|min:8',
        ])->validate();

        if (!Hash::check($request->current_password, $this->member->password)) {
            throw ValidationException::withMessages(['current_password' => ['invalid']]);
        }
        return ['current_password' => ['valid']];
    }

    /**
     * @param Request $request
     * @return Member
     */
    public function updateLocale(Request $request)
    {
        Validator::make($request->all(), [
            'app_lang' => 'required|in:' . config('website.cnf_langs'),
            'app_region' => 'sometimes'
        ])->validate();
        $this->member->app_lang = $request->app_lang;
        $this->member->app_region = $request->app_region ?? 'eg';
        $this->member->region_code = $request->app_region ?? 'eg';
        $this->member->country_code = $request->app_region ?? 'eg';
        $this->member->save();
        return $this->member;
    }

    /**
     * @param Request $request
     * @return string[]
     */
    public function sendOTP(Request $request)
    {
        $phNumber = '+' . ltrim($request->phone_number, '+');
        $request->merge([
            'phone_number' => $phNumber
        ]);
        $countries = Country::where('for_otp', 1)->pluck('valid_prefixes');
        $validPrefixes = [];
        foreach ($countries as $country) {
            $validPrefixes = array_merge_recursive($validPrefixes, json_decode($country));
        }
        Validator::make($request->all(), [
            'phone_number' => 'required|unique:users,phone_number,' . $this->member->user_id . ',user_id|starts_with:' . implode(',', $validPrefixes) . ($this->member->phone_number_verified ? '|not_in:' . $this->member->phone_number : '')
        ])->validate();

        $otp = $request->otp;

        event(new SendOTP($this->member, $phNumber, $otp));

        return ['sent' => 'yes'];
    }

    /**
     * @return Member
     */
    public function getProfile()
    {
        return $this->member;
    }

    /**
     * @param Request $request
     * @param $month_for
     * @return array
     */
    public function getFilterMonths(Request $request, $month_for)
    {
        $function_name = 'get' . $month_for . 'Months';
        $months = [];
        if (method_exists($this->member, $function_name))
            $months = $this->member->$function_name();

        return $months;
    }

    /**
     * @param Request $request
     * @return string[]
     */
    public function closeClaim(Request $request)
    {
        $this->member->claims()->where('id', $request->id)->update(['status' => $request->status]);
        return ['closed' => 'yes'];
    }

    /**
     * @return \Illuminate\Database\Eloquent\Collection
     */
    public function getReferredUsers()
    {

        return $this->member->referred_users()->get();

    }

    /**
     * @return \Illuminate\Database\Eloquent\Collection
     */
    public function getReferarlInvites()
    {
        return $this->member->referral_invites()->orderBy('id', 'DESC')->get();
    }

    /**
     * @param $id
     * @return array
     */
    public function resendPayoutVerification($id)
    {
        $method = $this->member->payout_methods()->find($id);
        if ($method)
            Mail::to($this->member->email)->locale($this->member->user_lang)->queue(new VerifyPayoutEmail($this->member, $method));

        return ['sent' => 'yes', 'id' => $id];

    }

    /**
     * @param Request $request
     * @return string[]
     */
    public function sendReferralEmail(Request $request)
    {

        if (!empty(rtrim($request->emails, ','))) {
            foreach (explode(',', rtrim($request->emails, ',')) as $userEmail) {
                $this->member->referral_invites()->save(new ReferralInvites(['email' => $userEmail]));
                Mail::to($userEmail)->locale($this->member->user_lang)->send(new ReferralInviteEmail($this->member));
            }
            $res = ['sent' => 'yes'];
        } else {
            $res = ['sent' => 'no', 'error' => 'emails list is required'];
        }
        return $res;
    }

    /**
     * @param $value
     * @param $currency
     * @return string
     */
    private function currencyValueFormatted($value, $currency): string
    {
        $value = round($value, 2);
        $formattedValue = "{$value} {$currency->symbol}";
        if ($currency->display_as == 'prefix')
            $formattedValue = "{$currency->symbol} {$value}";
        return $formattedValue;
    }

    /**
     * @return array
     */
    public function getAccountData()
    {

        $userPoints = UserNewBonus::where([['user_id', $this->member->user_id], ['status', 'pending']])->sum('awarded_points');
        $BalanceFormatted = $this->getBalanceFormatted();

        $memberCurrency = $this->member->getUserCurrency();
        $userBalanceAmounts = [
            'balance' => 0,
            'pending' => 0,
            'available' => 0,
            'bonus' => 0
        ];
        $salesCount = 0;
        if (!$this->member->is_merchant) {
            $userBalanceAmounts = $this->member->getWalletBalance();
            $salesCount = $this->member->sales()->count();
        }
        $userBalance = AppDataFormatter::formatBalanceForWalletPage($userBalanceAmounts, $memberCurrency);
        $favoritesCount = $this->member->getFavoriteStoresCount();
        $referBonus = BonusType::where('code', '=', 'refer_bonus')->first();
        $referBonusAmountFormatted = self::currencyValueFormatted($referBonus->amount * $memberCurrency->conversion_rate, $memberCurrency);


        $userBalance["cashback"] = $BalanceFormatted["cashback"]["available"];
        $userBalance["cashback_formatted"] = $BalanceFormatted["cashback"]["available_formatted"];

        $userBalance["reward"] = $BalanceFormatted["reward"]["available"];
        $userBalance["reward_formatted"] = $BalanceFormatted["reward"]["available_formatted"];

        // converting user balance to stars
        $Walletbalance = $this->member->getWalletBalance();
        $UserConvertedBalance = $Walletbalance["balance"] * 1000;
        return [
            'user' => $this->member,
//            'referred_by' => $this->member->referrer_code ? Member::where('referral_code', $this->member->referrer_code)->first() : null,
            'referred_by' => $this->member->referrer_id ? Member::find($this->member->referrer_id) : null,
            'has_favorites_brand' => $this->hasFavoritesObject('brand'),
            'has_payment_info' => $this->HasVerifiedPayoutMethods(),
            'balance' => $userBalance,
            'points' => number_format($UserConvertedBalance, 0, ",", " "),
            'orders_count' => $salesCount,
            'favorites_count' => $favoritesCount,
            'refer_bonus_amount_formatted' => $referBonusAmountFormatted
        ];
    }

    /**
     * @return array
     */
    public function getLoyaltyAchievement()
    {
        $memberCurrency = $this->member->getUserCurrency();

        $now = Carbon::now();
        $period_in_seconds = 7 * 24 * 60 * 60;
        $next_friday = Carbon::createFromTimeStamp(strtotime("next friday"))->endOfDay();
        $interval = $next_friday->diffInSeconds($now);

        $tierCalculator = new TierCalculator();
        $tierData = $tierCalculator->calculateTiers([$this->member->user_id]);

        $tier = null;
        if (isset($tierData[$this->member->user_id]))
            $tier = $tierData[$this->member->user_id];

        if ($tier) {
            if ($tier['next_program']) {
                $tier['next_program']['program']->applyCurrencyConversion($memberCurrency, true);
                $tier['next_program']['program'] = LoyaltyProgram::mapItemsForApp($tier['next_program']['program']);
            }

            if ($tier['current_program']) {
                $tier['current_program']['program']->applyCurrencyConversion($memberCurrency, true);
                $tier['current_program']['program'] = LoyaltyProgram::mapItemsForApp($tier['current_program']['program']);
            }
        }

        $allPrograms = $tierCalculator->loyalty_programs->sortBy('rank')->map(function ($program) use ($memberCurrency) {
            $program->applyCurrencyConversion($memberCurrency, true);
            return LoyaltyProgram::mapItemsForApp($program);
        })->values();

        return [
            'days_left' => $next_friday->diffInDays($now),
            'end_date' => $next_friday->format('d/m/Y'),
            'progress' => round(($period_in_seconds - $interval) / $period_in_seconds * 100, 2),
            'user_programs' => $tier,
            'all_programs' => $allPrograms,
            'terms' => json_decode(config('settingConfig.loyalty_terms_and_conditions'), true)
        ];
    }

    /**
     * @param Request $request
     * @return array
     */
    public function updateUser(Request $request)
    {

        return ['updated' => $this->commonUpdateUser($request), 'user' => $this->member];
    }

    /**
     * @param Request $request
     * @return array
     */
    public function updateVerifiedName(Request $request)
    {
        if (isset($request->verified_name)) {
            $updateUser['verified_name'] = $request->verified_name;
        }

        if (!empty($updateUser)) {
            $updated = $this->member->update($updateUser);
        } else {
            $updated = true;
        }

        return ['updated' => $updated, 'user' => $this->member];
    }

    /**
     * @param Request $request
     * @return mixed
     */
    private function commonUpdateUser(Request $request)
    {
        Validator::make($request->all(), [
            'gender' => 'sometimes|in:Male,Female'
        ])->validate();

        if ($request->country != '') {
            $currency = 'USD';
            $country = Country::where('code', $request->country)->first();
            if ($country) $currency = $country->default_currency;
            $createUser['currency_code'] = $currency;
        }
        if ($request->first_name != '') {
            $createUser['first_name'] = $request->first_name;
        }
        if ($request->last_name != '') {
            $createUser['last_name'] = $request->last_name;
        }
        if ($request->birthdate != '') {
            $createUser['birthdate'] = $request->birthdate;
        }
        if ($request->gender != '') {
            $createUser['gender'] = $request->gender;
        }
        if ($request->app_region != '') {
            $createUser['app_region'] = $request->app_region ?? 'eg';
        }
        if ($request->region_code != '') {
            $createUser['region_code'] = $request->region_code ?? 'eg';
        }
        if ($request->country_code != '') {
            $createUser['country_code'] = $request->country_code ?? 'eg';
        }
        if ($request->app_lang != '') {
            $createUser['app_lang'] = $request->app_lang ?? 'en';
        }
        if ($request->user_lang != '') {
            $createUser['user_lang'] = $request->user_lang ?? 'en';
        }
        if ($request->platform != '') {
            $createUser['platform'] = $request->header('platform') ? $request->header('platform') : 'website';
        }

        if (isset($request->verified_name)) {
            $createUser['verified_name'] = $request->verified_name;
        }

        if (!empty($createUser)) {
            $updated = $this->member->update($createUser);
        } else {
            $updated = true;
        }

        return $updated;
    }

    /**
     * @return bool
     */
    private function HasVerifiedPayoutMethods()
    {
        $user_methods = $this->member->payout_methods()->get();
        if (!$user_methods) {
            $res = false;
        } else {
            $res = true;
        }
        return $res;

    }

    /**
     * @param Request $request
     * @return array
     */
    public function deleteAccount(Request $request)
    {
        DB::table('deleted_users')->insert([
            "user_id" => $this->member->user_id,
            "user_email" => $this->member->email,
            "mobile_number" => $this->member->phone_number,
            "reason" => $request->reason ? $request->reason : 'null',
            "deleted_at" => now()
        ]);
        $this->member->delete();

        return [];
    }

    /**
     * @param Request $request
     * @return array
     */
    public function SendVerifyemailcode(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'email' => 'required|email:rfc,dns'
        ])->validate();
        $email = $request->email;
        $member = Member::where('user_id', $request->user_id)->first();
        if (empty($member->email)) {
            $member->email = $email;
        } else {
            $member->temp_email = $email;
        }
        $member->save();
        $otp = new OtpVerification();
        $otp->user_id = $member->user_id;
        $otp->channel = 'email';
        $otp->type = 'email_confirmation';
        $otp->target = $email;
        $otp->otp = rand(1000, 9999);
        $otp->expired_at = date('Y-m-d H:i:s', strtotime('+1 hour'));
        $otp->save();
        Mail::to($email)->locale($member->user_lang)->queue(new Emailverification($member, $otp));
        return ["message" => "Success mail was sent"];
    }

    /**
     * @param Request $request
     * @return array
     */
    public function Verifyemail(Request $request)
    {
        $otp_codes = [];
        $member = Member::find($request->user_id);
        $otps = OtpVerification::where('user_id', $member->user_id)
            ->where('channel', 'email')
            ->where('type', 'email_confirmation')
            ->orderBy('id', 'DESC')
            ->get();
        if ($otps) {
            foreach ($otps as $otp) {
                array_push($otp_codes, $otp->otp);
                array_push($otp_codes, strrev($otp->otp));
            }
            if (!in_array($request->otp, $otp_codes)) {
                return ["message" => "please Verify the code"];
            } else {
                if ($member->email != $member->temp_email) {
                    $member->email = $member->temp_email;
                    $member->email_verified = 1;
                    $member->save();
                    return ["message" => "Success. Your email is verified now"];
                } else {
                    $member->email_verified = 1;
                    $member->save();
                    return ["message" => "Success. Your email is verified now"];
                }
            }

        } else {
            throw ValidationException::withMessages(["otp" => "The given data was invalid"]);
        }

    }


    /**
     * @param Request $request
     * @return array
     */
    public function getIncompleteOrder(Request $request)
    {
        $user_last_clicks = Click::where('user_id', $request->user_id)->where("display", null)
            ->orderBy('id', 'DESC')
            ->get();
        $store = null;
        if (count($user_last_clicks) > 0) {
            foreach ($user_last_clicks as $user_last_click) {
                if (!Sale::where("click_id", $user_last_click->id)->first()) {
                    $store = Store::find($user_last_click->store_id);
                    break;
                }
            }
            return ["store_info" => $store];
        } else {
            return ["message" => " No data found"];
        }

    }

    /**
     * @param Request $request
     * @return array
     */
    public function HideIncompleteOrder(Request $request)
    {
        $user_last_clicks = Click::where('user_id', $request->user_id)
            ->orderBy('id', 'DESC')
            ->get();

        foreach ($user_last_clicks as $user_last_click) {
            $user_last_click->display = false;
            $user_last_click->save();
        }
        return [true];
    }

    /**
     * @param Request $request
     * @return array
     */
    public function getExtension(Request $request)
    {
        $user = Member::find($request->user_id);
        Mail::to($user->email)->locale($user->user_lang)->send(new ExtensionInstallation($user));
        return ["message" => "Instruction successfully sent"];
    }

    /**
     * @param Request $request
     * @return array
     */
    public function Survey(Request $request)
    {
        $new_data = [];
        $member = $this->member;

        if ($request->gender) {
            $member->gender = $request->gender;
        }

        if ($request->country) {
            $member->country = $request->country;
        }

        if ($request->birth_date) {

            $member->birthdate = date(substr($request->birth_date, 0, 10));
        }

        $member->save();
        // pushing data to array
        if ($request->relationship_status) {
            array_push($new_data, $new_data["relationship_status"] = $request->relationship_status);
        }

        if ($request->industries) {
            array_push($new_data, $new_data["industries"] = $request->industries);

        }
        if ($request->purchasing_decisions) {
            array_push($new_data, $new_data["purchasing_decisions"] = $request->purchasing_decisions);

        }
        if ($request->langs) {
            array_push($new_data, $new_data["languages"] = $request->langs);

        }
        if ($request->number_people_household) {
            array_push($new_data, $new_data["number_people_household"] = $request->number_people_household);

        }
        if ($request->options_household) {
            array_push($new_data, $new_data["options_household"] = $request->options_household);
        }
        if ($request->children) {
            array_push($new_data, $new_data["children"] = $request->children);
        }
        if ($request->shopping_online_last_month) {
            array_push($new_data, $new_data["shopping_online_last_month"] = $request->shopping_online_last_month);
        }
        if ($request->shopping_online_from) {
            array_push($new_data, $new_data["shopping_online_from"] = $request->shopping_online_from);
        }
        if ($request->employment_status) {
            array_push($new_data, $new_data["employment_status"] = $request->employment_status);
        }
        if ($request->organization_primary_industry) {
            array_push($new_data, $new_data["organization_primary_industry"] = $request->organization_primary_industry);
        }
        if ($request->organization_employees) {
            array_push($new_data, json_encode($new_data["organization_employees"] = $request->organization_employees));

        }
        if ($request->job_title) {
            array_push($new_data, $new_data["job_title"] = $request->job_title);
        }
        if ($request->personal_income) {
            array_push($new_data, $new_data["personal_income"] = $request->personal_income);
        }
        if ($request->other_income_sources) {
            array_push($new_data, $new_data["other_income_sources"] = $request->other_income_sources);
        }
        if ($request->education_level) {
            array_push($new_data, $new_data["education_level"] = $request->education_level);
        }

        DB::table('survey')->insert([
            "user_id" => $member->user_id,
            "survey_form" => json_encode($new_data)
        ]);
        //send bonus survey for user
        $bonus = NewBonusType::where('code', 'complete_survey')->first();
        if (is_null($bonus)) return ["message" => "success"];
        $count = UserNewBonus::where([['user_id', $member->user_id], ['bonus_type_id', $bonus->id]])->count();
        if ($count) return ["message" => "success"];
        $user_bonus = new UserNewBonus();
        $user_bonus->user_id = $member->user_id;
        $user_bonus->bonus_type_id = $bonus->id;
        $user_bonus->awarded_points = $bonus->points;
        $user_bonus->awarded_on = now();
        $user_bonus->save();
        event(new NewBonusNew($member, $bonus));
        return ["message" => "success"];
    }

}
