<?php

namespace MintyPHP\Repository\Access;

use MintyPHP\DB;

/** Manages which roles a given role is allowed to assign (role hierarchy). */
class RoleAssignableRoleRepository implements RoleAssignableRoleRepositoryInterface
{
    public function listAssignableRoleIdsByRoleId(int $roleId): array
    {
        $rows = DB::select(
            'select assignable_role_id from role_assignable_roles where role_id = ?',
            (string) $roleId
        );
        if (!is_array($rows)) {
            return [];
        }
        $ids = [];
        foreach ($rows as $row) {
            $data = $row['role_assignable_roles'] ?? $row;
            if (is_array($data) && isset($data['assignable_role_id'])) {
                $ids[] = (int) $data['assignable_role_id'];
            }
        }
        return array_values(array_unique($ids));
    }

    public function listAssignableRoleIdsByRoleIds(array $roleIds): array
    {
        $roleIds = toIntIds($roleIds);
        if (!$roleIds) {
            return [];
        }

        $placeholders = implode(',', array_fill(0, count($roleIds), '?'));
        $rows = DB::select(
            'select distinct assignable_role_id from role_assignable_roles where role_id in (' .
            $placeholders .
            ')',
            ...array_map('strval', $roleIds)
        );

        if (!is_array($rows)) {
            return [];
        }

        $ids = [];
        foreach ($rows as $row) {
            $data = $row['role_assignable_roles'] ?? $row;
            if (is_array($data) && isset($data['assignable_role_id'])) {
                $ids[] = (int) $data['assignable_role_id'];
            }
        }
        return array_values(array_unique($ids));
    }

    public function replaceForRole(int $roleId, array $assignableRoleIds): bool
    {
        DB::delete('delete from role_assignable_roles where role_id = ?', (string) $roleId);
        $ids = array_values(array_unique(array_filter(array_map('intval', $assignableRoleIds))));
        if (!$ids) {
            return true;
        }
        foreach ($ids as $assignableRoleId) {
            DB::insert(
                'insert into role_assignable_roles (role_id, assignable_role_id, created) values (?,?,NOW())',
                (string) $roleId,
                (string) $assignableRoleId
            );
        }
        return true;
    }
}
