<?php

namespace Yajny\Controller;

use App\Http\Controllers\Controller;
use Yajny\Models\Store;
use Yajny\Models\Coupon;

class CouponCtrl extends Controller
{
    /**
     * @param null $type
     * @param int $cat_id
     * @return mixed
     */
    public static function getHomeFeaturedCouponsByType($type = null, $cat_id = 0)
    {
        $query = Coupon::with(['couponStore' => function ($q) {
            $q->selectRaw(Store::colSelect());
        }])
            ->where('status', 'publish')
            ->where('is_featured', 1)
            ->orderBy('updated_at','DESC')
            ->limit(20)
        ;

        if ($type)
            $query->where('type', $type);

        if ($cat_id > 0)
            self::applyConditions($query, [], [$cat_id], [], []);

        self::applyRegions($query);
        return $query->get();
    }

    /**
     * @param null $type
     * @param int $cat_id
     * @return mixed
     */
    public static function getHomeRecommendedCouponsByType($type = null, $cat_id = 0)
    {
        $query = Coupon::with(['couponStore' => function ($q) {
            $q->selectRaw(Store::colSelect());
        }])
            ->where('status', 'publish')
            ->where('is_recommended', 1)
            ->orderBy('updated_at','DESC')
            ->limit(20)
        ;

        if ($type)
            $query->where('type', $type);

        if ($cat_id > 0)
            self::applyConditions($query, [], [$cat_id], [], []);

        self::applyRegions($query);
        return $query->get();
    }

    /**
     * @param $type
     * @param $regionCode
     * @param $limit
     * @param null $storeIDs
     * @param null $userID
     * @param false $forApp
     * @return mixed
     */
    public static function getUserRecommendedCouponsByType($type, $regionCode, $limit, $storeIDs = null, $userID = null, $forApp = false)
    {
        if ($storeIDs === null) {
            $stores = StoreCtrl::getTopStores($userID, $limit);
            $storeIDs = $stores->pluck('id');
        }
        $query = Coupon::with([
            'couponStore' => function ($q) {
                $q->selectRaw(Store::colSelect());
            }
        ])
            ->where('type', $type);
        if ($type == 'offer')
            $query->where('is_recommended', 1);
        if ($forApp)
            $query;
        if ($storeIDs)
            $query->orderByRaw('FIELD (store_id, "' . $storeIDs->reverse()->implode('id', '","') . '") DESC' );
        $query->orderByDesc('clicks');
        if ($regionCode && $regionCode!='global')
            $query->whereJsonContains('region_code', $regionCode);
        $coupons = $query->get();
        $couponsGrouped = $coupons->groupBy('store_id');
        foreach ($couponsGrouped as $key => $groupedCoupons) {
            $couponsGrouped[$key] = $groupedCoupons->take(2);
        }
        return $couponsGrouped->flatten()->take($limit)->sortByDesc('clicks');
    }

    /**
     * @param null $type
     * @param int $tag_id
     * @return mixed
     */
    public static function getCouponsByTag($type = null, $tag_id = 0)
    {
        $query = Coupon::with(['couponStore' => function ($q) {
            $q->selectRaw(Store::colSelect());
        }])
            ->where('status', 'publish')
            ->orderBy('updated_at','DESC')
            ->limit(20)
        ;

        if ($type)
            $query->where('type', $type);

        if ($tag_id > 0)
            self::applyConditions($query, [], [], [], [$tag_id]);

        self::applyRegions($query);
        return $query->get();
    }

    /**
     * @param null $type
     * @param int $cat_id
     * @return mixed
     */
    public static function getCouponsByType($type = null, $cat_id = 0)
    {
        $query = Coupon::with(['couponStore' => function ($q) {
            $q->selectRaw(Store::colSelect());
        }])
            ->where('status', 'publish')
            ->orderBy('clicks', 'DESC')
            ->limit(20)
        ;

        if ($type)
            $query->where('type', $type);

        if ($cat_id > 0)
            self::applyConditions($query, [], [$cat_id], [], []);

        self::applyRegions($query);
        return $query->get();
    }

