<?php

namespace Yajny\Controller;

use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;
use Yajny\Models\Store;
use Yajny\Models\StoreCashback;
use Yajny\Models\StoreCategories;
use Yajny\Models\TopPicks;


class StoreCtrl extends Controller
{
    /**
     * @param $store_id
     * @return mixed
     */
    public static function getInfo($store_id)
    {
        return Store::where('id', $store_id)->orWhere('slug', $store_id)->with(['store_cashback' => function ($q) {
            return $q->selectRaw(StoreCashback::colSelect());
        }])->selectRaw(Store::apiColSelect())->first();
    }

    /**
     * @param $storeIds
     * @param null $limit
     * @return \Illuminate\Support\Collection
     */
    public static function getStoresById($storeIds, $limit = null)
    {
        if (count($storeIds) == 0) return collect([]);
        $storesQuery = Store::selectRaw(Store::colSelect())
            ->addSelect('clicks')
            ->withCount('store_coupons')
            ->whereIn('id', $storeIds);
        $storesQuery->orderByRaw('FIELD(id,' . implode(',', $storeIds) . ')');
        self::applyRegions($storesQuery);

        if ($limit && is_integer($limit))
            $storesQuery->take($limit);

        return $storesQuery->get();
    }

    /**
     * @param $storeIds
     * @param null $limit
     * @return \Illuminate\Support\Collection
     */
    public static function getStoresByIdwithoutRegion($storeIds, $limit = null)
    {
        if (count($storeIds) == 0) return collect([]);
        $storesQuery = Store::selectRaw(Store::colSelect())
            ->addSelect('clicks')
            ->withCount('store_coupons')
            ->whereIn('id', $storeIds);
        $storesQuery->orderByRaw('FIELD(id,' . implode(',', $storeIds) . ')');

        if ($limit && is_integer($limit))
            $storesQuery->take($limit);

        return $storesQuery->get();
    }

    /**
     * @return \Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection|TopPicks[]
     */
    public static function getpickedStores()
    {
        $regionCode = request('region');
        $topPicksQuery = TopPicks::with('stores')->orderBy('sort_order')->where('is_shown', 1);
        if ($regionCode) {
            $topPicksQuery = $topPicksQuery->whereHas('stores', function ($query) use ($regionCode) {
                $query->whereJsonContains('region_code', $regionCode);
            });
        }
        return $topPicksQuery->get();
    }

    /**
     * @param int $limit
     * @return mixed
     */
    public static function getRecentStores($limit = 4)
    {
        $storesQuery = Store::selectRaw(Store::colSelect())
            ->withCount('store_coupons')
            ->addSelect('clicks')
            ->where('stores.status', 'publish')
            ->orderBy('name', 'DESC')
            ->orderBy('created_at', 'DESC')->limit($limit);
        self::applyRegions($storesQuery);

        return $storesQuery->get()->filter(function ($store) {
            return $store->store_coupons_count > 0 || $store->cb_status == 1;
        })->values();
    }
    /**
     * @param int $limit
     * @return mixed
     */
    public static function getRecentStoreswithoutlimit($limit = 4)
    {
        $storesQuery = Store::selectRaw(Store::colSelect())
            ->withCount('store_coupons')
            ->addSelect('clicks')
            ->where('stores.status', 'publish')
            ->orderBy('created_at', 'DESC')
            ->limit($limit);
        self::applyRegions($storesQuery);

        return $storesQuery->get()->filter(function ($store) {
            return $store->store_coupons_count > 0 || $store->cb_status == 1;
        })->values();
    }
     /**
     * @param int $limit
     * @return mixed
     */
    public static function getRecentStoreswithoutRegion($limit = 4)
    {
        $storesQuery = Store::selectRaw(Store::colSelect())
            ->withCount('store_coupons')
            ->addSelect('clicks')
            ->where('stores.status', 'publish')
            ->orderBy('name', 'DESC')
            ->orderBy('created_at', 'DESC')->limit($limit);

        return $storesQuery->get()->filter(function ($store) {
            return $store->store_coupons_count > 0 || $store->cb_status == 1;
        })->values();
    }


