<?php

namespace App\Livewire;

use App\Enums\UserRole;
use App\Models\Comment;
use App\Models\User;
use Livewire\Attributes\Url;
use Livewire\Component;
use Livewire\WithPagination;

class AdminCommentSearch extends Component
{
    use WithPagination;

    #[Url(history: true)]
    public $search = '';

    #[Url(history: true)]
    public $userSearch = '';

    #[Url(history: true)]
    public $sortField = 'created_at';

    #[Url(history: true)]
    public $sortDirection = 'desc';

    #[Url(history: true)]
    public $perPage = 20;

    public $selected = [];

    public $selectPage = false;

    protected $queryString = [
        'search' => ['except' => ''],
        'userSearch' => ['except' => ''],
        'sortField' => ['except' => 'created_at'],
        'sortDirection' => ['except' => 'desc'],
        'perPage' => ['except' => 20],
    ];

    protected $allowedSortFields = ['id', 'body', 'created_at', 'user_id'];

    protected $allowedPerPages = [10, 20, 50, 100];

    public function updatedPerPage(): void
    {
        $this->resetPage();
    }

    public function updatedPage(): void
    {
        $this->selectPage = false;
        $this->selected = [];
    }

    public function updatedSelectPage($value): void
    {
        if ($value) {
            $this->selected = $this->comments->pluck('id')->map(fn ($id) => (string) $id)->toArray();
        } else {
            $this->selected = [];
        }
    }

    public function sortBy(string $field): void
    {
        if (! in_array($field, $this->allowedSortFields)) {
            return;
        }

        if ($this->sortField === $field) {
            $this->sortDirection = $this->sortDirection === 'asc' ? 'desc' : 'asc';
        } else {
            $this->sortField = $field;
            $this->sortDirection = 'asc';
        }
    }

    public function clearFilters(): void
    {
        $this->search = '';
        $this->userSearch = '';
        $this->sortField = 'created_at';
        $this->sortDirection = 'desc';
        $this->perPage = 20;
        $this->resetPage();
    }

    public function deleteComment(int $commentId): void
    {
        $comment = Comment::findOrFail($commentId);
        $comment->delete();
        cache()->flush();
        $this->dispatch('notify', type: 'success', message: 'Comment deleted successfully.');
    }

    public function bulkDelete(): void
    {
        $count = Comment::whereIn('id', array_map('intval', $this->selected))->delete();
        cache()->flush();
        $this->selected = [];
        $this->selectPage = false;
        $this->dispatch('notify', type: 'success', message: "{$count} comment(s) deleted.");
    }

    public function banCommentAuthor(int $commentId): void
    {
        $comment = Comment::findOrFail($commentId);
        $user = $comment->user;

        if ($user && ! $user->hasRole(UserRole::BANNED)) {
            $user->addRole(UserRole::BANNED);
            cache()->flush();
            $this->dispatch('notify', type: 'success', message: "{$user->name} has been banned.");
        } else {
            $this->dispatch('notify', type: 'error', message: 'User is already banned or not found.');
        }
    }

    public function bulkBanAuthors(): void
    {
        $count = 0;
        $userIds = Comment::whereIn('id', array_map('intval', $this->selected))
            ->pluck('user_id')
            ->unique();

        foreach ($userIds as $userId) {
            $user = User::find($userId);
            if ($user && ! $user->hasRole(UserRole::BANNED)) {
                $user->addRole(UserRole::BANNED);
                $count++;
            }
        }

        cache()->flush();
        $this->selected = [];
        $this->selectPage = false;
        $this->dispatch('notify', type: 'success', message: "{$count} comment author(s) banned.");
    }

    public function getCommentsProperty()
    {
        return Comment::query()
            ->with('user')
            ->when($this->search !== '', fn ($query) => $query->where('body', 'LIKE', "%{$this->search}%"))
            ->when($this->userSearch !== '', fn ($query) => $query->whereHas('user', fn ($q) => $q->where('name', 'LIKE', "%{$this->userSearch}%")))
            ->orderBy($this->sortField, $this->sortDirection)
            ->paginate((int) $this->perPage);
    }

    public function render()
    {
        return view('livewire.admin-comment-search', [
            'comments' => $this->comments,
        ]);
    }
}