<?php

declare(strict_types=1);

abstract class MicFormActionBase implements MyronAction
{
    public function __construct(protected readonly MicFormService $service)
    {
    }

    protected function formSchema(bool $requireName = false): array
    {
        return [
            'type' => 'object',
            'properties' => [
                'formId' => ['type' => 'string'],
                'name' => ['type' => 'string'],
                'description' => ['type' => 'string'],
                'submit_button_label' => ['type' => 'string'],
                'success_message' => ['type' => 'string'],
                'fields' => ['type' => 'array'],
                'success_strategy' => ['type' => 'string'],
                'success_redirect_url' => ['type' => 'string'],
                'notification_email_id' => ['type' => 'string'],
                'embed_mode' => ['type' => 'string'],
                'cta_label' => ['type' => 'string'],
                'completion_routing' => ['type' => 'object'],
            ],
            'required' => $requireName ? ['name'] : [],
        ];
    }
}

final class MicFormCreateAction extends MicFormActionBase
{
    public function metadata(): MyronActionMetadata
    {
        return new MyronActionMetadata('/api/v1/content/forms', 'POST', 'content.forms', 'form', 'create', $this->formSchema(true), ['type' => 'object', 'properties' => ['form' => ['type' => 'object']]], MyronApiScopes::CONTENT_WRITE, 'Create a reusable Content Bank form.', ['inserts form_definitions row'], [], [], 4, ['forms.create'], false, null, true);
    }

    public function execute(array $input, MyronActionCallerContext $caller): MyronActionResult
    {
        try { return MyronActionResult::ok($this->service->create($input, $caller)); }
        catch (Throwable $e) { return MyronActionResult::error('input_invalid', $e->getMessage()); }
    }
}

final class MicFormReadAction extends MicFormActionBase
{
    public function metadata(): MyronActionMetadata
    {
        return new MyronActionMetadata('/api/v1/content/forms/{formId}', 'GET', 'content.forms', 'form', 'read', ['type' => 'object', 'properties' => ['formId' => ['type' => 'string']], 'required' => ['formId']], ['type' => 'object', 'properties' => ['form' => ['type' => 'object']]], MyronApiScopes::CONTENT_READ, 'Read one reusable Content Bank form.', [], [], [], 3, [], false, null, true);
    }

    public function execute(array $input, MyronActionCallerContext $caller): MyronActionResult
    {
        try { return MyronActionResult::ok($this->service->read((string) $input['formId'])); }
        catch (Throwable $e) { return MyronActionResult::error('not_found', $e->getMessage()); }
    }
}

final class MicFormListAction extends MicFormActionBase
{
    public function metadata(): MyronActionMetadata
    {
        return new MyronActionMetadata('/api/v1/content/forms', 'GET', 'content.forms', 'form', 'list', ['type' => 'object', 'properties' => []], ['type' => 'object', 'properties' => ['forms' => ['type' => 'array']]], MyronApiScopes::CONTENT_READ, 'List reusable Content Bank forms.', [], [], [], 3, [], false, null, true);
    }

    public function execute(array $input, MyronActionCallerContext $caller): MyronActionResult
    {
        return MyronActionResult::ok($this->service->list());
    }
}

final class MicFormUpdateAction extends MicFormActionBase
{
    public function metadata(): MyronActionMetadata
    {
        return new MyronActionMetadata('/api/v1/content/forms/{formId}', 'PATCH', 'content.forms', 'form', 'update', $this->formSchema(false), ['type' => 'object', 'properties' => ['form' => ['type' => 'object']]], MyronApiScopes::CONTENT_WRITE, 'Update a reusable Content Bank form.', ['updates form_definitions row'], [], [], 4, ['forms.update'], false, null, true);
    }

    public function execute(array $input, MyronActionCallerContext $caller): MyronActionResult
    {
        try { return MyronActionResult::ok($this->service->update((string) $input['formId'], $input, $caller)); }
        catch (Throwable $e) { return MyronActionResult::error('input_invalid', $e->getMessage()); }
    }
}

