<?php

namespace App\Modules\HR\EmploymentStatuses\Repositories;

use App\Modules\HR\EmploymentStatuses\Models\EmploymentStatus;
use App\Support\Lists\ListQuery;
use App\Support\SelectOptionFormatter;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Http\Request;

class EmploymentStatusRepository
{
    public function listOrdered(): Collection
    {
        return EmploymentStatus::query()
            ->orderBy('sort_order')
            ->orderBy('name')
            ->get();
    }

    public function paginateForIndex(Request $request): LengthAwarePaginator
    {
        $query = EmploymentStatus::query();

        ListQuery::applySearch($query, $request->input('q'), ['name', 'code']);
        ListQuery::applyBoolean($query, 'is_active', $request->input('is_active'));
        ListQuery::applySort(
            $query,
            $request->input('sort'),
            $request->input('dir'),
            [
                'name' => 'name',
                'sort_order' => 'sort_order',
                'is_active' => 'is_active',
            ],
            'sort_order',
        );
        $query->orderBy('name');

        return ListQuery::paginate($query, $request);
    }

    public function findOrFail(int $id): EmploymentStatus
    {
        return EmploymentStatus::query()->findOrFail($id);
    }

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

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

        return $status->fresh();
    }

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

    /**
     * @param  list<array<string, mixed>>  $defaults
     */
    public function seedDefaults(int $tenantId, array $defaults): void
    {
        foreach ($defaults as $row) {
            EmploymentStatus::query()->firstOrCreate(
                ['tenant_id' => $tenantId, 'code' => $row['code']],
                [
                    'name' => $row['name'],
                    'description' => $row['description'] ?? null,
                    'color' => $row['color'] ?? 'info',
                    'sort_order' => $row['sort_order'] ?? 0,
                    'is_active' => true,
                ],
            );
        }
    }

    public function findIdByLegacyCode(int $tenantId, string $code): ?int
    {
        $id = EmploymentStatus::query()
            ->where('tenant_id', $tenantId)
            ->where('code', $code)
            ->value('id');

        return $id !== null ? (int) $id : null;
    }

    /**
     * @return list<array{value: string, label: string}>
     */
    public function searchForLookup(
        int $tenantId,
        string $query,
        int $limit = 30,
        ?int $onlyId = null,
    ): array {
        $builder = EmploymentStatus::query()
            ->where('tenant_id', $tenantId)
            ->where('is_active', true)
            ->orderBy('sort_order')
            ->orderBy('name');

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

        return SelectOptionFormatter::mapRows(
            $builder->get(['id', 'name', 'code']),
            'name',
            'code',
        );
    }
}
