<?php

namespace App\Services\Roles;

use App\Models\Role;
use App\Models\Staff;
use App\Models\User;
use App\Models\UserRole;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class RoleAssignmentService
{
    public function __construct(private RoleStaffService $staffService)
    {
    }

    /** @param int[] $roleIds */
    public function assignRoles(int $userId, array $roleIds, ?int $adminId = null): array
    {
        $roleIds = array_values(array_unique(array_filter(array_map('intval', $roleIds), fn ($id) => $id > 0)));

        $user = User::query()->find($userId);
        if (!$user) {
            return ['ok' => false, 'message' => 'User not found.'];
        }

        try {
            DB::transaction(function () use ($userId, $roleIds, $adminId) {
                UserRole::query()->where('user_id', $userId)->delete();

                foreach ($roleIds as $roleId) {
                    UserRole::query()->create([
                        'user_id' => $userId,
                        'role_id' => $roleId,
                        'updated_by' => $adminId,
                    ]);
                }
            });
        } catch (\Throwable $e) {
            Log::error('Role assignment failed: ' . $e->getMessage());
            throw $e;
        }

        $roleNames = Role::query()
            ->whereIn('id', $roleIds)
            ->pluck('name')
            ->map(fn ($n) => strtolower((string) $n))
            ->all();

        $this->staffService->syncStaffRecord($user, $roleNames);

        return [
            'ok' => true,
            'role_names' => $roleNames,
        ];
    }
}
