<?php

namespace App\Modules\Settings\Rbac\Services;

use App\Models\User;
use App\Modules\Admin\Tenancy\Models\Tenant;
use App\Modules\Navigation\Services\NavigationService;
use App\Modules\Settings\Rbac\Repositories\TenantUserRepository;
use App\Modules\Settings\Rbac\Repositories\UserRoleRepository;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\ValidationException;

class TenantUserCreationService
{
    public function __construct(
        private readonly TenantUserDirectoryService $directory,
        private readonly TenantUserRepository $users,
        private readonly UserRoleRepository $userRoles,
        private readonly TenantUserEmployeeLinkService $employeeLinks,
        private readonly RbacAuditService $audit,
    ) {}

    /**
     * @param  list<int>  $roleIds
     */
    public function create(
        Tenant $tenant,
        string $name,
        string $email,
        string $password,
        array $roleIds,
        ?int $employeeId = null,
    ): User {
        if ($this->directory->emailTakenInTenant($tenant, $email, null)) {
            throw ValidationException::withMessages([
                'email' => [__('rbac.validation.email_taken')],
            ]);
        }

        $user = DB::transaction(function () use ($tenant, $name, $email, $password, $roleIds, $employeeId): User {
            $user = $this->users->create([
                'name' => $name,
                'email' => $email,
                'password' => Hash::make($password),
                'tenant_id' => $tenant->id,
                'is_admin' => false,
                'email_verified_at' => now(),
            ]);
            $this->userRoles->syncRolesForUser($user, (int) $tenant->id, $roleIds);
            TenantPermissionEvaluator::forgetCacheForUser($user);
            NavigationService::forgetForUser($user);

            if ($employeeId !== null) {
                $this->employeeLinks->sync($tenant, $user, $employeeId);
            }

            return $this->users->find((int) $tenant->id, (int) $user->id) ?? $user;
        });
        $this->audit->user($user, 'created');

        return $user;
    }
}
