<?php

namespace bird\helpers;

class bird_request_schemas
{
    public static function noBody(): array
    {
        return [
            'type' => 'object',
            'additionalProperties' => false,
            'properties' => [],
        ];
    }

    public static function voiceCreateCallBody(): array
    {
        return [
            'type' => 'object',
            'additionalProperties' => false,
            'required' => ['to'],
            'properties' => [
                'from' => ['type' => 'string', 'minLength' => 1, 'maxLength' => 100],
                'to' => ['type' => 'string', 'minLength' => 1, 'maxLength' => 100],
                'ringTimeout' => ['type' => 'integer', 'min' => 3, 'max' => 120],
                'maxDuration' => ['type' => 'integer', 'min' => 1],
                'sendKeys' => ['type' => 'string', 'maxLength' => 20, 'pattern' => '^[0-9*#]+$'],
                'record' => ['type' => 'boolean'],
                'recordStart' => ['type' => 'string', 'enum' => ['record-from-answer', 'record-from-ringing']],
                'flowStart' => ['type' => 'string', 'enum' => ['from-answer', 'from-ringing']],
                'stereo' => ['type' => 'boolean'],
                'callFlow' => self::callFlowCommands(),
                'scheduledFor' => ['type' => 'string', 'format' => 'date-time'],
                'notification' => self::notificationSchema(),
                'amdSettings' => self::amdSettingsSchema(),
                'tags' => ['type' => 'array', 'maxItems' => 10, 'items' => ['type' => 'string', 'minLength' => 1, 'maxLength' => 64]],
            ],
        ];
    }

    public static function voiceListCallsQuery(): array
    {
        return [
            'type' => 'object',
            'additionalProperties' => false,
            'properties' => [
                'limit' => ['type' => 'integer', 'min' => 1, 'max' => 1000],
                'pageToken' => ['type' => 'string', 'maxLength' => 8000],
                'startAt' => ['type' => 'string', 'format' => 'date-time'],
                'endAt' => ['type' => 'string', 'format' => 'date-time'],
                'status' => ['type' => 'string', 'enum' => self::callStatuses()],
                'type' => ['type' => 'string', 'enum' => ['pstn', 'sip', 'webrtc']],
                'to' => ['type' => 'string', 'minLength' => 1, 'maxLength' => 100],
                'from' => ['type' => 'string', 'minLength' => 1, 'maxLength' => 100],
                'duration' => ['type' => 'integer', 'min' => 0],
                'direction' => ['type' => 'string', 'enum' => ['incoming', 'outgoing']],
                'id' => ['type' => 'string', 'format' => 'uuid'],
                'tag' => ['type' => 'array', 'csv' => true, 'items' => ['type' => 'string', 'minLength' => 1, 'maxLength' => 64]],
            ],
        ];
    }

    public static function voiceUpdateCallBody(): array
    {
        return [
            'type' => 'object',
            'additionalProperties' => false,
            'properties' => [
                'status' => ['type' => 'string', 'nullable' => true, 'enum' => ['completed']],
                'callFlow' => self::callFlowCommands(),
            ],
        ];
    }

    public static function voiceHangupBody(): array
    {
        return [
            'type' => 'object',
            'additionalProperties' => false,
            'properties' => [
                'cause' => ['type' => 'string', 'enum' => ['rejected', 'busy']],
            ],
        ];
    }

    public static function voicePlaybackBody(): array
    {
        return [
            'type' => 'object',
            'additionalProperties' => false,
            'required' => ['media'],
            'properties' => [
                'media' => ['type' => 'array', 'minItems' => 1, 'maxItems' => 80, 'items' => ['type' => 'string', 'minLength' => 1]],
                'loop' => ['type' => 'integer', 'min' => 0],
                'timeout' => ['type' => 'integer', 'min' => 0],
                'pauseMilliseconds' => ['type' => 'integer', 'min' => 0, 'max' => 30000],
            ],
        ];
    }

    public static function voiceSayBody(): array
    {
        return [
            'type' => 'object',
            'additionalProperties' => false,
            'required' => ['text'],
            'properties' => [
                'text' => ['type' => 'string', 'minLength' => 1],
                'locale' => ['type' => 'string', 'minLength' => 2, 'maxLength' => 20],
                'voice' => ['type' => 'string', 'minLength' => 1, 'maxLength' => 64],
                'loop' => ['type' => 'integer', 'min' => 0],
                'timeout' => ['type' => 'integer', 'min' => 0],
                'hangup' => ['type' => 'boolean'],
            ],
        ];
    }

    public static function voiceGatherBody(): array
    {
        return [
            'type' => 'object',
            'additionalProperties' => false,
            'properties' => [
                'maxNumKeys' => ['type' => 'integer', 'min' => 1],
                'endKey' => ['type' => 'string', 'enum' => self::digitEnums()],
                'timeout' => ['type' => 'integer', 'min' => 0],
                'retries' => ['type' => 'integer', 'min' => 0],
                'input' => ['type' => 'string', 'enum' => ['dtmf', 'speech', 'dtmf speech']],
                'speechLocale' => ['type' => 'string', 'minLength' => 2, 'maxLength' => 20],
                'playback' => self::voicePlaybackBody(),
                'say' => self::voiceSayBody(),
            ],
        ];
    }

