<?php

namespace App\Support\Tasks;

use App\Models\Task;
use Illuminate\Database\Eloquent\Builder;

class TaskFilterApplier
{
    /**
     * @param  Builder<Task>  $query
     * @param  array<string, mixed>  $filters
     */
    public function apply(Builder $query, array $filters): void
    {
        $query
            ->when($filters['search'] !== '', function (Builder $builder) use ($filters): void {
                $search = (string) $filters['search'];

                $builder->where('title', 'like', "%{$search}%");
            })
            ->when($filters['status'], fn (Builder $builder) => $builder->where('status', $filters['status']))
            ->when($filters['priority'], fn (Builder $builder) => $builder->where('priority', $filters['priority']))
            ->when($filters['assignee_id'], fn (Builder $builder) => $builder->where('assignee_id', $filters['assignee_id']))
            ->when($filters['creator_id'], fn (Builder $builder) => $builder->where('creator_id', $filters['creator_id']))
            ->when($filters['project_id'], fn (Builder $builder) => $builder->where('project_id', $filters['project_id']))
            ->when($filters['deadline'] === 'overdue', function (Builder $builder): void {
                $builder->where('status', '!=', 'done')
                    ->whereNotNull('due_at')
                    ->where('due_at', '<', now());
            })
            ->when($filters['deadline'] === 'today', function (Builder $builder): void {
                $builder->whereDate('due_at', now()->toDateString());
            })
            ->when($filters['deadline'] === 'week', function (Builder $builder): void {
                $builder->whereBetween('due_at', [now()->startOfDay(), now()->copy()->addDays(7)->endOfDay()]);
            })
            ->when($filters['deadline'] === 'no_deadline', function (Builder $builder): void {
                $builder->whereNull('due_at');
            })
            ->when($filters['parent_mode'] === 'parents', fn (Builder $builder) => $builder->whereNull('parent_id'))
            ->when($filters['parent_mode'] === 'subtasks', fn (Builder $builder) => $builder->whereNotNull('parent_id'))
            ->when($filters['parent_mode'] === 'with_subtasks', fn (Builder $builder) => $builder->has('subtasks'))
            ->when($filters['parent_mode'] === 'without_subtasks', fn (Builder $builder) => $builder->doesntHave('subtasks'))
            ->when($filters['date_from'] !== '', fn (Builder $builder) => $builder->whereDate('due_at', '>=', $filters['date_from']))
            ->when($filters['date_to'] !== '', fn (Builder $builder) => $builder->whereDate('due_at', '<=', $filters['date_to']))
            ->when($filters['mine'], function (Builder $builder) use ($filters): void {
                $builder->where(function (Builder $sub) use ($filters): void {
                    $sub->where('creator_id', $filters['user_id'])
                        ->orWhere('assignee_id', $filters['user_id']);
                });
            });
    }
}
