<?php

namespace App\Repos;

use App\Models\Page;
use Illuminate\Contracts\Database\Eloquent\Builder;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;

class PageRepo
{
    public static function read(int $id)
    {
        return Page::with('colored')
            ->findOrFail($id)
            ->setAppends([
                'is_colored',
                'is_owner'
            ]);
    }

    public static function create(array $user)
    {
        return Page::create($user);
    }

    public static function paginate(
        int $page,
        string|null $search,
        string|null $sort,
        string $scope
    ) {
        $query = Page::with(['colored', 'user']);
        if (!Auth::user()->admin) {
            $query->where('blocked', false);
        }
        if ($search) {
            $query->where(function (Builder $query) use ($search) {
                $query->where('prompt', 'like', "%$search%")
                    ->orWhereHas('user', function ($userQuery) use ($search) {
                        $userQuery->where('name', 'like', "%$search%")
                            ->orWhere('stripe_id', 'like', "%$search%");
                    });
            });
        }
        switch ($scope) {
            case 'favorited':
                $query->whereHas('favoritedUsers', function ($userQuery) {
                    $userQuery->where('id', Auth::id());
                })
                    ->join('favoriteds', function ($join) {
                        $join->on('pages.id', '=', 'favoriteds.page_id')
                            ->where('favoriteds.user_id', Auth::id());
                    })
                    ->select('pages.*');
                break;
            case 'owned':
                $query->whereHas('user', function ($userQuery) {
                    $userQuery->where('id', Auth::id());
                });
                break;
            case 'colored':
                $query->whereHas('coloreds', function ($coloredQuery) {
                    $coloredQuery->whereHas('user', function ($userQuery) {
                        $userQuery->where('id', Auth::id());
                    });
                })
                    ->join('coloreds', function ($join) {
                        $join->on('pages.id', '=', 'coloreds.page_id')
                            ->where('coloreds.user_id', Auth::id());
                    })
                    ->select('pages.*');
                break;
        }
        switch ($sort) {
            case 'oldest':
                switch ($scope) {
                    case 'favorited':
                        $query->orderBy('favoriteds.created_at');
                        break;
                    case 'colored':
                        $query->orderBy('coloreds.created_at');
                        break;
                    default:
                        $query->oldest();
                }
                break;
            case 'trending':
                $query->where('trending', true)
                    ->orderByDesc('favorited_count')
                    ->orderByDesc('colored_count');
                break;
            case 'popularity':
                $query->orderByDesc('favorited_count')
                    ->orderByDesc('colored_count');
                break;
            case 'mostFavorited':
                $query->orderByDesc('favorited_count');
                break;
            case 'mostColored':
                $query->orderByDesc('colored_count');
                break;
            case 'latest':
                switch ($scope) {
                    case 'favorited':
                        $query->orderByDesc('favoriteds.created_at');
                        break;
                    case 'colored':
                        $query->orderByDesc('coloreds.created_at');
                        break;
                    default:
                        $query->latest();
                }
                break;
        }
        $pagination = $query->paginate(18, ['*'], 'page', $page);
        $data = $pagination
            ->getCollection()
            ->each
            ->setAppends([
                'is_colored',
                'is_favorited',
                'is_owner'
            ]);
        $pagination->setCollection($data);
        return $pagination;
    }

    public static function toggleBlockedOrFail(int $id)
    {
        $page = Page::findOrFail($id);
        $pageData = ['blocked' => !$page->blocked];
        return $page->update($pageData);
    }

    public static function toggleFavoritedOrFail(int $id, int $userId)
    {
        $page = Page::findOrFail($id);
        $page->favoritedUsers()->toggle($userId);
        return $page->fresh();
    }

    public static function incrementFavoritedCount(int $id)
    {
        return Page::whereId($id)->increment('favorited_count');
    }

    public static function decrementFavoritedCount(int $id)
    {
        return Page::whereId($id)->decrement('favorited_count');
    }

    public static function incrementColoredCount(int $id)
    {
        return Page::whereId($id)->increment('colored_count');
    }

    public static function count()
    {
        return Page::count();
    }

    public static function countBetweenDate(Carbon $start, Carbon $end)
    {
        return Page::whereBetween('created_at', [$start, $end])
            ->count();
    }

    public static function dailyCountBetweenDate(Carbon $start, Carbon $end)
    {
        return Page::dailyCountBetweenDate($start, $end)
            ->get();
    }

    public static function findOrFailById(int $id)
    {
        return Page::findOrFail($id);
    }

    public static function unmarkTrendings()
    {
        return Page::where('trending', true)
            ->update(['trending' => false]);
    }

    public static function markTrendings()
    {
        $query = Page::createdThisWeek()
            ->orderByDesc('favorited_count')
            ->orderByDesc('colored_count')
            ->limit(12)
            ->update(['trending' => true]);
    }
}