    /**
     * @param null $type
     * @param int $cat_id
     * @param null $limit
     * @param int $page
     * @return \Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection|\Illuminate\Database\Query\Builder[]|\Illuminate\Support\Collection|Coupon[]
     */
    public static function listCouponsByType($type = null, $cat_id = 0,$limit=null, $page=1)
    {

        $query = Coupon::with(['couponStore' => function ($q) {
            $q->selectRaw(Store::colSelect());
        }])
            ->where('status', 'publish')
            ->orderBy('clicks', 'DESC')
        ;

        if ($type)
            $query->where('type', $type);

        if ($cat_id > 0)
            self::applyConditions($query, [], [$cat_id], [], []);

        if($limit && $page!='all')
            $query->limit($limit)->offset(($page - 1) * $limit);

        self::applyRegions($query);

        return $query->get();

    }

    /**
     * @param null $type
     * @return mixed
     */
    public static function getAppCouponsByTypewithPagination($type = null)
    {
        $query = Coupon::with(['couponStore' => function ($q) {
            $q->selectRaw(Store::colSelect());
        }])
            ->where('status', 'publish')
            ->orderBy('clicks', 'DESC')
            ->limit(25)
        ;

        if ($type)
            $query->where('type', $type)
                ->paginate(10);

        self::applyRegions($query);
        return $query->get();
    }
    public static function getAppCouponsByTypewithPaginationwithoutRegion($type = null)
    {
        $query = Coupon::with(['couponStore' => function ($q) {
            $q->selectRaw(Store::colSelect());
        }])
            ->where('status', 'publish')
            ->orderBy('clicks', 'DESC')
            ->limit(25)
        ;

        if ($type)
            $query->where('type', $type)
                ->paginate(10);

        return $query->get();
    }
    /**
     * @param null $type
     * @return mixed
     */
    public static function getAppCouponsByType($type = null)
    {
        $query = Coupon::with(['couponStore' => function ($q) {
            $q->selectRaw(Store::colSelect());
        }])
            ->where('status', 'publish')
            ->orderBy('clicks', 'DESC')
            ->limit(25)
        ;

        if ($type)
            $query->where('type', $type)
                ->paginate(10);

        self::applyRegions($query);
        return $query->get();
    }

    /**
     * @param null $type
     * @param int $limit
     * @return mixed
     */
    public static function getRecentCouponsByType($type = null, $limit = 25)
    {
        $query = Coupon::with(['couponStore' => function ($q) {
            $q->selectRaw(Store::colSelect());
        }])
            ->where('status', 'publish')
            ->orderBy('id', 'DESC');

        if ($type)
            $query->where('type', $type);

        self::applyRegions($query);
        return $query->get();
    }
    /**
     * @param null $type
     * @param int $limit
     * @return mixed
     */
    public static function getRecentCouponsByTypewithpagination($type = null, $limit = 25)
    {
        $query = Coupon::with(['couponStore' => function ($q) {
            $q->selectRaw(Store::colSelect());
        }])
            ->where('status', 'publish')
            ->orderBy('id', 'DESC')
        ;

        if ($type)
            $query->where('type', $type)
                ->paginate(10);

        self::applyRegions($query);
        return $query->get();
    }

    /**
     * @param null $type
     * @param int $cat_id
     * @return mixed
     */
    public static function getTopCouponsByType($type = null, $cat_id = 0)
    {
        $query = Coupon::with(['couponStore' => function ($q) {
            $q->selectRaw(Store::colSelect());
        }])
            ->where('status', 'publish')
            ->orderBy('clicks', 'DESC')
            ->limit(25)
        ;

        if ($type)
            $query->where('type', $type);

        if ($cat_id > 0)
            self::applyConditions($query, [], [$cat_id], [], []);

        self::applyRegions($query);
        return $query->get();
    }

