<?php

namespace App\Modules\Settings\Rbac\Services;

use App\Models\User;
use App\Modules\Admin\Tenancy\Models\Tenant;
use App\Modules\HR\Employees\Repositories\EmployeeRepository;
use App\Modules\Navigation\Services\NavigationService;
use App\Modules\Settings\Rbac\Repositories\TenantUserRepository;
use Illuminate\Validation\ValidationException;

class TenantUserEmployeeLinkService
{
    public function __construct(
        private readonly TenantUserRepository $users,
        private readonly EmployeeRepository $employees,
        private readonly RbacAuditService $audit,
    ) {}

    public function sync(Tenant $tenant, User $user, ?int $employeeId): void
    {
        if (($user->employee_id === null && $employeeId === null)
            || (int) $user->employee_id === $employeeId) {
            return;
        }

        if ($employeeId === null) {
            $updated = $this->users->setEmployeeId($user, null);
            $this->forgetCaches($updated);
            $this->audit->user($updated, 'employee_unlinked');

            return;
        }

        $employee = $this->employees->findForTenant((int) $tenant->id, $employeeId);

        if ($employee === null) {
            throw ValidationException::withMessages([
                'employee_id' => [__('rbac.validation.employee_invalid')],
            ]);
        }

        $conflict = $this->users->employeeLinkExists(
            (int) $tenant->id,
            $employeeId,
            (int) $user->id,
        );

        if ($conflict) {
            throw ValidationException::withMessages([
                'employee_id' => [__('rbac.validation.employee_already_linked')],
            ]);
        }

        $updated = $this->users->setEmployeeId($user, $employeeId);
        $this->forgetCaches($updated);
        $this->audit->user($updated, 'employee_linked');
    }

    private function forgetCaches(User $user): void
    {
        TenantPermissionEvaluator::forgetCacheForUser($user);
        NavigationService::forgetForUser($user);
    }
}
