<?php

namespace App\Repositories;

use App\Contracts\StaffRepositoryContract;
use App\Enums\UserStatus;
use App\Enums\UserType;
use App\Models\User;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;

class StaffRepository implements StaffRepositoryContract
{
    /** @var list<string> */
    private array $listColumns = [
        'id',
        'name',
        'email',
        'phone',
        'status',
        'user_type',
        'is_primary_admin',
        'department_id',
        'designation_id',
        'created_at',
    ];

    public function paginate(array $filters = [], int $perPage = 15): LengthAwarePaginator
    {
        $query = User::query()
            ->select($this->listColumns)
            ->where('user_type', UserType::Staff)
            ->with([
                'department:id,name',
                'designation:id,name',
                'roles:id,name',
            ])
            ->orderBy('name');

        $this->applyFilters($query, $filters);

        return $query->paginate($perPage)->withQueryString();
    }

    public function paginateCustomers(array $filters = [], int $perPage = 15): LengthAwarePaginator
    {
        $query = User::query()
            ->select($this->listColumns)
            ->where('user_type', UserType::Customer)
            ->with(['roles:id,name'])
            ->orderBy('name');

        $this->applyFilters($query, $filters);

        return $query->paginate($perPage)->withQueryString();
    }

    public function find(int $id): ?User
    {
        return User::query()
            ->with([
                'department:id,name',
                'designation:id,name',
                'roles:id,name',
                'permissions:id,name',
            ])
            ->find($id);
    }

    public function create(array $data): User
    {
        return User::query()->create($data);
    }

    public function update(User $user, array $data): User
    {
        $user->update($data);

        return $user->fresh([
            'department:id,name',
            'designation:id,name',
            'roles:id,name',
        ]);
    }

    public function delete(User $user): bool
    {
        return (bool) $user->delete();
    }

    public function getActiveCount(): int
    {
        return User::query()
            ->where('status', UserStatus::Active)
            ->count();
    }

    public function getByDepartment(int $departmentId): Collection
    {
        return User::query()
            ->select($this->listColumns)
            ->where('department_id', $departmentId)
            ->orderBy('name')
            ->get();
    }

    private function applyFilters(Builder $query, array $filters): void
    {
        if (! empty($filters['search'])) {
            $search = trim((string) $filters['search']);

            if ($search !== '') {
                $this->applySearch($query, $search);
            }
        }

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

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

    private function applySearch(Builder $query, string $search): void
    {
        if ($this->supportsFullTextSearch()) {
            $query->whereFullText(['name', 'email'], $search);

            return;
        }

        $query->where(function (Builder $builder) use ($search) {
            $builder->where('name', 'like', "{$search}%")
                ->orWhere('email', 'like', "{$search}%");
        });
    }

    private function supportsFullTextSearch(): bool
    {
        return DB::connection()->getDriverName() === 'mysql';
    }
}