    /**
     * @param int $cat_id
     * @return mixed
     */
    public static function getHomepageCoupons($cat_id = 0)
    {
        return self::getCouponsByType('offer', $cat_id);
    }

    /**
     * @return mixed
     */
    public static function getFeaturedDeals(){
        $query = Coupon::with(['couponStore' => function($q) {
            $q->selectRaw(Store::colSelect());
        }] )
            ->where('is_featured',1)
            ->where('status', 'publish')->limit(5)
            ->orderBy('updated_at','DESC');
        self::applyRegions($query);
        return $query->get();
    }

    /**
     * @param array $stores
     * @param array $cats
     * @param array $brands
     * @param array $tags
     * @param array $type
     * @param int $limit
     * @param int $page
     * @return mixed
     */
    public static function filterCoupon($stores = [], $cats = [], $brands = [], $tags = [], $type = [], $limit = 30, $page = 1)
    {
        $couponQry = Coupon::with(['couponStore' => function ($q) { $q->selectRaw(\Yajny\Models\Store::colSelect()); }]  );

        // if coupon/offer type filter applied
        if ($type && $type != 'all')
        {
            if($type=='coupon')
                $couponQry->whereNotNull('code');
            else
                $couponQry->whereNull('code');
        }

        self::applyConditions($couponQry, $stores, $cats, $brands, $tags);

        $couponQry->limit($limit)->offset(($page - 1) * $limit);

        $couponQry->selectRaw( Coupon::colSelect() );

        self::applyRegions($couponQry);

        return  $couponQry->get();
    }

    /**
     * @param array $stores
     * @param array $cats
     * @param array $brands
     * @param array $tags
     * @return mixed
     */
    public static function buildFilterArray($stores = [], $cats = [], $brands = [], $tags = [])
    {
        $couponQry = Coupon::selectRaw('JSON_ARRAYAGG(brands) brands, JSON_ARRAYAGG(tags) tags, JSON_ARRAYAGG(cats) cats, GROUP_CONCAT(store_id) stores, COUNT(*) as offers_count');

        self::applyConditions($couponQry, $stores, $cats, $brands, $tags);

        self::applyRegions($couponQry);

        return $couponQry->first();

    }

    /**
     * @param $couponQry
     * @param string $field
     */
    public static function applyRegions(&$couponQry, $field = 'region_code') {

        $regionCode =request()->headers->get('region') ?? request('region');

        if ($regionCode && $regionCode!='global') {
            $couponQry->whereJsonContains("{$field}", $regionCode);
        }
    }

    /**
     * @param $couponQry
     * @param $stores
     * @param $cats
     * @param $brands
     * @param $tags
     */
    private static function applyConditions(&$couponQry, $stores, $cats, $brands, $tags)
    {
        if (count($stores) > 0)
            $couponQry->whereIn('store_id', $stores);

        if (count($cats) > 0)
            $couponQry->whereRaw("  JSON_OVERLAPS(cats,'[" . implode(',', $cats) . ",\"" . implode('","', $cats) . "\"]')");

        if (count($brands) > 0)
            $couponQry->whereRaw("  JSON_OVERLAPS(brands,'[" . implode(',', $brands) . ",\"" . implode('","', $brands) . "\"]')");

        if (count($tags) > 0)
            $couponQry->whereRaw("  JSON_OVERLAPS(tags,'[" . implode(',', $tags) . ",\"" . implode('","', $tags) . "\"]')");
    }

    /**
     * @param $user_id
     * @param $limit
     * @param string $type
     * @return mixed
     */
    public static function getTopCoupons($user_id, $limit, $type = "coupon")
    {
        $query = Coupon::with(['couponStore' => function ($q) {
            $q->selectRaw(Store::colSelect());
        }])
            ->where('status', 'publish')
            ->orderBy('clicks', 'DESC')
            ->limit($limit)
        ;

        if ($type)
            $query->where('type', $type);

        self::applyConditions($query, [], [], [], []);

        self::applyRegions($query);
        return $query->get();
    }