    public static function voiceBridgeBody(): array
    {
        return [
            'type' => 'object',
            'additionalProperties' => false,
            'required' => ['to'],
            'properties' => [
                'from' => ['type' => 'string', 'minLength' => 1, 'maxLength' => 100],
                'to' => ['type' => 'string', 'minLength' => 1, 'maxLength' => 100],
                'ringTimeout' => ['type' => 'integer', 'min' => 3, 'max' => 120],
                'maxDuration' => ['type' => 'integer', 'min' => 1],
                'ringTone' => ['type' => 'string', 'enum' => ['be', 'ca', 'cn', 'cy', 'cz', 'de', 'dk', 'dz', 'eg', 'fi', 'fr', 'hk', 'hu', 'il', 'in', 'jp', 'ko', 'pk', 'pl', 'ro', 'rs', 'ru', 'sa', 'tr', 'uk', 'us']],
                'hangupAfterBridge' => ['type' => 'boolean'],
                'record' => ['type' => 'boolean'],
                'recordStart' => ['type' => 'string', 'enum' => ['record-from-answer', 'record-from-ringing']],
                'recordStereo' => ['type' => 'boolean'],
                'callFlow' => self::callFlowCommands(),
                'notification' => self::notificationSchema(),
                'amdSettings' => self::amdSettingsSchema(),
            ],
        ];
    }

    public static function voiceRecordBody(): array
    {
        return [
            'type' => 'object',
            'additionalProperties' => false,
            'properties' => [
                'endKey' => ['type' => 'string', 'enum' => self::digitEnums()],
                'maxLength' => ['type' => 'integer', 'min' => 1],
                'timeout' => ['type' => 'integer', 'min' => 0],
                'beep' => ['type' => 'boolean'],
                'transcribe' => ['type' => 'boolean'],
                'transcribeLocale' => ['type' => 'string', 'minLength' => 2, 'maxLength' => 20],
            ],
        ];
    }

    public static function voiceRecordingsCreateBody(): array
    {
        return [
            'type' => 'object',
            'additionalProperties' => false,
            'properties' => [
                'maxLength' => ['type' => 'integer', 'min' => 1],
                'stereo' => ['type' => 'boolean'],
            ],
        ];
    }

    public static function voiceRecordingsListQuery(): array
    {
        return [
            'type' => 'object',
            'additionalProperties' => false,
            'properties' => [
                'limit' => ['type' => 'integer', 'min' => 1, 'max' => 1000],
                'pageToken' => ['type' => 'string', 'maxLength' => 8000],
            ],
        ];
    }

    public static function voiceRecordingUpdateBody(): array
    {
        return [
            'type' => 'object',
            'additionalProperties' => false,
            'required' => ['status'],
            'properties' => [
                'status' => ['type' => 'string', 'enum' => ['paused', 'ongoing', 'completed']],
            ],
        ];
    }

    public static function voiceCallsLogQuery(): array
    {
        return [
            'type' => 'object',
            'additionalProperties' => false,
            'properties' => [
                'limit' => ['type' => 'integer', 'min' => 1, 'max' => 1000],
                'pageToken' => ['type' => 'string', 'maxLength' => 8000],
                'startAt' => ['type' => 'string', 'format' => 'date-time'],
                'endAt' => ['type' => 'string', 'format' => 'date-time'],
                'channelId' => ['type' => 'array', 'csv' => true, 'items' => ['type' => 'string', 'format' => 'uuid']],
                'status' => ['type' => 'string', 'enum' => self::callStatuses()],
                'type' => ['type' => 'string', 'enum' => ['pstn', 'sip', 'webrtc']],
                'to' => ['type' => 'string', 'minLength' => 1, 'maxLength' => 100],
                'from' => ['type' => 'string', 'minLength' => 1, 'maxLength' => 100],
                'duration' => ['type' => 'integer', 'min' => 0],
                'direction' => ['type' => 'string', 'enum' => ['incoming', 'outgoing']],
                'id' => ['type' => 'string', 'format' => 'uuid'],
                'tag' => ['type' => 'array', 'csv' => true, 'items' => ['type' => 'string', 'minLength' => 1, 'maxLength' => 64]],
            ],
        ];
    }

    public static function voiceTestOutboundBody(): array
    {
        $create = self::voiceCreateCallBody();
        $properties = isset($create['properties']) && is_array($create['properties']) ? $create['properties'] : [];

        $properties['timeout'] = ['type' => 'integer', 'min' => 1];
        $properties['pollIntervalSeconds'] = ['type' => 'integer', 'min' => 1];
        $properties['maxPollSeconds'] = ['type' => 'integer', 'min' => 5];
        $properties['hangupCause'] = ['type' => 'string', 'enum' => ['rejected', 'busy']];

        return [
            'type' => 'object',
            'additionalProperties' => false,
            'properties' => $properties,
        ];
    }