final class MicFormDeleteAction extends MicFormActionBase
{
    public function metadata(): MyronActionMetadata
    {
        return new MyronActionMetadata('/api/v1/content/forms/{formId}', 'DELETE', 'content.forms', 'form', 'delete', ['type' => 'object', 'properties' => ['formId' => ['type' => 'string']], 'required' => ['formId']], ['type' => 'object', 'properties' => ['deleted' => ['type' => 'boolean']]], MyronApiScopes::CONTENT_WRITE, 'Delete a reusable Content Bank form.', ['deletes form_definitions row'], [], [], 4, ['forms.delete'], false, null, true);
    }

    public function execute(array $input, MyronActionCallerContext $caller): MyronActionResult
    {
        return MyronActionResult::ok($this->service->delete((string) $input['formId']));
    }
}

final class MicFormDuplicateAction extends MicFormActionBase
{
    public function metadata(): MyronActionMetadata
    {
        return new MyronActionMetadata('/api/v1/content/forms/{formId}/duplicate', 'POST', 'content.forms', 'form', 'duplicate', ['type' => 'object', 'properties' => ['formId' => ['type' => 'string']], 'required' => ['formId']], ['type' => 'object', 'properties' => ['form' => ['type' => 'object']]], MyronApiScopes::CONTENT_WRITE, 'Duplicate a reusable Content Bank form.', ['inserts form_definitions row'], [], [], 4, ['forms.duplicate'], false, null, true);
    }

    public function execute(array $input, MyronActionCallerContext $caller): MyronActionResult
    {
        try { return MyronActionResult::ok($this->service->duplicate((string) $input['formId'], $caller)); }
        catch (Throwable $e) { return MyronActionResult::error('input_invalid', $e->getMessage()); }
    }
}

final class MicFormSubmissionListAction extends MicFormActionBase
{
    public function metadata(): MyronActionMetadata
    {
        return new MyronActionMetadata('/api/v1/content/forms/{formId}/submissions', 'GET', 'content.forms.submissions', 'submission', 'list', ['type' => 'object', 'properties' => ['formId' => ['type' => 'string'], 'limit' => ['type' => 'string'], 'offset' => ['type' => 'string']], 'required' => ['formId']], ['type' => 'object', 'properties' => ['submissions' => ['type' => 'array']]], MyronApiScopes::ADMINISTRATION_READ, 'List submissions for a form.', [], [], [], 3, [], false, null, true);
    }

    public function execute(array $input, MyronActionCallerContext $caller): MyronActionResult
    {
        return MyronActionResult::ok($this->service->listSubmissions((string) $input['formId'], (int) ($input['limit'] ?? 50), (int) ($input['offset'] ?? 0)));
    }
}

final class MicFormSubmissionReadAction extends MicFormActionBase
{
    public function metadata(): MyronActionMetadata
    {
        return new MyronActionMetadata('/api/v1/content/forms/{formId}/submissions/{submissionId}', 'GET', 'content.forms.submissions', 'submission', 'read', ['type' => 'object', 'properties' => ['formId' => ['type' => 'string'], 'submissionId' => ['type' => 'string']], 'required' => ['formId', 'submissionId']], ['type' => 'object', 'properties' => ['submission' => ['type' => 'object']]], MyronApiScopes::ADMINISTRATION_READ, 'Read one form submission.', [], [], [], 3, [], false, null, true);
    }

    public function execute(array $input, MyronActionCallerContext $caller): MyronActionResult
    {
        try { return MyronActionResult::ok($this->service->readSubmission((string) $input['submissionId'])); }
        catch (Throwable $e) { return MyronActionResult::error('not_found', $e->getMessage()); }
    }
}

final class MicFormSubmissionDeleteAction extends MicFormActionBase
{
    public function metadata(): MyronActionMetadata
    {
        return new MyronActionMetadata('/api/v1/content/forms/{formId}/submissions/{submissionId}', 'DELETE', 'content.forms.submissions', 'submission', 'delete', ['type' => 'object', 'properties' => ['formId' => ['type' => 'string'], 'submissionId' => ['type' => 'string']], 'required' => ['formId', 'submissionId']], ['type' => 'object', 'properties' => ['deleted' => ['type' => 'boolean']]], MyronApiScopes::ADMINISTRATION_WRITE, 'Hard-delete one form submission.', ['deletes form_submissions row'], [], [], 4, ['forms.submissions.delete'], false, null, true);
    }

    public function execute(array $input, MyronActionCallerContext $caller): MyronActionResult
    {
        return MyronActionResult::ok($this->service->deleteSubmission((string) $input['submissionId']));
    }
}