    /**
     * @param $user_id
     * @param $limit
     * @param string $type
     * @return mixed
     */
    public static function getTopCouponswithoutRegion($user_id, $limit, $type = "coupon")
    {
        $query = Coupon::with(['couponStore' => function ($q) {
            $q->selectRaw(Store::colSelect());
        }])
            ->where('status', 'publish')
            ->orderBy('clicks', 'DESC')
            ->limit($limit)
        ;

        if ($type)
            $query->where('type', $type);

        self::applyConditions($query, [], [], [], []);

        return $query->get();
    }
    /**
     * @param $stores
     * @param int $limit
     * @param string $type
     * @return mixed
     */
    public static function getLastCouponsByFavObject($stores, $limit = 8, $type = "")
    {
        $query = Coupon::with(['couponStore' => function ($q) {
            $q->selectRaw(Store::colSelect());
        }])
            ->where('status', 'publish')
            ->orderBy('updated_at', 'DESC')
        ;
        if ($type)
            $query->where('type', $type);


        self::applyConditions($query, $stores, [], [], []);

        self::applyRegions($query);

        if ($limit)
            $query->limit($limit);
        return $query->get();
    }
    public static function getLastCouponsByFavObjectwithoutRegion($stores, $limit = 8, $type = "")
    {
        $query = Coupon::with(['couponStore' => function ($q) {
            $q->selectRaw(Store::colSelect());
        }])
            ->where('status', 'publish')
            ->orderBy('updated_at', 'DESC')
        ;
        if ($type)
            $query->where('type', $type);


        self::applyConditions($query, $stores, [], [], []);


        if ($limit)
            $query->limit($limit);
        return $query->get();
    }


    /**
     * @param $user_id
     * @param $limit
     * @param $type
     * @return mixed
     */
    public static function getRecentlyAddCoupons($user_id, $limit , $type){
        $query = Coupon::with(['couponStore' => function ($q) {
            $q->selectRaw(Store::colSelect());
        }])
            ->where('status', 'publish')
            ->orderBy('id', 'DESC')
        ;

        if ($limit)
            $query->limit($limit);

        if ($type)
            $query->where('type', $type);

        self::applyRegions($query);
        return $query->get();
    }
    public static function getRecentlyAddCouponswithoutRegion($user_id, $limit , $type){
        $query = Coupon::with(['couponStore' => function ($q) {
            $q->selectRaw(Store::colSelect());
        }])
            ->where('status', 'publish')
            ->orderBy('id', 'DESC')
        ;

        if ($limit)
            $query->limit($limit);

        if ($type)
            $query->where('type', $type);

        return $query->get();
    }

    /**
     * @param $user_id
     * @param $limit
     * @param $type
     * @return mixed
     */
    public static function getExclusiveCoupons($user_id, $limit , $type){
        $query = Coupon::with(['couponStore' => function ($q) {
            $q->selectRaw(Store::colSelect());
        }])
            ->where('status', 'publish')
            ->where('is_exclusive', 1)
            ->orderBy('updated_at','DESC')
            ->limit($limit)
        ;

        if ($type)
            $query->where('type', $type);


        self::applyConditions($query, [], [], [], []);

        self::applyRegions($query);
        return $query->get();
    }
    public static function getExclusiveCouponswithoutRegion($user_id, $limit , $type){
        $query = Coupon::with(['couponStore' => function ($q) {
            $q->selectRaw(Store::colSelect());
        }])
            ->where('status', 'publish')
            ->where('is_exclusive', 1)
            ->orderBy('updated_at','DESC')
            ->limit($limit)
        ;

        if ($type)
            $query->where('type', $type);


        self::applyConditions($query, [], [], [], []);

        return $query->get();
    }
}
