<?php

namespace App\Services\Messaging;

use App\Models\Message;
use App\Models\User;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;

class MessageQueryService
{
    public function getUserRoleName(int $userId): ?string
    {
        $user = User::query()->with('roles')->find($userId);
        if (!$user) {
            return null;
        }

        $role = $user->roles->sortBy('id')->first();
        return $role ? (string) $role->name : null;
    }

    public function inbox(int $userId, array $filters, int $page, int $perPage): LengthAwarePaginator
    {
        return $this->baseQuery($filters)
            ->where('recipient_id', $userId)
            ->whereIn('status', ['sent', 'received'])
            ->paginate($perPage, ['*'], 'page', $page);
    }

    public function sent(int $userId, array $filters, int $page, int $perPage): LengthAwarePaginator
    {
        return $this->baseQuery($filters)
            ->where('sender_id', $userId)
            ->where('status', 'sent')
            ->paginate($perPage, ['*'], 'page', $page);
    }

    public function drafts(int $userId, array $filters, int $page, int $perPage): LengthAwarePaginator
    {
        return $this->baseQuery($filters)
            ->where('sender_id', $userId)
            ->where('status', 'draft')
            ->paginate($perPage, ['*'], 'page', $page);
    }

    public function trash(int $userId, array $filters, int $page, int $perPage): LengthAwarePaginator
    {
        return $this->baseQuery($filters)
            ->where('status', 'trashed')
            ->where(function ($q) use ($userId) {
                $q->where('sender_id', $userId)
                    ->orWhere('recipient_id', $userId);
            })
            ->paginate($perPage, ['*'], 'page', $page);
    }

    public function receivedAndMarkRead(int $userId): array
    {
        $messages = Message::query()
            ->with(['sender', 'recipient'])
            ->where('recipient_id', $userId)
            ->orderByDesc('sent_datetime')
            ->get();

        $ids = $messages
            ->where('read_status', false)
            ->pluck('id')
            ->all();

        if (!empty($ids)) {
            Message::query()
                ->whereIn('id', $ids)
                ->update([
                    'read_status' => 1,
                    'read_datetime' => now(),
                ]);
        }

        return $messages->all();
    }

    public function findForUser(int $messageId): ?Message
    {
        return Message::query()
            ->with(['sender', 'recipient'])
            ->find($messageId);
    }

    private function baseQuery(array $filters)
    {
        $query = Message::query()->with(['sender', 'recipient']);

        if (!empty($filters['priority'])) {
            $query->where('priority', $filters['priority']);
        }

        if (isset($filters['read_status'])) {
            $query->where('read_status', (int) $filters['read_status']);
        }

        if (!empty($filters['search'])) {
            $term = '%' . $filters['search'] . '%';
            $query->where(function ($q) use ($term) {
                $q->where('subject', 'like', $term)
                    ->orWhere('message', 'like', $term);
            });
        }

        $sortBy = $filters['sort_by'] ?? 'sent_datetime';
        $sortDir = strtolower((string) ($filters['sort_dir'] ?? 'desc')) === 'asc' ? 'asc' : 'desc';
        $query->orderBy($sortBy, $sortDir);

        return $query;
    }
}
