<?php

namespace App\Domain\Feeds\Queries;

use App\Domain\Feeds\Models\Feed;
use App\Domain\Feeds\Enums\StatusEnum;
use Illuminate\Database\Eloquent\Builder;
use App\Domain\Feeds\DataTransferObjects\FeedData;
use App\Domain\Subscriptions\Service\SubscriptionService;

class FeedQueryBuilder
{
    const PAGINATION_COUNT = 10;

    public $feed;
    public $pagination = true;
    public $onlyActiveFeed = true;
    public $nextCursor;
    public $is_ads = false;
    public $hasPages;

    public function __construct($query = null)
    {
        if($query){
            $this->feed = $query;
        }else{
            $this->feed = Feed::query();
        }

    }
    public function enableAdvertising()
    {
        $this->is_ads = true;
        return $this;
    }

    public function search($filters)
    {
        $this->feed->when($filters['search'] ?? null, function ($query, $search) {
            $query->where(function ($query) use ($search) {
                $query->where('title', 'ilike', '%'.$search.'%')
                    ->orWhere('body', 'ilike', '%'.$search.'%');
            });
        });
        return $this;
    }

    public function addTags($tags)
    {
        $this->feed->whereHas('tags', function (Builder $query) use($tags) {
            $query->whereIn('id', $tags);
        });
        return $this;
    }

    public function addType($type)
    {
        if($type == 'image'){
            //$this->feed->whereHasMorph('feedable', [Image::class]);
            $this->feed->where('type', 'images');
        }
        if($type == 'video'){
           // $this->feed->whereHasMorph('feedable', [Video::class]);
            $this->feed->where('type', 'videos');
        }
        if($type == 'music'){
            //$this->feed->whereHasMorph('feedable', [Music::class]);
            $this->feed->where('type', 'musics');
        }
        return $this;
    }

    public function filter($filter = null)
    {
        if($filter === 'hot'){
            return $this->order('likes_count');
        }
        return $this->order();
    }

    public function order($by = null)
    {
        if($by){
            $this->feed->orderBy($by, 'desc');
        }else{
            $this->feed->orderBy('id', 'desc');
        }
        return $this;

    }

    public function selectBy($where, $by)
    {
        $this->feed->where($where, $by);
        return $this;
    }

    public function selectByIds($ids)
    {
        if(is_array($ids)){
            $this->feed->whereIn('id', $ids);
        }else{
            $this->feed->where('id', $ids);
        }
        return $this;
    }

    public function withTrashed() {
        $this->feed->withTrashed();
        return $this;
    }

    public function disableActiveFeed()
    {
        $this->onlyActiveFeed = false;
        return $this;
    }

    public function disablePaginate()
    {
        $this->pagination = false;
        return $this;
    }

    public function getData()
    {
        if($this->onlyActiveFeed){
            $this->feed = $this->feed->where('status', StatusEnum::APPROVED());
        }
        $this->feed = $this->feed->withCount([
            'comments',
            'likes',
        ]);

        if(auth()->user()){
            $this->feed = $this->feed
            ->withCount(['likes as liked' => function (Builder $query)  {
                $query->where('user_id', auth()->user()->id);
            }])
            ->withCasts(['liked' => 'boolean']);
        }
        if($this->pagination){
            $this->feed = $this->feed->cursorPaginate(self::PAGINATION_COUNT);
            $this->getCursorHash();
        }else{
            $this->feed = $this->feed->get();
        }

        return $this;
    }

    protected function getCursorHash()
    {
        $this->hasPages = $this->feed->hasMorePages();
        $this->nextCursor = get_cursor_hash($this->feed);
    }

    public function withTags()
    {
        $this->feed->with('tags:id,name,slug');
        return $this;
    }

    public function withUser()
    {
        $this->feed->with('user:id,first_name,last_name,username,photo_path,color,user_char,private');
        return $this;
    }

    public function withFeedable()
    {

        // $this->feed->with('media');
        // :id,model_type,model_id,name,file_name,collection_name,custom_properties

        if(auth()->user()){
            $this->feed->withCount('media')
            ->with(['media' => function($query){
                // withCount('likes')->withCasts(['likes_count' => 'boolean']);
                $query->withCount(['likes' => function (Builder $query)  {
                    $query->where('user_id', auth()->user()->id);
                }])->withCasts(['likes_count' => 'boolean']);
            }]);
        }else{
            $this->feed->with('media');
        }


        return $this;

        // $this->feed->with('feedable', function (MorphTo $morphTo) {
        //     $morphTo->morphWith([
        //         Image::class => ['media'],
        //         Video::class => ['media'],
        //         Music::class => ['media'],
        //     ]);
        // });
        // return $this;
    }

    public function transformData()
    {
        $feed_collect = collect();

        if(auth()->user()){
            $purchased_subscriptions_by_users = \DB::table('users_package_customers')
            ->where('customer_id', auth()->user()->id)
            ->where('time_end', '>', now())
            ->pluck('user_id')->toArray();
        }else{
            $purchased_subscriptions_by_users = [];
        }

        foreach ($this->feed as $feed) {
            $feed = FeedData::fromDataBaseWithUser($feed, $purchased_subscriptions_by_users);
            if($feed['entity']){
                $feed['entity']->tags->transform(function ($item) {
                    return [
                        'id' => $item->id,
                        'name' => $item->name,
                        'slug' => $item->slug,
                    ];
                });
            }

            $feed_collect[] = $feed;
        }

        if(auth()->check()){
            $subscription_purchased = SubscriptionService::activeSubscription();
            if($subscription_purchased == false){
                $adsMedia = Feed::where('is_ads', true)->with('media')->inRandomOrder()->first();
                if($adsMedia && $this->is_ads){
                    $adsMediaData = FeedData::fromAds($adsMedia);
                    $feed_collect->splice(4, 0, [$adsMediaData]);
                }
            }
        }
        return $feed_collect;
    }

    public function build()
    {
        $this
            ->withFeedable()
            ->withUser()
            ->withTags()
            ->getData();
        return $this;
    }

    public function transformGet()
    {

        return $this
            ->withFeedable()
            ->withUser()
            ->withTags()
            ->getData()->transformData();
    }

}
