<?php

use classes\economic;

class economic_m
{
    public economic $economic;
    /**
     * https://secure.e-conomic.com/secure/api1/requestaccess.aspx?appPublicToken=WeG89W2Y63wLjy1lnqfpsHlfa1mBiyNKByqtGmBOoOw&redirectUrl=truckwash.dk
     */
    private string $api_url = 'https://restapi.e-conomic.com';
    private string $appAccessGrant;
    private string $app_token;
    private string $appAccessGrant2;
    private static bool $reportedMissingRequiredCredentials = false;
    private static bool $reportedMissingGrant2 = false;

    public function __construct()
    {
        global $ECONOMIC_API;
        $this->app_token = (string)($ECONOMIC_API['app_secret_token'] ?? '');
        $this->appAccessGrant = (string)($ECONOMIC_API['app_access_grant'] ?? '');
        $this->appAccessGrant2 = (string)($ECONOMIC_API['app_access_grant2'] ?? '');
        $this->economic = new economic();
    }

    protected function resolve_app_secret_token(): string
    {
        $appSecretToken = trim($this->app_token);
        if ($appSecretToken === '') {
            if (!self::$reportedMissingRequiredCredentials) {
                error_log('[economic_m] Missing ECONOMIC_API_APP_SECRET_TOKEN. e-conomic requests will fail until configuration is fixed.');
                self::$reportedMissingRequiredCredentials = true;
            }
            throw new \RuntimeException('Missing e-conomic app secret token. Set ECONOMIC_API_APP_SECRET_TOKEN and recreate php containers.');
        }
        return $appSecretToken;
    }

    protected function resolve_agreement_grant_token(bool $authToken2): string
    {
        $primaryGrant = trim($this->appAccessGrant);
        $secondaryGrant = trim($this->appAccessGrant2);

        if ($primaryGrant === '') {
            if (!self::$reportedMissingRequiredCredentials) {
                error_log('[economic_m] Missing ECONOMIC_API_APP_ACCESS_GRANT. e-conomic requests will fail until configuration is fixed.');
                self::$reportedMissingRequiredCredentials = true;
            }
            throw new \RuntimeException('Missing e-conomic agreement grant token. Set ECONOMIC_API_APP_ACCESS_GRANT and recreate php containers.');
        }

        if ($authToken2 && $secondaryGrant !== '') {
            return $secondaryGrant;
        }

        if ($authToken2 && $secondaryGrant === '' && !self::$reportedMissingGrant2) {
            error_log('[economic_m] ECONOMIC_API_APP_ACCESS_GRANT2 is missing. Falling back to ECONOMIC_API_APP_ACCESS_GRANT.');
            self::$reportedMissingGrant2 = true;
        }

        return $primaryGrant;
    }

    /**
     * Allowed search filters
     * @return array
     */
    public function allowed_search_filters_customers(): array
    {
        return [
            'address', 'balance', 'barred', 'city', 'corporateIdentificationNumber', 'country', 'creditLimit', 'currency', 'customerGroup.customerGroupNumber', 'customerNumber', 'ean', 'email', 'lastUpdated', 'mobilePhone', 'name', 'publicEntryNumber', 'telephoneAndFaxNumber', 'vatNumber', 'website', 'zip'
        ];
    }

    /**
     * Send a request to the Economic API
     * @param string $url
     * @param string $method
     * @param string $data
     * @param bool $authToken2
     * @return string
     */
    protected function send_request($url, $method, $data = '', bool $authToken2 = false): string
    {
        $appSecretToken = $this->resolve_app_secret_token();
        $agreementGrantToken = $this->resolve_agreement_grant_token($authToken2);

        $curl = curl_init();
        curl_setopt_array($curl, array(
            CURLOPT_URL => $this->api_url . $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_ENCODING => '',
            CURLOPT_MAXREDIRS => 10,
            CURLOPT_CONNECTTIMEOUT => 3,
            CURLOPT_TIMEOUT => 30,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST => $method,
            CURLOPT_HTTPHEADER => array(
                'X-AppSecretToken: ' . $appSecretToken,
                'X-AgreementGrantToken: ' . $agreementGrantToken,
                'Content-Type: application/json'
            ),
        ));

        if ($method === 'POST') {
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }

        $response = curl_exec($curl);
        if ($response === false) {
            $error = curl_error($curl);
            curl_close($curl);
            throw new \RuntimeException('Curl error: ' . $error);
        }
        $httpStatusCode = (int)curl_getinfo($curl, CURLINFO_HTTP_CODE);
        curl_close($curl);

        return $this->assert_successful_response($httpStatusCode, $response);
    }

    /**
     * Validate e-conomic HTTP responses and convert upstream errors into deterministic runtime exceptions.
     */
    protected function assert_successful_response(int $httpStatusCode, string|false $response): string
    {
        if ($response === false) {
            throw new \RuntimeException('e-conomic request failed without a response body.');
        }

        if ($httpStatusCode >= 400) {
            throw new \RuntimeException($this->format_upstream_error_message($httpStatusCode, $response));
        }

        return $response;
    }

    /**
     * Build a sanitized error message from a non-2xx e-conomic response body.
     */
    protected function format_upstream_error_message(int $httpStatusCode, string $response): string
    {
        $prefix = 'e-conomic request failed with HTTP ' . $httpStatusCode;
        $decoded = json_decode($response, true);

        if (!is_array($decoded)) {
            return $prefix . '.';
        }

        $message = isset($decoded['message']) && is_string($decoded['message'])
            ? trim($decoded['message'])
            : 'Upstream e-conomic error';

        $details = [];

        if (isset($decoded['errors']) && is_array($decoded['errors'])) {
            $safeErrors = [];
            foreach ( $decoded['errors'] as $error ) {
                if (is_scalar($error)) {
                    $safeErrors[] = (string)$error;
                }
            }
            if (!empty($safeErrors)) {
                $details['errors'] = $safeErrors;
            }
        }

        if (isset($decoded['logId']) && is_scalar($decoded['logId'])) {
            $details['logId'] = (string)$decoded['logId'];
        }

        if (isset($decoded['httpStatusCode']) && is_numeric($decoded['httpStatusCode'])) {
            $details['httpStatusCode'] = (int)$decoded['httpStatusCode'];
        }

        if (empty($details)) {
            return $prefix . ': ' . $message;
        }

        return $prefix
            . ': '
            . $message
            . ' | details='
            . json_encode($details, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    }
}
