<?php

namespace App\Modules\HR\Positions\Repositories;

use App\Modules\HR\Positions\Models\Position;
use App\Support\LookupCodeColumn;
use App\Support\SelectOptionFormatter;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;

class PositionRepository
{
    public function paginateForList(int $perPage = 20): LengthAwarePaginator
    {
        return Position::query()
            ->with(['department:id,name,tenant_id', 'jobGrade:id,name,tenant_id'])
            ->orderBy('title')
            ->paginate($perPage)
            ->withQueryString();
    }

    public function findOrFail(int $id): Position
    {
        return Position::query()
            ->with(['department:id,name,tenant_id', 'jobGrade:id,name,tenant_id'])
            ->findOrFail($id);
    }

    /**
     * @param  array<string, mixed>  $data
     */
    public function create(array $data): Position
    {
        return Position::query()->create($data);
    }

    /**
     * @param  array<string, mixed>  $data
     */
    public function update(Position $position, array $data): Position
    {
        $position->update($data);

        return $position->fresh(['department:id,name,tenant_id', 'jobGrade:id,name,tenant_id']);
    }

    /**
     * @return array<int, string>
     */
    public function listForSelect(): array
    {
        return Position::query()
            ->where('is_active', true)
            ->orderBy('title')
            ->pluck('title', 'id')
            ->all();
    }

    /**
     * @return list<array{value: string, label: string}>
     */
    public function searchForLookup(
        string $query,
        int $limit = 30,
        ?int $onlyId = null,
        ?int $tenantId = null,
        ?int $departmentId = null,
    ): array {
        if ($onlyId === null && ($departmentId === null || $departmentId <= 0)) {
            return [];
        }

        $builder = Position::query()
            ->where('is_active', true)
            ->orderBy('title');

        if ($tenantId !== null && $tenantId > 0) {
            $builder->where('tenant_id', $tenantId);
        }

        if ($departmentId !== null && $departmentId > 0) {
            $builder->where('department_id', $departmentId);
        }

        if ($onlyId !== null) {
            $builder->whereKey($onlyId);
        } else {
            if ($query !== '') {
                $builder->where(function ($q) use ($query): void {
                    $q->where('title', 'like', '%'.$query.'%');
                    if (LookupCodeColumn::exists('positions')) {
                        $q->orWhere('code', 'like', '%'.$query.'%');
                    }
                });
            }
            $builder->limit($limit);
        }

        $columns = ['id', 'title'];
        $codeKey = LookupCodeColumn::exists('positions') ? 'code' : null;
        if ($codeKey !== null) {
            $columns[] = 'code';
        }

        return SelectOptionFormatter::mapRows(
            $builder->get($columns),
            'title',
            $codeKey,
        );
    }
}