    /**
     * @return mixed
     */
    public static function getStores()
    {
        $storesQuery = Store::selectRaw(Store::colSelect())
            ->withCount('store_coupons')
            ->addSelect('clicks')
            ->orderBy('name');

        self::applyRegions($storesQuery);

        return $storesQuery->get()->filter(function ($store) {
            return $store->store_coupons_count > 0 || $store->cb_status == 1;
        })->values();
    }
    public static function getStoreswithoutRegion()
    {
        $storesQuery = Store::selectRaw(Store::colSelect())
            ->withCount('store_coupons')
            ->addSelect('clicks')
            ->orderBy('name');


        return $storesQuery->get()->filter(function ($store) {
            return $store->store_coupons_count > 0 || $store->cb_status == 1;
        })->values();
    }

    /**
     * @param null $userID
     * @param int $limit
     * @return mixed
     */
    public static function getTopStores($userID = null, $limit = 12)
    {
        $selectCols = explode(',', Store::colSelect());
        $storesQuery = Store::selectRaw('stores.' . implode(',stores.', $selectCols))
            ->where('cb_status', 1);

        if ($userID)
            $storesQuery->leftJoin('user_store_click_count', function ($query) use ($userID) {
                $query->on('user_store_click_count.store_id', 'stores.id');
                $query->where('user_store_click_count.user_id', $userID);
            })
                ->addSelect('user_store_click_count.click_count')
                ->orderByDesc('user_store_click_count.click_count');

        $storesQuery->orderByDesc('stores.clicks')->limit($limit);
        self::applyRegions($storesQuery);
        return $storesQuery->get();
    }

     /**
     * @param null $userID
     * @param int $limit
     * @return mixed
     */
    public static function getTopStoreswithoutRegion($userID = null, $limit = 12)
    {
        $selectCols = explode(',', Store::colSelect());
        $storesQuery = Store::selectRaw('stores.' . implode(',stores.', $selectCols))
            ->where('cb_status', 1);

        if ($userID)
            $storesQuery->leftJoin('user_store_click_count', function ($query) use ($userID) {
                $query->on('user_store_click_count.store_id', 'stores.id');
                $query->where('user_store_click_count.user_id', $userID);
            })
                ->addSelect('user_store_click_count.click_count')
                ->orderByDesc('user_store_click_count.click_count');

        $storesQuery->orderByDesc('stores.clicks')->limit($limit);
        return $storesQuery->get();
    }

    /**
     * @param null $userID
     * @param int $limit
     * @return mixed
     */
    public static function getFeaturedStores($userID = null, $limit = 12)
    {
        $selectCols = explode(',', Store::colSelect());
        $storesQuery = Store::selectRaw('stores.' . implode(',stores.', $selectCols))
            ->where('cb_status', 1)
            ->where('is_featured', 1);

        if ($userID)
            $storesQuery->leftJoin('user_store_click_count', function ($query) use ($userID) {
                $query->on('user_store_click_count.store_id', 'stores.id');
                $query->where('user_store_click_count.user_id', $userID);
            })
                ->addSelect('user_store_click_count.click_count')
                ->orderByDesc('user_store_click_count.click_count');

        $storesQuery->orderByDesc('stores.clicks')->limit($limit);
        self::applyRegions($storesQuery);
        return $storesQuery->get();
    }

