<?php

namespace App\Repositories;

use App\Models\Participant;
use App\Services\IcNumberService;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;

class ParticipantRepository
{
    public function __construct(
        private readonly IcNumberService $icNumberService,
    ) {}

    public function findByIcNumber(string $icNumber): ?Participant
    {
        $hash = $this->icNumberService->hash($icNumber);

        return Participant::where('ic_number_hash', $hash)
            ->where('is_active', true)
            ->first();
    }

    public function searchByName(string $name, int $limit = 25): Collection
    {
        $name = preg_replace('/\s+/u', ' ', trim($name));
        $escapedName = addcslashes($name, '%_\\');
        $keywords = preg_split('/\s+/u', $name, -1, PREG_SPLIT_NO_EMPTY);

        return Participant::query()
            ->where('is_active', true)
            ->where(function (Builder $query) use ($keywords) {
                foreach ($keywords as $keyword) {
                    $escapedKeyword = addcslashes($keyword, '%_\\');
                    $query->where('full_name', 'like', '%'.$escapedKeyword.'%');
                }
            })
            ->orderByRaw(
                'CASE WHEN full_name = ? THEN 0 WHEN full_name LIKE ? THEN 1 ELSE 2 END',
                [$name, $escapedName.'%']
            )
            ->orderBy('full_name')
            ->limit($limit)
            ->get();
    }

    public function paginate(array $filters = [], int $perPage = 15): LengthAwarePaginator
    {
        return $this->buildQuery($filters)
            ->orderBy($filters['sort'] ?? 'created_at', $filters['direction'] ?? 'desc')
            ->paginate($perPage)
            ->withQueryString();
    }

    public function buildQuery(array $filters = []): Builder
    {
        $query = Participant::query();

        if (! empty($filters['search'])) {
            $query->where(function ($q) use ($filters) {
                $q->where('full_name', 'like', '%'.$filters['search'].'%')
                    ->orWhere('participant_number', 'like', '%'.$filters['search'].'%')
                    ->orWhere('category', 'like', '%'.$filters['search'].'%');
            });
        }

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

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

        if (! empty($filters['ic_number'])) {
            $hash = $this->icNumberService->hash($filters['ic_number']);
            $query->where('ic_number_hash', $hash);
        }

        return $query;
    }

    public function getCategories(): array
    {
        return Participant::whereNotNull('category')
            ->distinct()
            ->orderBy('category')
            ->pluck('category')
            ->toArray();
    }
}
