<?php

namespace App\Services\Roles;

use App\Models\Permission;
use App\Models\RolePermission;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class RolePermissionService
{
    public function listPermissions(): array
    {
        return Permission::query()
            ->orderBy('id', 'asc')
            ->get()
            ->all();
    }

    public function listRolePermissions(int $roleId): array
    {
        $rows = Permission::query()
            ->leftJoin('role_permissions', function ($join) use ($roleId) {
                $join->on('role_permissions.permission_id', '=', 'permissions.id')
                    ->where('role_permissions.role_id', '=', $roleId);
            })
            ->select(
                'permissions.id',
                'permissions.name',
                'permissions.description',
                'role_permissions.can_create',
                'role_permissions.can_read',
                'role_permissions.can_update',
                'role_permissions.can_delete',
                'role_permissions.can_manage'
            )
            ->orderBy('permissions.name', 'asc')
            ->get()
            ->map(fn ($r) => (array) $r)
            ->all();

        return $rows;
    }

    public function saveRolePermissions(int $roleId, array $permissions): void
    {
        try {
            DB::transaction(function () use ($roleId, $permissions) {
                $existing = RolePermission::query()
                    ->where('role_id', $roleId)
                    ->get()
                    ->keyBy('permission_id');

                foreach ($permissions as $permissionId => $crudValues) {
                    $permissionId = (int) $permissionId;
                    if ($permissionId <= 0) {
                        continue;
                    }

                    $data = [
                        'can_create' => !empty($crudValues['create']) ? 1 : 0,
                        'can_read' => !empty($crudValues['read']) ? 1 : 0,
                        'can_update' => !empty($crudValues['update']) ? 1 : 0,
                        'can_delete' => !empty($crudValues['delete']) ? 1 : 0,
                        'can_manage' => !empty($crudValues['manage']) ? 1 : 0,
                    ];

                    if ($existing->has($permissionId)) {
                        RolePermission::query()
                            ->where('role_id', $roleId)
                            ->where('permission_id', $permissionId)
                            ->update($data);
                    } else {
                        RolePermission::query()->create(array_merge($data, [
                            'role_id' => $roleId,
                            'permission_id' => $permissionId,
                        ]));
                    }
                }

                foreach ($existing as $permissionId => $row) {
                    if (!array_key_exists((string) $permissionId, $permissions) && !array_key_exists((int) $permissionId, $permissions)) {
                        RolePermission::query()
                            ->where('role_id', $roleId)
                            ->where('permission_id', $permissionId)
                            ->delete();
                    }
                }
            });
        } catch (\Throwable $e) {
            Log::error('Role permission save failed: ' . $e->getMessage());
            throw $e;
        }
    }
}