    /**
     * @param null $userID
     * @param int $limit
     * @return mixed
     */
    public static function getTopStoresByCashback($userID = null, $limit = 12)
    {

        $selectCols = explode(',', Store::colSelect());
        $storesQuery = Store::selectRaw('stores.' . implode(',stores.', $selectCols))
            ->addSelect('stores.clicks')
            ->where('cb_status', 1)
            ->where('stores.status', 'publish');

        if ($userID)
            $storesQuery->leftJoin('user_store_click_count', function ($query) use ($userID) {
                $query->on('user_store_click_count.store_id', 'stores.id');
                $query->where('user_store_click_count.user_id', $userID);
            });

        $storesQuery->orderByDesc('stores.clicks')->limit($limit);
        self::applyRegions($storesQuery);
        return $storesQuery->get();
    }
    

    /**
     * @param null $userID
     * @param int $limit
     * @return mixed
     */
    public static function getTopStoresByCashbackwithoutRegion($userID = null, $limit = 12)
    {

        $selectCols = explode(',', Store::colSelect());
        $storesQuery = Store::selectRaw('stores.' . implode(',stores.', $selectCols))
            ->addSelect('stores.clicks')
            ->where('cb_status', 1)
            ->where('stores.status', 'publish');

        if ($userID)
            $storesQuery->leftJoin('user_store_click_count', function ($query) use ($userID) {
                $query->on('user_store_click_count.store_id', 'stores.id');
                $query->where('user_store_click_count.user_id', $userID);
            });
            
        $storesQuery->orderByDesc('stores.clicks')->limit($limit);
        return $storesQuery->get();
    }


    /**
     * @param $storeIds
     * @param null $limit
     * @return \Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection|\Illuminate\Database\Query\Builder[]|\Illuminate\Support\Collection|Store[]
     */
    public static function getStoresWithCategoriesByID($storeIds, $limit = null)
    {
        if (count($storeIds) == 0) return collect([]);
        $storesQuery = Store::with([
            'store_cashback' => function ($q) {
                $q->selectRaw(StoreCashback::colSelect());
                $q->orderByRaw('rate_amount DESC');
                return $q;
            }
        ])
            ->selectRaw(Store::colSelect())
            ->addSelect('clicks')
            ->whereIn('id', $storeIds);
        $storesQuery->orderByRaw('FIELD(id,' . implode(',', $storeIds) . ')');
        self::applyRegions($storesQuery);

        if ($limit && is_integer($limit))
            $storesQuery->take($limit);

        return $storesQuery->get();
    }

    /**
     * @return mixed
     */
    public static function getAllStores()
    {
        $storesQuery = Store::withoutGlobalScopes()
            ->select(['stores.*', DB::raw('count(c.id) as coupons_count')])
            ->leftJoin('coupons AS c', function ($query) {
                $query->on('c.store_id', 'stores.id')
                    ->where('c.type', 'coupon')
                    ->where('c.status', 'publish')
                    ->whereRaw(' IFNULL(c.expiry_date,CURRENT_DATE) >= CURRENT_DATE ');
            })
            ->where('stores.status', 'publish')
            ->groupBy('stores.id')
            ->orderByDesc('coupons_count');
            self::applyRegions($storesQuery,'stores.region_code',true);
        return $storesQuery->get();
    }
    /**
     * @return mixed
     */
    public static function getAllStoreswithoutRegion()
    {
        $storesQuery = Store::withoutGlobalScopes()
            ->select(['stores.*', DB::raw('count(c.id) as coupons_count')])
            ->leftJoin('coupons AS c', function ($query) {
                $query->on('c.store_id', 'stores.id')
                    ->where('c.type', 'coupon')
                    ->where('c.status', 'publish')
                    ->whereRaw(' IFNULL(c.expiry_date,CURRENT_DATE) >= CURRENT_DATE ');
            })
            ->where('stores.status', 'publish')
            ->groupBy('stores.id')
            ->orderByDesc('coupons_count');
        return $storesQuery->get();
    }
    /**
     * @return mixed
     */
    public static function getStoresWithCoupons()
    {
        $storesQuery = Store::withoutGlobalScopes()
            ->select(['stores.*', DB::raw('count(c.id) as coupons_count')])
            ->leftJoin('coupons AS c', function ($query) {
                $query->on('c.store_id', 'stores.id')
                    ->where('c.type', 'coupon')
                    ->where('c.status', 'publish')
                    ->whereRaw(' IFNULL(c.expiry_date,CURRENT_DATE) >= CURRENT_DATE ');
            })
            ->where('stores.status', 'publish')
            ->groupBy('stores.id')
            ->orderByDesc('coupons_count')
            ->having('coupons_count', '>', 0);
        self::applyRegions($storesQuery, 'stores.region_code', false);
        return $storesQuery->get();
    }