    public static function flashCreateBody(): array
    {
        return [
            'type' => 'object',
            'additionalProperties' => false,
            'required' => ['to'],
            'properties' => [
                'from' => ['type' => 'string', 'minLength' => 1, 'maxLength' => 100],
                'to' => ['type' => 'string', 'minLength' => 1, 'maxLength' => 100],
                'ringTimeout' => ['type' => 'integer', 'min' => 3, 'max' => 120],
            ],
        ];
    }

    public static function flashListQuery(): array
    {
        return [
            'type' => 'object',
            'additionalProperties' => false,
            'properties' => [
                'limit' => ['type' => 'integer', 'min' => 1, 'max' => 1000],
                'pageToken' => ['type' => 'string', 'maxLength' => 8000],
                'startAt' => ['type' => 'string', 'format' => 'date-time'],
                'endAt' => ['type' => 'string', 'format' => 'date-time'],
                'status' => ['type' => 'string', 'enum' => self::callStatuses()],
                'to' => ['type' => 'string', 'minLength' => 1, 'maxLength' => 100],
                'from' => ['type' => 'string', 'minLength' => 1, 'maxLength' => 100],
                'duration' => ['type' => 'integer', 'min' => 0],
                'id' => ['type' => 'string', 'format' => 'uuid'],
            ],
        ];
    }

    public static function flashEndBody(): array
    {
        return [
            'type' => 'object',
            'additionalProperties' => false,
            'required' => ['result'],
            'properties' => [
                'receivedCli' => ['type' => 'string', 'minLength' => 1, 'maxLength' => 100],
                'result' => ['type' => 'string', 'enum' => ['unknown', 'verified', 'canceled', 'timeout', 'wrong_cli']],
            ],
        ];
    }

    public static function flashHangupBody(): array
    {
        return [
            'oneOf' => [
                [
                    'type' => 'object',
                    'additionalProperties' => false,
                    'required' => ['result'],
                    'properties' => [
                        'receivedCli' => ['type' => 'string', 'minLength' => 1, 'maxLength' => 100],
                        'result' => ['type' => 'string', 'enum' => ['unknown', 'verified', 'canceled', 'timeout', 'wrong_cli']],
                    ],
                ],
                [
                    'type' => 'object',
                    'additionalProperties' => false,
                    'required' => ['from', 'to'],
                    'properties' => [
                        'from' => ['type' => 'string', 'minLength' => 1, 'maxLength' => 100],
                        'to' => ['type' => 'string', 'minLength' => 1, 'maxLength' => 100],
                        'receivedCli' => ['type' => 'string', 'minLength' => 1, 'maxLength' => 100],
                        'result' => ['type' => 'string', 'enum' => ['unknown', 'verified', 'canceled', 'timeout', 'wrong_cli']],
                    ],
                ],
            ],
        ];
    }

    private static function callFlowCommands(): array
    {
        return [
            'type' => 'array',
            'maxItems' => 20,
            'items' => self::callFlowCommandSchema(),
        ];
    }

    private static function callFlowCommandSchema(): array
    {
        return [
            'type' => 'object',
            'additionalProperties' => false,
            'required' => ['command'],
            'properties' => [
                'command' => [
                    'type' => 'string',
                    'enum' => ['answer', 'hangup', 'playback', 'say', 'gather', 'record', 'bridge', 'pause', 'ringing'],
                ],
                'conditions' => [
                    'type' => 'array',
                    'items' => [
                        'type' => 'object',
                        'additionalProperties' => false,
                        'required' => ['variable', 'operator', 'value'],
                        'properties' => [
                            'variable' => ['type' => 'string', 'minLength' => 1, 'maxLength' => 64],
                            'operator' => ['type' => 'string', 'minLength' => 1, 'maxLength' => 16],
                            'value' => ['type' => 'string', 'minLength' => 1, 'maxLength' => 255],
                        ],
                    ],
                ],
                'options' => [
                    'type' => 'object',
                    'additionalProperties' => true,
                    'properties' => [],
                ],
            ],
        ];
    }

    private static function notificationSchema(): array
    {
        return [
            'type' => 'object',
            'additionalProperties' => false,
            'required' => ['url'],
            'properties' => [
                'url' => ['type' => 'string', 'minLength' => 1, 'maxLength' => 2048],
            ],
        ];
    }

    private static function amdSettingsSchema(): array
    {
        return [
            'type' => 'object',
            'additionalProperties' => false,
            'properties' => [
                'enabled' => ['type' => 'boolean'],
                'wordCount' => ['type' => 'integer', 'min' => 1],
                'speechTimeout' => ['type' => 'integer', 'min' => 1],
                'speechLocale' => ['type' => 'string', 'minLength' => 2, 'maxLength' => 20],
                'beepTimeout' => ['type' => 'integer', 'min' => 1],
                'ifMachineNotifyAfter' => ['type' => 'string', 'enum' => ['wordCount', 'beep']],
            ],
        ];
    }

    private static function callStatuses(): array
    {
        return ['accepted', 'starting', 'ringing', 'ongoing', 'completed', 'no-answer', 'busy', 'failed', 'cancelled', 'scheduled'];
    }

    private static function digitEnums(): array
    {
        return ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '*', '#'];
    }
}
