<?php

declare(strict_types=1);

final class MyronImportSiteSnapshotAction implements MyronAction
{
    public function __construct(private readonly MyronSiteSnapshotImportService $service)
    {
    }

    public function metadata(): MyronActionMetadata
    {
        return new MyronActionMetadata(
            uri: '/api/v1/site/snapshot/import',
            method: 'POST',
            domain: 'administration',
            resource: 'site-snapshot',
            verb: 'import',
            inputSchema: [
                'type' => 'object',
                'properties' => [
                    'filename' => ['type' => 'string'],
                    'contentType' => ['type' => 'string'],
                    'contentBase64' => ['type' => 'string'],
                    'sizeBytes' => ['type' => 'integer'],
                    'sha256' => ['type' => 'string'],
                    'dryRun' => ['type' => 'boolean'],
                ],
                'required' => ['filename', 'contentType', 'contentBase64', 'sizeBytes', 'sha256'],
            ],
            outputSchema: ['type' => 'object'],
            requiredScope: MyronApiScopes::ADMINISTRATION_DESTRUCTIVE,
            summary: 'Validate or apply a portable site snapshot envelope. Dry-run is the default; dryRun:false applies complete replacement.',
            sideEffects: ['dryRun:false replaces covered operator-owned site tables'],
            preconditions: ['valid JSON-content envelope', 'snapshot sha256 verifies', 'snapshotVersion is compatible'],
            postconditions: ['dry-run report returned or complete replacement applied'],
            audienceClass: 4,
            adminAliases: ['dry-run-site-snapshot-import', 'apply-site-snapshot-import'],
            snapshotInclude: false,
            exposeToMcp: true,
        );
    }

    public function execute(array $input, MyronActionCallerContext $caller): MyronActionResult
    {
        try {
            $decoder = new MyronJsonContentEnvelope(
                dirname(__DIR__, 3) . '/tmp/uploads',
                ['application/json', 'text/plain'],
                50 * 1024 * 1024
            );
            $decoded = $decoder->decode([
                'filename' => $input['filename'] ?? '',
                'contentType' => $input['contentType'] ?? '',
                'contentBase64' => $input['contentBase64'] ?? '',
                'sizeBytes' => $input['sizeBytes'] ?? 0,
                'sha256' => $input['sha256'] ?? '',
            ]);

            try {
                $snapshotJson = (string) file_get_contents($decoded->tempPath);
                $dryRun = (bool) ($input['dryRun'] ?? true);
                if ($dryRun) {
                    return MyronActionResult::ok([
                        'dryRun' => true,
                        'report' => $this->service->dryRun($snapshotJson)->toArray(),
                    ]);
                }

                return MyronActionResult::ok([
                    'dryRun' => false,
                    'result' => $this->service->apply($snapshotJson),
                ]);
            } finally {
                $decoded->cleanup();
            }
        } catch (MyronJsonContentEnvelopeError|InvalidArgumentException $e) {
            return MyronActionResult::error('input_invalid', $e->getMessage());
        } catch (Throwable $e) {
            return MyronActionResult::error('import_failed', $e->getMessage());
        }
    }
}