    /**
     * @param false $keyword
     * @return mixed
     */
    public static function getCashbackStores($keyword = false)
    {
        if ($keyword) $keyWhere = "name LIKE '%{$keyword}%'"; else $keyWhere = " 1 =1 ";
        return Store::selectRaw(Store::colSelect())->WhereRaw($keyWhere)->where('cb_status', 1)->orderBy('name')->limit(5)->get();
    }

    /**
     * @param $storeIds
     * @return mixed
     */
    public static function getStoresByIdWithCategory($storeIds)
    {
        $storesQuery = Store::selectRaw(Store::colSelect())
            ->whereIn('id', $storeIds)
            ->withCount('store_coupons');
        return $storesQuery->get();
    }

    /**
     * @param $storeIds
     * @return mixed
     */
    public static function getStoresByIdWithCategoryAndRegion($storeIds, $field = "region_code", $regionCode, $randomOnGlobal = false)
    {
        $storesQuery = Store::selectRaw(Store::colSelect())
            ->whereIn('id', $storeIds)
            ->withCount('store_coupons');
        if ($regionCode) {
            $storesQuery->whereJsonContains("{$field}", $regionCode ?? 'global');
            $storesQuery->orderByRaw("JSON_LENGTH({$field})");
        } elseif ($randomOnGlobal) {
            $storesQuery->inRandomOrder();
        }
        return $storesQuery->get();
    }


    /**
     * @param $store_id
     * @return \Illuminate\Support\Collection
     */
    public static function store_cashback($store_id)
    {
        return DB::table('store_cashback')
            ->where('store_id', $store_id)->where('enabled', 'Y')->get();
    }

    /** Get Strores for Slider **/
    public static function getStoresByCategory($cat_id)
    {
        $cat_id = $cat_id . ',"' . $cat_id . '"';
        $storesQuery = Store::whereRaw("JSON_OVERLAPS(categories,'[" . $cat_id . "]')")->selectRaw(Store::colSelect())->orderBy('name_lang', 'ASC');
        $storesQuery->paginate(10);
        self::applyRegions($storesQuery);
        return $storesQuery->get();
    }

    /**
     * @param $user_id
     * @return \Illuminate\Support\Collection
     */
    public static function getAllFavorateOffers($user_id)
    {
        return DB::table('user_favs')
            ->join('coupons', 'user_favs.object_id', 'coupons.id')
            ->join('stores', 'coupons.store_id', 'stores.id')
            ->where('user_favs.user_id', $user_id)
            ->get();
    }

    /**
     * @param $cats
     * @return mixed
     */
    public static function getStoreCatsById($cats)
    {
        return StoreCategories::whereIn('id', $cats);
    }

    /**
     * @param $storesQuery
     * @param string $field
     * @param bool $randomOnGlobal
     */
    private static function applyRegions(&$storesQuery, $field = 'region_code', $randomOnGlobal = true)
    {
        $regionCode = request('region')??request()->headers->get('region');

        if ($regionCode && $regionCode!='global') {
            $storesQuery->whereJsonContains("{$field}", $regionCode);
            $storesQuery->orderByRaw("JSON_LENGTH({$field})");
        } elseif ($randomOnGlobal) {
            $storesQuery->inRandomOrder();
        }
    }
}
