<?php

namespace routes;

require_once WD . '/classes/bird.php';
require_once WD . '/traits/route_t.php';
require_once WD . '/traits/bird_route_helpers_t.php';
require_once WD . '/traits/bird_route_validation_t.php';
require_once WD . '/modules/bird/helpers/bird_request_schemas.php';
require_once WD . '/modules/bird/helpers/bird_payloads.php';

use bird\helpers\bird_no_body_payload;
use bird\helpers\bird_request_schemas;
use bird\helpers\bird_voice_bridge_payload;
use bird\helpers\bird_voice_calls_log_query_payload;
use bird\helpers\bird_voice_create_call_payload;
use bird\helpers\bird_voice_gather_payload;
use bird\helpers\bird_voice_hangup_payload;
use bird\helpers\bird_voice_list_calls_query_payload;
use bird\helpers\bird_voice_playback_payload;
use bird\helpers\bird_voice_record_payload;
use bird\helpers\bird_voice_recording_update_payload;
use bird\helpers\bird_voice_recordings_create_payload;
use bird\helpers\bird_voice_recordings_list_query_payload;
use bird\helpers\bird_voice_say_payload;
use bird\helpers\bird_voice_test_outbound_payload;
use bird\helpers\bird_voice_update_call_payload;
use classes\bird;
use traits\bird_route_helpers_t;
use traits\bird_route_validation_t;
use traits\route_t;

class birdVoiceCallsRoute
{
    use route_t, bird_route_helpers_t, bird_route_validation_t;

