<?php

namespace App\Components\Task;

use App\Models\Task;
use App\Models\User\User;
use App\Services\HistoryService;
use App\Services\TaskService;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Livewire\Attributes\Computed;
use Livewire\Attributes\Lazy;
use Livewire\Component;
use Livewire\WithPagination;

class TaskAssigner extends Component {
    use AuthorizesRequests;
    use WithPagination;

    // Use bootstrap for Livewire pagination links
    protected $paginationTheme = 'bootstrap';

    // The polymorphic owner model
    public $owner;

    public bool $showAdd = false;
    public string $filter = 'all'; // Filters: all, overdue, soon, good

    public string $title = '';
    public string $description = '';
    public string $due_at = '';
    public int $assigned_to = 0;

    public ?int $editingTaskId = null;
    public bool $showEdit = false;

    #[Computed]
    public function users() {
        return User::all()->mapWithKeys(function ($user) {
            return [$user->id => "{$user->name_first} {$user->name_last}"];
        })->toArray();
    }

    #[Computed]
    public function counts() {
        // Base query restricted to this specific polymorphic owner
        $baseQuery = Task::where('owner_type', $this->owner->getMorphClass())
            ->where('owner_id', $this->owner->getKey());

        return [
            'overdue' => (clone $baseQuery)->where('due_at', '<', now())->count(),
            'soon'    => (clone $baseQuery)->whereBetween('due_at', [now(), now()->addDays(2)])->count(),
            'good'    => (clone $baseQuery)->where('due_at', '>', now()->addDays(2))->count(),
        ];
    }

    #[Computed]
    public function tasks() {
        $query = Task::where('owner_type', $this->owner->getMorphClass())
            ->where('owner_id', $this->owner->getKey());

        if ($this->filter === 'overdue') {
            $query->where('due_at', '<', now());
        } elseif ($this->filter === 'soon') {
            $query->whereBetween('due_at', [now(), now()->addDays(2)]);
        } elseif ($this->filter === 'good') {
            $query->where('due_at', '>', now()->addDays(2));
        }

        // Return a paginated list
        return $query->orderBy('due_at', 'asc')->paginate(5);
    }

    public function showAddTask() {
        $this->showAdd = true;
    }

    public function hideAddTask() {
        $this->showAdd = false;
        $this->reset('title', 'description', 'due_at');
    }

    public function addTask(HistoryService $history, TaskService $service) {
        $this->authorize('tasks.create');
        $validated = $this->validate([
            'title'       => 'required|string|max:255',
            'description' => 'required|string|max:6535',
            'due_at'      => 'nullable|date|after:now',
            'assigned_to' => 'nullable|exists:users,id',
        ]);

        // Create the task using your service, attaching it to this file (owner)
        // so the history entry is recorded against the file.
        $service->addTask(
            $history,
            $validated['title'],
            $validated['due_at'] ?: Carbon::now()->addHours(48)->toDateString(),
            $validated['description'] ?? null,
            !empty($validated['assigned_to']) ? $validated['assigned_to'] : null,
            $this->owner,
        );

        $this->hideAddTask();
        $this->resetPage(); // Reset to the first page so they can see their new task (if applicable)
    }

    public function editTask(int $taskId): void {
        $task = Task::where('owner_type', $this->owner->getMorphClass())
            ->where('owner_id', $this->owner->getKey())
            ->findOrFail($taskId);

        $this->editingTaskId = $task->id;
        $this->title         = $task->title;
        $this->description   = (string) $task->description;
        $this->due_at        = $task->due_at ? $task->due_at->format('Y-m-d\TH:i') : '';
        $this->assigned_to   = (int) $task->user_id;
        $this->showEdit      = true;
    }

    public function updateTask(): void {
        $this->authorize('tasks.edit');
        $validated = $this->validate([
            'title'       => 'required|string|max:255',
            'description' => 'nullable|string|max:1000',
            'due_at'      => 'nullable|date',
            'assigned_to' => 'nullable|exists:users,id',
        ]);

        $task = Task::where('owner_type', $this->owner->getMorphClass())
            ->where('owner_id', $this->owner->getKey())
            ->findOrFail($this->editingTaskId);

        $task->update([
            'title'       => $validated['title'],
            'description' => $validated['description'] ?? null,
            'due_at'      => $validated['due_at'] ?: null,
            'user_id'     => !empty($validated['assigned_to']) ? $validated['assigned_to'] : $task->user_id,
        ]);

        $this->hideEditTask();
    }

    public function hideEditTask(): void {
        $this->showEdit = false;
        $this->reset(['title', 'description', 'due_at', 'assigned_to', 'editingTaskId']);
    }

    public function completeTask(HistoryService $history, TaskService $service, $taskId) {
        $this->authorize('tasks.complete');
        $task = Task::find($taskId);

        if ($task) {
            $service->completeTask($history, $task);
        }
    }

    public function deleteTask(HistoryService $history, TaskService $service, $taskId) {
        $this->authorize('tasks.delete');
        $task = Task::find($taskId);

        if ($task) {
            $service->deleteTask($history, $task);
        }
    }

    public function setFilter($filter) {
        // Toggle off if they click the active filter again
        $this->filter = ($this->filter === $filter) ? 'all' : $filter;
        $this->resetPage(); // Reset pagination when filter changes
    }

    public function render() {
        return view('components.task.task-assigner');
    }
}