<?php

namespace BitApps\PiPro\src\Integrations\Flowlu;

// Prevent direct script access
if (!defined('ABSPATH')) {
    exit;
}

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;
use InvalidArgumentException;

class FlowluAction implements ActionInterface
{
    private NodeInfoProvider $nodeInfoProvider;

    private FlowluAccountTypeService $accountTypeService;

    private FlowluCalendarService $calendarService;

    private FlowluOpportunitySourceService $opportunitySourceService;

    private FlowluOpportunityStageService $opportunityStageService;

    private FlowluPipelineService $pipelineService;

    private FlowluTaskService $taskService;

    private FlowluOpportunityService $opportunityService;

    private FlowluAccountService $accountService;

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

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

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

    private function executeFlowluAction()
    {
        $connectionId = $this->nodeInfoProvider->getFieldMapConfigs('connection-id.value');

        $tokenAuthorization = AuthorizationFactory::getAuthorizationHandler(
            AuthorizationType::OAUTH2,
            $connectionId
        );
        $authDetails = $tokenAuthorization->getAuthDetails();
        $domain = $authDetails['extraData']->domain ?? '';

        if (empty($domain)) {
            return [
                'response'    => ['success' => false, 'message' => 'Domain is required. Please set your Flowlu domain in the connection settings.'],
                'payload'     => [],
                'status_code' => 400
            ];
        }

        $accessToken = $tokenAuthorization->getAccessToken();

        $baseUrl = "https://{$domain}.flowlu.com/api/v1";

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

        $machineSlug = $this->nodeInfoProvider->getMachineSlug();

        $this->accountTypeService = new FlowluAccountTypeService($httpClient, $baseUrl, $this->nodeInfoProvider);
        $this->calendarService = new FlowluCalendarService($httpClient, $baseUrl, $this->nodeInfoProvider);
        $this->opportunitySourceService = new FlowluOpportunitySourceService($httpClient, $baseUrl, $this->nodeInfoProvider);
        $this->opportunityStageService = new FlowluOpportunityStageService($httpClient, $baseUrl, $this->nodeInfoProvider);
        $this->pipelineService = new FlowluPipelineService($httpClient, $baseUrl, $this->nodeInfoProvider);
        $this->taskService = new FlowluTaskService($httpClient, $baseUrl, $this->nodeInfoProvider);
        $this->opportunityService = new FlowluOpportunityService($httpClient, $baseUrl, $this->nodeInfoProvider);
        $this->accountService = new FlowluAccountService($httpClient, $baseUrl, $this->nodeInfoProvider);

        return $this->executeMachine($machineSlug);
    }

    private function executeMachine($machineSlug)
    {
        switch ($machineSlug) {
            // Account Type Actions
            case 'createAccountType':
                return $this->accountTypeService->createAccountType();
            case 'updateAccountType':
                return $this->accountTypeService->updateAccountType();
            case 'getAccountType':
                return $this->accountTypeService->getAccountType();
            case 'listAccountTypes':
                return $this->accountTypeService->listAccountTypes();
            case 'deleteAccountType':
                return $this->accountTypeService->deleteAccountType();

                // Calendar Actions
            case 'createCalendar':
                return $this->calendarService->createCalendar();
            case 'updateCalendar':
                return $this->calendarService->updateCalendar();
            case 'getCalendar':
                return $this->calendarService->getCalendar();
            case 'listCalendars':
                return $this->calendarService->listCalendars();
            case 'deleteCalendar':
                return $this->calendarService->deleteCalendar();

                // Opportunity Source Actions
            case 'createOpportunitySource':
                return $this->opportunitySourceService->createOpportunitySource();
            case 'updateOpportunitySource':
                return $this->opportunitySourceService->updateOpportunitySource();
            case 'getOpportunitySource':
                return $this->opportunitySourceService->getOpportunitySource();
            case 'listOpportunitySources':
                return $this->opportunitySourceService->listOpportunitySources();
            case 'deleteOpportunitySource':
                return $this->opportunitySourceService->deleteOpportunitySource();

                // Opportunity Stage Actions
            case 'createOpportunityStage':
                return $this->opportunityStageService->createOpportunityStage();
            case 'updateOpportunityStage':
                return $this->opportunityStageService->updateOpportunityStage();
            case 'getOpportunityStage':
                return $this->opportunityStageService->getOpportunityStage();
            case 'listOpportunityStages':
                return $this->opportunityStageService->listOpportunityStages();
            case 'deleteOpportunityStage':
                return $this->opportunityStageService->deleteOpportunityStage();

                // Pipeline Actions
            case 'createPipeline':
                return $this->pipelineService->createPipeline();
            case 'updatePipeline':
                return $this->pipelineService->updatePipeline();
            case 'getPipeline':
                return $this->pipelineService->getPipeline();
            case 'listPipelines':
                return $this->pipelineService->listPipelines();
            case 'deletePipeline':
                return $this->pipelineService->deletePipeline();

                // Task Actions
            case 'createTask':
                return $this->taskService->createTask();
            case 'updateTask':
                return $this->taskService->updateTask();
            case 'getTask':
                return $this->taskService->getTask();
            case 'listTasks':
                return $this->taskService->listTasks();
            case 'deleteTask':
                return $this->taskService->deleteTask();

                // Opportunity Actions
            case 'createOpportunity':
                return $this->opportunityService->createOpportunity();
            case 'updateOpportunity':
                return $this->opportunityService->updateOpportunity();
            case 'getOpportunity':
                return $this->opportunityService->getOpportunity();
            case 'listOpportunities':
                return $this->opportunityService->listOpportunities();
            case 'deleteOpportunity':
                return $this->opportunityService->deleteOpportunity();

                // Account Actions
            case 'createAccount':
                return $this->accountService->createAccount();
            case 'updateAccount':
                return $this->accountService->updateAccount();
            case 'getAccount':
                return $this->accountService->getAccount();
            case 'listAccounts':
                return $this->accountService->listAccounts();
            case 'deleteAccount':
                return $this->accountService->deleteAccount();

            default:
                throw new InvalidArgumentException('Invalid action requested');
        }
    }
}