    public function run(): void
    {
        // List workspace call log
        $this->get('/bird/voice/calls/log', function () {
            global $response;
            self::requirePermission('modules_bird_voice_calls_log_list');

            $client = new bird();
            $workspaceId = $this->birdResolveWorkspaceId($client);

            $query = $this->birdPayloadWithout(['workspaceId', 'channelId']);
            $query = $this->birdNormalizeCsvField($query, 'channelId');
            $query = $this->birdNormalizeCsvField($query, 'tag');
            $query = $this->birdValidateSchema($query, bird_request_schemas::voiceCallsLogQuery());
            $query = bird_voice_calls_log_query_payload::fromArray($query)->toArray();

            $res = $client->getVoiceCallsLog($workspaceId, $query);
            $response->success($res ?? []);
        }, [
            'modules_bird_voice_calls_log_list' => 'List voice call log entries via Bird',
        ]);

        // Create a voice call
        $this->post('/bird/voice/calls', function () {
            global $response;
            self::requirePermission('modules_bird_voice_calls_create');

            $client = new bird();
            [$workspaceId, $channelId] = $this->birdResolveWorkspaceAndChannelIds($client);

            $payload = $this->birdPayloadWithout(['workspaceId', 'channelId']);
            $payload = $this->birdValidateSchema($payload, bird_request_schemas::voiceCreateCallBody());
            $payload = bird_voice_create_call_payload::fromArray($payload)->toArray();

            $res = $client->createVoiceCall($workspaceId, $channelId, $payload);
            $response->success($res ?? ['status' => 'ok']);
        }, [
            'modules_bird_voice_calls_create' => 'Create/place a voice call via Bird',
        ]);

        // List voice calls
        $this->get('/bird/voice/calls', function () {
            global $response;
            self::requirePermission('modules_bird_voice_calls_list');

            $client = new bird();
            [$workspaceId, $channelId] = $this->birdResolveWorkspaceAndChannelIds($client);

            $query = $this->birdPayloadWithout(['workspaceId', 'channelId']);
            $query = $this->birdNormalizeCsvField($query, 'tag');
            $query = $this->birdValidateSchema($query, bird_request_schemas::voiceListCallsQuery());
            $query = bird_voice_list_calls_query_payload::fromArray($query)->toArray();

            $res = $client->listVoiceCalls($workspaceId, $channelId, $query);
            $response->success($res ?? []);
        }, [
            'modules_bird_voice_calls_list' => 'List voice calls via Bird',
        ]);

        // Get a voice call by ID
        $this->get('/bird/voice/calls/{id}', function () {
            global $response;
            self::requirePermission('modules_bird_voice_calls_get');

            $client = new bird();
            [$workspaceId, $channelId] = $this->birdResolveWorkspaceAndChannelIds($client);
            $callId = $this->birdResolveRouteCallId();

            $res = $client->getVoiceCall($workspaceId, $channelId, $callId);
            $response->success($res ?? []);
        }, [
            'modules_bird_voice_calls_get' => 'Get a voice call by ID via Bird',
        ]);

        // Update a voice call by ID
        $this->patch('/bird/voice/calls/{id}', function () {
            global $response;
            self::requirePermission('modules_bird_voice_calls_update');

            $client = new bird();
            [$workspaceId, $channelId] = $this->birdResolveWorkspaceAndChannelIds($client);
            $callId = $this->birdResolveRouteCallId();

            $payload = $this->birdPayloadWithout(['workspaceId', 'channelId']);
            $payload = $this->birdValidateSchema($payload, bird_request_schemas::voiceUpdateCallBody());
            $payload = bird_voice_update_call_payload::fromArray($payload)->toArray();

            $res = $client->updateVoiceCall($workspaceId, $channelId, $callId, $payload);
            $response->success($res ?? ['status' => 'ok']);
        }, [
            'modules_bird_voice_calls_update' => 'Update a voice call by ID via Bird',
        ]);

        // Answer an incoming call by ID
        $this->post('/bird/voice/calls/{id}/answer', function () {
            global $response;
            self::requirePermission('modules_bird_voice_calls_answer');

            $client = new bird();
            [$workspaceId, $channelId] = $this->birdResolveWorkspaceAndChannelIds($client);
            $callId = $this->birdResolveRouteCallId();

            $payload = $this->birdPayloadWithout(['workspaceId', 'channelId']);
            $payload = $this->birdValidateSchema($payload, bird_request_schemas::noBody());
            $payload = bird_no_body_payload::fromArray($payload)->toArray();

            $res = $client->answerVoiceCall($workspaceId, $channelId, $callId, $payload);
            $response->success($res ?? ['status' => 'ok']);
        }, [
            'modules_bird_voice_calls_answer' => 'Answer a voice call by ID via Bird',
        ]);

        // Mark call as ringing by ID
        $this->post('/bird/voice/calls/{id}/ringing', function () {
            global $response;
            self::requirePermission('modules_bird_voice_calls_ringing');

            $client = new bird();
            [$workspaceId, $channelId] = $this->birdResolveWorkspaceAndChannelIds($client);
            $callId = $this->birdResolveRouteCallId();

            $payload = $this->birdPayloadWithout(['workspaceId', 'channelId']);
            $payload = $this->birdValidateSchema($payload, bird_request_schemas::noBody());
            $payload = bird_no_body_payload::fromArray($payload)->toArray();

            $res = $client->ringVoiceCall($workspaceId, $channelId, $callId, $payload);
            $response->success($res ?? ['status' => 'ok']);
        }, [
            'modules_bird_voice_calls_ringing' => 'Mark a voice call as ringing via Bird',
        ]);

        // Hang up an active call by ID
        $this->post('/bird/voice/calls/{id}/hangup', function () {
            global $response;
            self::requirePermission('modules_bird_voice_calls_hangup');

            $client = new bird();
            [$workspaceId, $channelId] = $this->birdResolveWorkspaceAndChannelIds($client);
            $callId = $this->birdResolveRouteCallId();

            $payload = $this->birdPayloadWithout(['workspaceId', 'channelId']);
            $payload = $this->birdValidateSchema($payload, bird_request_schemas::voiceHangupBody());
            $payload = bird_voice_hangup_payload::fromArray($payload)->toArray();

            $res = $client->hangupVoiceCall($workspaceId, $channelId, $callId, $payload);
            $response->success($res ?? ['status' => 'ok']);
        }, [
            'modules_bird_voice_calls_hangup' => 'Hang up a voice call by ID via Bird',
        ]);

        // Playback media on an active call by ID
        $this->post('/bird/voice/calls/{id}/playback', function () {
            global $response;
            self::requirePermission('modules_bird_voice_calls_playback');

            $client = new bird();
            [$workspaceId, $channelId] = $this->birdResolveWorkspaceAndChannelIds($client);
            $callId = $this->birdResolveRouteCallId();

            $payload = $this->birdPayloadWithout(['workspaceId', 'channelId']);
            $payload = $this->birdValidateSchema($payload, bird_request_schemas::voicePlaybackBody());
            $payload = bird_voice_playback_payload::fromArray($payload)->toArray();

            $res = $client->playbackVoiceCall($workspaceId, $channelId, $callId, $payload);
            $response->success($res ?? ['status' => 'ok']);
        }, [
            'modules_bird_voice_calls_playback' => 'Playback media on a voice call by ID via Bird',
        ]);

        // Say a message on an active call
        $this->post('/bird/voice/calls/{id}/say', function () {
            global $response;
            self::requirePermission('modules_bird_voice_calls_say');

            $client = new bird();
            [$workspaceId, $channelId] = $this->birdResolveWorkspaceAndChannelIds($client);
            $callId = $this->birdResolveRouteCallId();

            $payload = $this->birdPayloadWithout(['workspaceId', 'channelId']);
            $payload = $this->birdValidateSchema($payload, bird_request_schemas::voiceSayBody());
            $payload = bird_voice_say_payload::fromArray($payload)->toArray();

            $res = $client->sayMessage($workspaceId, $channelId, $callId, $payload);
            $response->success($res ?? ['status' => 'ok']);
        }, [
            'modules_bird_voice_calls_say' => 'Say a message on a voice call by ID via Bird',
        ]);

        // Gather input on an active call
        $this->post('/bird/voice/calls/{id}/gather', function () {
            global $response;
            self::requirePermission('modules_bird_voice_calls_gather');

            $client = new bird();
            [$workspaceId, $channelId] = $this->birdResolveWorkspaceAndChannelIds($client);
            $callId = $this->birdResolveRouteCallId();

            $payload = $this->birdPayloadWithout(['workspaceId', 'channelId']);
            $payload = $this->birdValidateSchema($payload, bird_request_schemas::voiceGatherBody());
            $payload = bird_voice_gather_payload::fromArray($payload)->toArray();

            $res = $client->gatherMessage($workspaceId, $channelId, $callId, $payload);
            $response->success($res ?? ['status' => 'ok']);
        }, [
            'modules_bird_voice_calls_gather' => 'Gather input on a voice call by ID via Bird',
        ]);

        // Bridge current call to another destination
        $this->post('/bird/voice/calls/{id}/bridge', function () {
            global $response;
            self::requirePermission('modules_bird_voice_calls_bridge');

            $client = new bird();
            [$workspaceId, $channelId] = $this->birdResolveWorkspaceAndChannelIds($client);
            $callId = $this->birdResolveRouteCallId();

            $payload = $this->birdPayloadWithout(['workspaceId', 'channelId']);
            $payload = $this->birdValidateSchema($payload, bird_request_schemas::voiceBridgeBody());
            $payload = bird_voice_bridge_payload::fromArray($payload)->toArray();

            $res = $client->bridgeVoiceCall($workspaceId, $channelId, $callId, $payload);
            $response->success($res ?? ['status' => 'ok']);
        }, [
            'modules_bird_voice_calls_bridge' => 'Bridge a voice call by ID via Bird',
        ]);

        // Record call command endpoint
        $this->post('/bird/voice/calls/{id}/record', function () {
            global $response;
            self::requirePermission('modules_bird_voice_calls_record');

            $client = new bird();
            [$workspaceId, $channelId] = $this->birdResolveWorkspaceAndChannelIds($client);
            $callId = $this->birdResolveRouteCallId();

            $payload = $this->birdPayloadWithout(['workspaceId', 'channelId']);
            $payload = $this->birdValidateSchema($payload, bird_request_schemas::voiceRecordBody());
            $payload = bird_voice_record_payload::fromArray($payload)->toArray();

            $res = $client->recordVoiceCall($workspaceId, $channelId, $callId, $payload);
            $response->success($res ?? ['status' => 'ok']);
        }, [
            'modules_bird_voice_calls_record' => 'Record a voice call by ID via Bird',
        ]);

        // Start call recording session
        $this->post('/bird/voice/calls/{id}/recordings', function () {
            global $response;
            self::requirePermission('modules_bird_voice_calls_recordings_create');

            $client = new bird();
            [$workspaceId, $channelId] = $this->birdResolveWorkspaceAndChannelIds($client);
            $callId = $this->birdResolveRouteCallId();

            $payload = $this->birdPayloadWithout(['workspaceId', 'channelId']);
            $payload = $this->birdValidateSchema($payload, bird_request_schemas::voiceRecordingsCreateBody());
            $payload = bird_voice_recordings_create_payload::fromArray($payload)->toArray();

            $res = $client->createVoiceCallRecordingSession($workspaceId, $channelId, $callId, $payload);
            $response->success($res ?? ['status' => 'ok']);
        }, [
            'modules_bird_voice_calls_recordings_create' => 'Create a voice call recording session via Bird',
        ]);

        // List call recordings
        $this->get('/bird/voice/calls/{id}/recordings', function () {
            global $response;
            self::requirePermission('modules_bird_voice_calls_recordings_list');

            $client = new bird();
            [$workspaceId, $channelId] = $this->birdResolveWorkspaceAndChannelIds($client);
            $callId = $this->birdResolveRouteCallId();

            $query = $this->birdPayloadWithout(['workspaceId', 'channelId']);
            $query = $this->birdValidateSchema($query, bird_request_schemas::voiceRecordingsListQuery());
            $query = bird_voice_recordings_list_query_payload::fromArray($query)->toArray();

            $res = $client->listVoiceCallRecordings($workspaceId, $channelId, $callId, $query);
            $response->success($res ?? []);
        }, [
            'modules_bird_voice_calls_recordings_list' => 'List voice call recordings via Bird',
        ]);

        // Get single call recording
        $this->get('/bird/voice/calls/{id}/recordings/{recordingId}', function () {
            global $response;
            self::requirePermission('modules_bird_voice_calls_recordings_get');

            $client = new bird();
            [$workspaceId, $channelId] = $this->birdResolveWorkspaceAndChannelIds($client);
            $callId = $this->birdResolveRouteCallId();
            $recordingId = $this->birdResolveRouteRecordingId();

            $res = $client->getVoiceCallRecording($workspaceId, $channelId, $callId, $recordingId);
            $response->success($res ?? []);
        }, [
            'modules_bird_voice_calls_recordings_get' => 'Get a voice call recording by ID via Bird',
        ]);

        // Update single call recording
        $this->patch('/bird/voice/calls/{id}/recordings/{recordingId}', function () {
            global $response;
            self::requirePermission('modules_bird_voice_calls_recordings_update');

            $client = new bird();
            [$workspaceId, $channelId] = $this->birdResolveWorkspaceAndChannelIds($client);
            $callId = $this->birdResolveRouteCallId();
            $recordingId = $this->birdResolveRouteRecordingId();

            $payload = $this->birdPayloadWithout(['workspaceId', 'channelId']);
            $payload = $this->birdValidateSchema($payload, bird_request_schemas::voiceRecordingUpdateBody());
            $payload = bird_voice_recording_update_payload::fromArray($payload)->toArray();

            $res = $client->updateVoiceCallRecording($workspaceId, $channelId, $callId, $recordingId, $payload);
            $response->success($res ?? ['status' => 'ok']);
        }, [
            'modules_bird_voice_calls_recordings_update' => 'Update a voice call recording via Bird',
        ]);

        // Get call insights
        $this->get('/bird/voice/calls/{id}/insights', function () {
            global $response;
            self::requirePermission('modules_bird_voice_calls_insights_get');

            $client = new bird();
            [$workspaceId, $channelId] = $this->birdResolveWorkspaceAndChannelIds($client);
            $callId = $this->birdResolveRouteCallId();

            $res = $client->getVoiceCallInsights($workspaceId, $channelId, $callId);
            $response->success($res ?? []);
        }, [
            'modules_bird_voice_calls_insights_get' => 'Get voice call insights by call ID via Bird',
        ]);

        // Place test outbound call and hang up when accepted
        $this->post('/bird/voice/calls/test-outbound', function () {
            global $response;
            self::requirePermission('modules_bird_voice_calls_test_outbound');

            $client = new bird();
            [$workspaceId, $channelId] = $this->birdResolveWorkspaceAndChannelIds($client);

            $payload = $this->birdPayloadWithout(['workspaceId', 'channelId']);
            $payload = $this->birdValidateSchema($payload, bird_request_schemas::voiceTestOutboundBody());
            $payload = bird_voice_test_outbound_payload::fromArray($payload)->toArray();

            try {
                $result = $client->createOutboundTestCallAndHangupWhenAccepted($workspaceId, $channelId, $payload);
                $response->success($result);
            } catch (\Throwable $e) {
                $response->error($e->getMessage(), 500);
            }
        }, [
            'modules_bird_voice_calls_test_outbound' => 'Place a test outbound call and hang up when accepted',
        ]);
    }
}
