<?php

declare(strict_types=1);

/**
 * APO-196 Card 5 — Update a user profile.
 *
 * URI:   PATCH /api/v1/administration/users/{userId}/profile
 * Scope: administration.write
 *
 * Self-service callers should target their own userId; AI bearer integrations
 * can update profile fields they're scoped for. The route gate enforces
 * "can't update another user's profile without admin role" — this action's
 * required scope (administration.write) defends in depth.
 */
final class MyronUpdateProfileAction implements MyronAction
{
    public function __construct(private readonly MyronIdentityActionService $service) {}
    public function metadata(): MyronActionMetadata
    {
        return new MyronActionMetadata(
            uri: '/api/v1/administration/users/{userId}/profile', method: 'PATCH',
            domain: 'administration', resource: 'user-profile', verb: 'update',
            inputSchema: [
                'type' => 'object',
                'properties' => [
                    'userId'       => ['type' => 'string'],
                    'first_name'   => ['type' => 'string'],
                    'last_name'    => ['type' => 'string'],
                    'display_name' => ['type' => 'string'],
                    'email'        => ['type' => 'string'],
                    'job_title'    => ['type' => 'string'],
                    'same_as_urls' => ['type' => 'string'],
                ],
                'required' => ['userId'],
            ],
            outputSchema: ['type' => 'object', 'properties' => ['userId' => ['type' => 'string']]],
            requiredScope: MyronApiScopes::ADMINISTRATION_WRITE,
            summary: 'Update a user profile (name, email, display name).',
            sideEffects: ['updates users row'],
            preconditions: ['user exists; caller has admin role or is updating self'],
            postconditions: ['profile fields updated'],
            audienceClass: 4, adminAliases: ['save-profile'],
            snapshotInclude: false, exposeToMcp: true,
        );
    }
    public function execute(array $input, MyronActionCallerContext $caller): MyronActionResult
    {
        try { return MyronActionResult::ok($this->service->updateProfile((string) ($input['userId'] ?? ''), $input, $caller)); }
        catch (InvalidArgumentException $e) { return MyronActionResult::error('input_invalid', $e->getMessage()); }
        catch (Throwable $e) { return MyronActionResult::error('business_rule_failed', $e->getMessage()); }
    }
}
