<?php

namespace BitApps\PiPro\src\Integrations\Airtable;

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

use BitApps\Pi\Helpers\MixInputHandler;
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 BitApps\PiPro\src\Integrations\Airtable\helper\AirtableFieldFormatter;
use InvalidArgumentException;

class AirtableAction implements ActionInterface
{
    public const BASE_URL = 'https://api.airtable.com/v0/';

    private NodeInfoProvider $nodeInfoProvider;

    private AirtableService $airtableService;

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

    public function execute(): array
    {
        $airtableAction = $this->nodeInfoProvider->getMachineSlug();

        // Get appropriate input based on action type
        if (\in_array($airtableAction, ['createRecord', 'updateRecord'], true)) {
            $payload = $this->nodeInfoProvider->getFieldMapRepeaters('record-fields.value', false, true, 'airtableFieldKey', 'value');
        } else {
            $payload = $this->nodeInfoProvider->getFieldMapData();
        }

        $response = $this->executeAirtableAction();

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

    /**
     * Convert stdClass objects to arrays recursively.
     *
     * @param mixed $data
     *
     * @return mixed
     */
    private function toArray($data)
    {
        if (\is_object($data)) {
            $data = (array) $data;
        }

        if (\is_array($data)) {
            return array_map([$this, 'toArray'], $data);
        }

        return $data;
    }

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

        $accessToken = AuthorizationFactory::getAuthorizationHandler(
            AuthorizationType::BEARER_TOKEN,
            $connectionId
        )->getAccessToken();

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

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

        $this->airtableService = new AirtableService($httpClient, static::BASE_URL);

        $baseId = $this->nodeInfoProvider->getFieldMapConfigs('base-id.value');
        $tableId = $this->nodeInfoProvider->getFieldMapConfigs('table-id.value');


        // Get field types from node info (stored by frontend)
        $fieldTypes = $this->nodeInfoProvider->getData()['db']['fieldTypes'] ?? [];

        switch ($airtableAction) {
            case 'createRecord':
                $fields = $this->nodeInfoProvider->getFieldMapRepeaters('record-fields.value', false, true, 'airtableFieldKey', 'value');

                // Format fields based on their Airtable field types
                $formattedFields = AirtableFieldFormatter::formatFields($fields, $fieldTypes);

                $recordsPayload = [['fields' => $formattedFields]];

                return $this->airtableService->createRecord($baseId, $tableId, $recordsPayload);

            case 'updateRecord':
                $mixInputRecordId = $this->nodeInfoProvider->getFieldMapConfigs('record-id.value');
                $recordId = MixInputHandler::replaceMixTagValue($mixInputRecordId);
                $fields = $this->nodeInfoProvider->getFieldMapRepeaters('record-fields.value', false, true, 'airtableFieldKey', 'value');

                // Format fields based on their Airtable field types
                $formattedFields = AirtableFieldFormatter::formatFields($fields, $fieldTypes);

                return $this->airtableService->updateRecord($baseId, $tableId, $recordId, $formattedFields);

            case 'deleteRecord':
                $mixInputRecordId = $this->nodeInfoProvider->getFieldMapConfigs('record-id.value');
                $recordId = MixInputHandler::replaceMixTagValue($mixInputRecordId);

                return $this->airtableService->deleteRecord($baseId, $tableId, $recordId);

            case 'searchRecord':
                $mixInputRecordId = $this->nodeInfoProvider->getFieldMapConfigs('record-id.value');
                $recordId = MixInputHandler::replaceMixTagValue($mixInputRecordId);

                return $this->airtableService->searchRecord($baseId, $tableId, $recordId);

            case 'getRecords':
                return $this->airtableService->getRecords($baseId, $tableId);

            default:
                throw new InvalidArgumentException("Unknown action: {$airtableAction}");
        }
    }
}
