<?php

namespace App\Modules\HR\Leave\Repositories;

use App\Modules\HR\Leave\Models\LeaveBalance;
use App\Modules\HR\Leave\Models\LeaveRequest;
use App\Modules\HR\Leave\Support\LeaveRequestStatus;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;

class LeaveBalanceRepository
{
    public function findOrCreate(
        int $tenantId,
        int $employeeId,
        int $leaveTypeId,
        int $year,
        float $entitledDays,
    ): LeaveBalance {
        $balance = LeaveBalance::query()->firstOrCreate(
            [
                'employee_id' => $employeeId,
                'leave_type_id' => $leaveTypeId,
                'year' => $year,
            ],
            [
                'tenant_id' => $tenantId,
                'entitled_days' => $entitledDays,
                'used_days' => 0,
            ],
        );

        return $balance->fresh();
    }

    public function lockForUpdate(int $tenantId, int $employeeId, int $leaveTypeId, int $year): ?LeaveBalance
    {
        return LeaveBalance::query()
            ->where('tenant_id', $tenantId)
            ->where('employee_id', $employeeId)
            ->where('leave_type_id', $leaveTypeId)
            ->where('year', $year)
            ->lockForUpdate()
            ->first();
    }

    public function addUsedDays(LeaveBalance $balance, float $days): LeaveBalance
    {
        $balance->update([
            'used_days' => (float) $balance->used_days + $days,
        ]);

        return $balance->fresh();
    }

    public function paginateForTenant(int $tenantId, ?int $employeeId, int $year, int $perPage = 25): LengthAwarePaginator
    {
        $q = LeaveBalance::query()
            ->where('tenant_id', $tenantId)
            ->where('year', $year)
            ->with(['employee:id,full_name', 'leaveType:id,name'])
            ->orderBy('employee_id')
            ->orderBy('leave_type_id');
        if ($employeeId !== null) {
            $q->where('employee_id', $employeeId);
        }

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

    public function sumPendingDays(int $tenantId, int $employeeId, int $leaveTypeId, int $year): float
    {
        return (float) LeaveRequest::query()
            ->where('tenant_id', $tenantId)
            ->where('employee_id', $employeeId)
            ->where('leave_type_id', $leaveTypeId)
            ->whereIn('status', [
                LeaveRequestStatus::PENDING,
                LeaveRequestStatus::MANAGER_APPROVED,
            ])
            ->whereYear('start_date', $year)
            ->sum('total_days');
    }
}
