<?php

declare(strict_types=1);

/**
 * APO-194 Card 6 — Import a JSONM definition file.
 *
 * URI:   POST /api/v1/design/definitions/import
 * Scope: administration.write  · exposeToMcp:TRUE (APO-205-006)
 *
 * The admin form path uploads a multipart file. The API path receives the
 * JSON-content envelope and writes it to a temp file, then ingests via the
 * registry's importDefinitionFile method.
 */
final class MyronImportDefinitionAction implements MyronAction
{
    public function __construct(
        private readonly MyronDefinitionsActionService $service,
    ) {
    }

    public function metadata(): MyronActionMetadata
    {
        return new MyronActionMetadata(
            uri:           '/api/v1/design/definitions/import',
            method:        'POST',
            domain:        'design',
            resource:      'definition',
            verb:          'import',
            inputSchema:   [
                'type'       => 'object',
                'properties' => [
                    'filename'         => ['type' => 'string'],
                    'contentType'      => ['type' => 'string'],
                    'contentBase64'    => ['type' => 'string'],
                    'sizeBytes'        => ['type' => 'integer'],
                    'sha256'           => ['type' => 'string'],
                    'importName'       => ['type' => 'string'],
                    'applyImmediately' => ['type' => 'boolean'],
                ],
                'required'   => ['filename', 'contentType', 'contentBase64', 'sizeBytes', 'sha256'],
            ],
            outputSchema:  ['type' => 'object', 'properties' => ['id' => ['type' => 'string'], 'name' => ['type' => 'string']]],
            requiredScope:   MyronApiScopes::DESIGN_WRITE,
            summary:         'Import a JSONM design definition file via the JSON-content envelope; optionally apply it as the install\'s active definition immediately.',
            sideEffects:     ['writes design_system_definitions row; optionally updates active definition'],
            preconditions:   ['envelope decodes cleanly; JSON parses as a valid definition'],
            postconditions:  ['definition imported and visible in the stored list'],
            audienceClass:   2,
            adminAliases:    ['import-definition'],
            snapshotInclude: false,
            exposeToMcp:     true,
        );
    }

    public function execute(array $input, MyronActionCallerContext $caller): MyronActionResult
    {
        try {
            $envelope = [
                'filename'      => $input['filename']      ?? '',
                'contentType'   => $input['contentType']   ?? 'application/json',
                'contentBase64' => $input['contentBase64'] ?? '',
                'sizeBytes'     => $input['sizeBytes']     ?? 0,
                'sha256'        => $input['sha256']        ?? '',
            ];
            $tempDir = dirname(__DIR__, 3) . '/tmp/uploads';
            $decoder = new MyronJsonContentEnvelope($tempDir, ['application/json', 'text/plain']);
            $decoded = $decoder->decode($envelope);
            try {
                $result = $this->service->importDefinition(
                    $decoded->tempPath,
                    isset($input['importName']) ? (string) $input['importName'] : null,
                    (bool) ($input['applyImmediately'] ?? false),
                    $caller
                );
                return MyronActionResult::ok($result);
            } finally {
                $decoded->cleanup();
            }
        } catch (MyronJsonContentEnvelopeError $e) {
            return MyronActionResult::error('input_invalid', $e->getMessage());
        } catch (MyronActionPreconditionError $e) {
            return MyronActionResult::error('precondition_failed', $e->getMessage());
        } catch (Throwable $e) {
            return MyronActionResult::error('business_rule_failed', $e->getMessage());
        }
    }
}
