<?php

namespace BitApps\PiPro\src\Integrations\GoogleCalendar;

use BitApps\Pi\Helpers\Utility;
use BitApps\Pi\src\Authorization\AuthorizationFactory;
use BitApps\Pi\src\Authorization\AuthorizationType;
use BitApps\Pi\src\Flow\NodeInfoProvider;
use BitApps\Pi\src\Interfaces\ActionInterface;
use BitApps\PiPro\Deps\BitApps\WPKit\Http\Client\HttpClient;

if (!\defined('ABSPATH')) {
    exit;
}

class GoogleCalendarAction implements ActionInterface
{
    private NodeInfoProvider $nodeInfoProvider;

    private GoogleCalendarService $googleCalendarService;

    public function __construct(NodeInfoProvider $nodeInfoProvider)
    {
        $this->nodeInfoProvider = $nodeInfoProvider;
    }

    public function execute(): array
    {
        $executedNodeAction = $this->executeGoogleCalendarAction();

        return Utility::formatResponseData(
            $executedNodeAction['status_code'],
            $executedNodeAction['payload'],
            $executedNodeAction['response']
        );
    }

    private function executeMachine($machineSlug, $fieldMapData, $configs, $attendeeEmails)
    {
        $calendarId = $configs['calendar-id']['value'] ?? null;
        $eventFieldMapSwitch = $configs['select-event-toggle']['value'] ?? null;
        $calendarFieldMapSwitch = $configs['select-calendar-toggle']['value'] ?? null;

        switch ($machineSlug) {
            case 'createCalendar':
                return $this->googleCalendarService->createCalendar($fieldMapData);

            case 'createEvent':
                return $this->googleCalendarService->createEvent($fieldMapData, $calendarId, $attendeeEmails);

            case 'deleteEvent':
                $eventId = $fieldMapData['eventId'] ?? null;

                return $this->googleCalendarService->deleteEvent($calendarId, $eventId);

            case 'getEvent':
                return $this->googleCalendarService->getEvent($calendarId, $fieldMapData, $eventFieldMapSwitch);

            case 'getManyEvents':
                return $this->googleCalendarService->getEvents($calendarId, $fieldMapData);

            case 'updateEvent':
                $eventId = $configs['event-select']['value'];

                return $this->googleCalendarService->updateEvent($fieldMapData, $calendarId, $eventId);

            case 'duplicateEvent':
                return $this->googleCalendarService->duplicateEvent($calendarId, $fieldMapData);

            case 'findAvailability':
                return $this->googleCalendarService->findAvailability($calendarId, $fieldMapData);

            case 'listCalendars':
                return $this->googleCalendarService->listCalendars($fieldMapData);

            case 'deleteCalendar':
                return $this->googleCalendarService->deleteCalendar($fieldMapData, $calendarFieldMapSwitch);

            case 'clearCalendar':
                return $this->googleCalendarService->clearCalendar($fieldMapData, $calendarFieldMapSwitch);

            case 'updateCalendar':
                return $this->googleCalendarService->updateCalendar($fieldMapData, $calendarFieldMapSwitch);

            case 'createAccessControlRule':
                $calendarId = $configs['calendar-id']['value'] ?? null;

                return $this->googleCalendarService->createAccessControlRule($calendarId, $fieldMapData);

            case 'listAccessControlRules':
                $calendarId = $configs['calendar-id']['value'] ?? null;

                return $this->googleCalendarService->listAccessControlRules($calendarId);

            case 'getAccessControlRule':
                $calendarId = $configs['calendar-id']['value'] ?? null;
                $ruleId = $fieldMapData['aclRuleId'] ?? null;

                return $this->googleCalendarService->getAccessControlRule($calendarId, $ruleId);

            case 'deleteAccessControlRule':
                $calendarId = $configs['calendar-id']['value'] ?? null;
                $ruleId = $fieldMapData['aclRuleId'] ?? null;

                return $this->googleCalendarService->deleteAccessControlRule($calendarId, $ruleId);

            case 'addAttendeesToEvent':
                $calendarId = $configs['calendar-id']['value'] ?? null;

                return $this->googleCalendarService->addAttendeesToEvent($calendarId, $fieldMapData);

            case 'removeAttendeesFromEvent':
                $calendarId = $configs['calendar-id']['value'] ?? null;

                return $this->googleCalendarService->removeAttendeesFromEvent($calendarId, $fieldMapData);
        }
    }

    private function executeGoogleCalendarAction()
    {
        $machineSlug = $this->nodeInfoProvider->getMachineSlug();
        $configs = $this->nodeInfoProvider->getFieldMapConfigs();
        $fieldMapData = $this->nodeInfoProvider->getFieldMapData();
        $attendeeEmails = $this->nodeInfoProvider->getFieldMapRepeaters('attendees.value', false, false);

        $accessToken = AuthorizationFactory::getAuthorizationHandler(
            AuthorizationType::OAUTH2,
            $configs['connection-id']
        )->getAccessToken();

        $httpClient = new HttpClient(
            [
                'headers' => [
                    'Content-Type'  => 'application/json',
                    'Authorization' => $accessToken,
                ],
            ]
        );

        $this->googleCalendarService = new GoogleCalendarService($httpClient);

        return $this->executeMachine($machineSlug, $fieldMapData, $configs, $attendeeEmails);
    }
}
