<?php

declare(strict_types=1);

namespace App\Services;

use App\Models\Paper;
use App\Models\QuestionBank;
use App\Models\SchoolClass;
use App\Models\User;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;

final class LearningAccessService
{
    public function visibleBanksQuery(User $user): Builder
    {
        $classIds = $this->classIds($user);

        return QuestionBank::query()
            ->where('is_active', true)
            ->where(function (Builder $query) use ($user, $classIds): void {
                $query->where('visibility', 'public')
                    ->orWhere('owner_id', $user->id)
                    ->orWhereExists(function ($sub) use ($user): void {
                        $sub->selectRaw('1')
                            ->from('bank_shares')
                            ->whereColumn('bank_shares.question_bank_id', 'question_banks.id')
                            ->where('target_type', 'user')
                            ->where('target_id', $user->id);
                    })
                    ->orWhereExists(function ($sub) use ($classIds): void {
                        $sub->selectRaw('1')
                            ->from('bank_shares')
                            ->whereColumn('bank_shares.question_bank_id', 'question_banks.id')
                            ->where('target_type', 'class')
                            ->whereIn('target_id', $classIds);
                    });
            });
    }

    public function visiblePapersQuery(User $user): Builder
    {
        return Paper::query()
            ->where('is_active', true)
            ->where(function (Builder $query) use ($user): void {
                $query->where('owner_id', $user->id)
                    ->orWhereIn('question_bank_id', $this->visibleBanksQuery($user)->select('id'));
            });
    }

    public function canAccessBank(User $user, QuestionBank $bank): bool
    {
        return $this->visibleBanksQuery($user)->whereKey($bank->id)->exists();
    }

    public function canAccessPaper(User $user, Paper $paper): bool
    {
        return $this->visiblePapersQuery($user)->whereKey($paper->id)->exists();
    }

    private function classIds(User $user): Collection
    {
        return SchoolClass::query()
            ->whereHas('members', fn (Builder $query) => $query->where('users.id', $user->id))
            ->pluck('id');
    }
}
