<?php

namespace App\Modules\HR\Recruitment\Repositories;

use App\Modules\HR\Recruitment\Models\RecruitmentOfferLetter;
use App\Modules\HR\Recruitment\Support\OfferLetterStatus;
use App\Support\SelectOptionFormatter;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;

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

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

        return $row->fresh($this->defaultWith());
    }

    public function softDelete(RecruitmentOfferLetter $row): void
    {
        $row->delete();
    }

    /** @param  list<int>  $ids */
    public function softDeleteMany(int $tenantId, array $ids): int
    {
        return RecruitmentOfferLetter::query()
            ->where('tenant_id', $tenantId)
            ->where('status', OfferLetterStatus::DRAFT)
            ->whereIn('id', $ids)
            ->delete();
    }

    public function lockForTenant(int $tenantId, int $id): ?RecruitmentOfferLetter
    {
        return RecruitmentOfferLetter::query()
            ->where('tenant_id', $tenantId)
            ->whereKey($id)
            ->lockForUpdate()
            ->first();
    }

    /**
     * @param  array{q?: ?string, status?: ?string, application_id?: ?int, candidate_id?: ?int, vacancy_id?: ?int}  $filters
     */
    public function paginateForTenant(int $tenantId, array $filters = [], int $perPage = 20): LengthAwarePaginator
    {
        $q = RecruitmentOfferLetter::query()
            ->where('tenant_id', $tenantId)
            ->with($this->defaultWith())
            ->orderByDesc('id');

        if (! empty($filters['status'])) {
            $q->where('status', $filters['status']);
        }
        if (! empty($filters['application_id'])) {
            $q->where('application_id', (int) $filters['application_id']);
        }
        if (! empty($filters['candidate_id'])) {
            $q->where('candidate_id', (int) $filters['candidate_id']);
        }
        if (! empty($filters['vacancy_id'])) {
            $q->where('vacancy_id', (int) $filters['vacancy_id']);
        }
        if (! empty($filters['q'])) {
            $term = '%'.$filters['q'].'%';
            $q->where(function ($b) use ($term): void {
                $b->where('reference_code', 'like', $term)
                    ->orWhereHas('candidate', fn ($c) => $c
                        ->where('first_name', 'like', $term)
                        ->orWhere('last_name', 'like', $term));
            });
        }

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

    /** @return list<array{value: string, label: string}> */
    public function searchForLookup(int $tenantId, string $query, int $limit = 30, ?int $onlyId = null): array
    {
        $builder = RecruitmentOfferLetter::query()
            ->where('tenant_id', $tenantId)
            ->with(['candidate'])
            ->orderByDesc('id');

        if ($onlyId !== null) {
            $builder->whereKey($onlyId);
        } else {
            if ($query !== '') {
                $term = '%'.$query.'%';
                $builder->where('reference_code', 'like', $term);
            }
            $builder->limit($limit);
        }

        $out = [];
        foreach ($builder->get() as $row) {
            $name = $row->candidate?->full_name ?? '';
            $out[] = [
                'value' => (string) $row->id,
                'label' => SelectOptionFormatter::label(
                    trim($row->reference_code.($name !== '' ? ' — '.$name : '')),
                    (string) $row->status
                ),
            ];
        }

        return $out;
    }

    /** @return list<string> */
    private function defaultWith(): array
    {
        return [
            'application', 'candidate', 'vacancy', 'department', 'position', 'employmentStatus',
        ];
    }
}
