<?php
/**
 * Api.php
 *
 * @since      1.0.0
 * @package    POPToFattureInCloud
 * @author     alfiopiccione <alfio.piccione@gmail.com>

 * @license    http://opensource.org/licenses/gpl-2.0.php GPL v2
 *
 * Copyright (C) 2025 POP
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

namespace WooPoPToFattureInCloud;

use FattureInCloud\Api\InfoApi;
use function WooPoPToFattureInCloud\Functions\buildFicVatTypeListCache;
use function WooPoPToFattureInCloud\Functions\filterInput;
use function WooPoPToFattureInCloud\Functions\getActiveApi;
use function WooPoPToFattureInCloud\Functions\getKey;
use function WooPoPToFattureInCloud\Functions\getUserAndCompanies;
use function WooPoPToFattureInCloud\Functions\settingsCompany;

if (! defined('ABSPATH')) {
    exit; // Exit if accessed directly.
}

/**
 * Class Api
 *
 * V2 api: https://api-v2.fattureincloud.it
 *
 * @author alfiopiccione <alfio.piccione@gmail.com>
 */
final class Api
{
    /**
     * Routes
     *
     * @var array|string[]
     */
    public static $routes = array(
        'oauth_authorize' => 'oauth/authorize',
        'oauth_device'    => 'oauth/device',
        'oauth_token'     => 'oauth/token',
        'user_info'       => 'user/info',
        'user_companies'  => 'user/companies',
    );

    /**
     * OAuth2 mode
     * 1. oauth_device
     * 2. oauth_token (dev mode)
     *
     * @var string
     */
    public static $oauthFlow = 'oauth_device';

    /**
     * POP to Fic public app client_id
     *
     * @var string
     */
    private static $clientID = "JL5t5HYvZyJh5bsaVukHuSDBd3tPor5k";

    /**
     * Regex SDI Code
     *
     * @since 1.0.0
     *
     * @var string
     */
    public static $regexWEBSERV = "/^[a-zA-Z0-9]{7}$/i";

    /**
     * Regex PEC
     *
     * @since 1.0.0
     *
     * @var string
     */
    public static $regexPEC = "/^(?:[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*|\"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*\")@(?:\w*.?pec(?:.?\w+)*)$/i";

    /**
     * Regex Legal Mail
     *
     * @since 1.0.0
     *
     * @var string
     */
    public static $regexLEGALMAIL = "/^(?:[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*|\"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*\")@(?:\w*.?legalmail(?:.?\w+)*)$/i";

    /**
     * Default Access scopes
     *
     * @var string The scopes for "invoices", "receipts", "credit_notes", "clients" and "settings"
     */
    public static $accessScopes = "entity.clients:a issued_documents.invoices:a issued_documents.receipts:a issued_documents.credit_notes:a settings:a situation:r";

    /**
     * Base URI
     *
     * @var string
     */
    private static $baseUri;

    /**
     * Get public client ID
     *
     * @return string
     */
    public static function getClientID()
    {
        return self::$clientID;
    }

    /**
     * fattureInCloudIssuedDocumentsApi
     *
     * @return \FattureInCloud\Api\IssuedDocumentsApi
     */
    public static function fattureInCloudIssuedDocumentsApi()
    {
        $apiData = getActiveApi();
        $config  = \FattureInCloud\Configuration::getDefaultConfiguration()->setAccessToken($apiData->accessToken);

        // IssuedDocumentsApi
        return new \FattureInCloud\Api\IssuedDocumentsApi(
            new \GuzzleHttp\Client(),
            $config
        );
    }

    /**
     * fattureInCloudReceiptsApi
     *
     * @return \FattureInCloud\Api\ReceiptsApi
     */
    public static function fattureInCloudReceiptsApi()
    {
        $apiData = getActiveApi();
        $config  = \FattureInCloud\Configuration::getDefaultConfiguration()->setAccessToken($apiData->accessToken);

        return new \FattureInCloud\Api\ReceiptsApi(
            new \GuzzleHttp\Client(),
            $config
        );
    }

    /**
     * fattureInCloudIssuedEInvoicesApi
     *
     * @return \FattureInCloud\Api\IssuedEInvoicesApi
     */
    public static function fattureInCloudIssuedEInvoicesApi()
    {
        $apiData = getActiveApi();
        $config  = \FattureInCloud\Configuration::getDefaultConfiguration()->setAccessToken($apiData->accessToken);

        // IssuedEInvoicesApi
        return new \FattureInCloud\Api\IssuedEInvoicesApi(
            new \GuzzleHttp\Client(),
            $config
        );
    }

    /**
     * fattureInCloudInfoApi
     *
     * @return \FattureInCloud\Api\InfoApi
     */
    public static function fattureInCloudInfoApi()
    {
        $apiData = getActiveApi();
        $config  = \FattureInCloud\Configuration::getDefaultConfiguration()->setAccessToken($apiData->accessToken);

        // InfoApi
        return new \FattureInCloud\Api\InfoApi(
            new \GuzzleHttp\Client(),
            $config
        );
    }

    /**
     * fattureInCloudSettingsApi
     *
     * @return \FattureInCloud\Api\SettingsApi
     */
    public static function fattureInCloudSettingsApi()
    {
        $apiData = getActiveApi();
        $config  = \FattureInCloud\Configuration::getDefaultConfiguration()->setAccessToken($apiData->accessToken);

        // Settings
        return new \FattureInCloud\Api\SettingsApi(
            new \GuzzleHttp\Client(),
            $config
        );
    }

    /**
     * fattureInCloudUserApi
     *
     * @return \FattureInCloud\Api\UserApi
     */
    public static function fattureInCloudUserApi()
    {
        $apiData = getActiveApi();
        $config  = \FattureInCloud\Configuration::getDefaultConfiguration()->setAccessToken($apiData->accessToken);

        // User info
        return new \FattureInCloud\Api\UserApi(
            new \GuzzleHttp\Client(),
            $config
        );
    }

    /**
     * fattureInCloudCreateClient
     *
     * @return \FattureInCloud\Api\ClientsApi
     */
    public static function fattureInCloudCreateClient()
    {
        $apiData = getActiveApi();
        $config  = \FattureInCloud\Configuration::getDefaultConfiguration()->setAccessToken($apiData->accessToken);

        return new \FattureInCloud\Api\ClientsApi(
            new \GuzzleHttp\Client(),
            $config
        );
    }

    /**
     * Set API base uri
     *
     * @param $uri
     */
    public static function setApiBaseUri($uri)
    {
        self::$baseUri = substr($uri, -1) === '/' ? $uri : $uri . '/';
    }

    /**
     * Get Base URI
     *
     * @return string|null
     */
    public static function getBaseUri()
    {
        return esc_url(self::$baseUri);
    }

    /**
     * User info
     *
     * @return object|void
     */
    public static function getUserAndCompanyData()
    {
        $currentUserInfo      = get_option('wfc_user_info');
        $currentUserCompanies = get_option('wfc_company_data');

        if (! $currentUserCompanies &&
            ! $currentUserInfo ||
            (is_object($currentUserInfo) && ! property_exists($currentUserInfo, 'hash'))
        ) {
            // UserApi
            $apiUserInstance = self::fattureInCloudUserApi();

            try {
                $resultUser          = $apiUserInstance->getUserInfo();
                $resultUserCompanies = $apiUserInstance->listUserCompanies();
                $dataUser            = $resultUser->getData();
                $dataCompanies       = $resultUserCompanies->getData();
                $dataCompaniesList   = $dataCompanies->getCompanies();

                $userInfoData = array(
                    'id'        => $dataUser->getId(),
                    'name'      => $dataUser->getName(),
                    'firstName' => $dataUser->getFirstName(),
                    'lastName'  => $dataUser->getLastName(),
                    'email'     => $dataUser->getEmail(),
                    'hash'      => $dataUser->getHash(),
                    'picture'   => $dataUser->getPicture(),
                );

                $userCompaniesData = array();
                $dataCompanies->getCompanies();
                if ($dataCompaniesList) {
                    foreach ($dataCompaniesList as $dataCompany) {
                        $userCompaniesData[] = (object)array(
                            'id'           => $dataCompany->getId(),
                            'name'         => $dataCompany->getName(),
                            'type'         => $dataCompany->getType(),
                            'connectionID' => $dataCompany->getConnectionId(),
                            'taxCode'      => $dataCompany->getTaxCode(),
                        );
                    }
                }

                // default CompanyID
                $defaultCompanyID = $userCompaniesData[0]->id;

                // Store company id
                update_option('wfc_company_id', $defaultCompanyID);
                // Store user info
                update_option('wfc_user_info', (object)$userInfoData);
                // Store company data
                update_option('wfc_company_data', (object)$userCompaniesData);

                // InfoApi
                $InfoApi = self::fattureInCloudInfoApi();

                /**
                 * listPaymentMethods
                 */
                self::setDefaultPaymentMethods($InfoApi, $defaultCompanyID);

                /**
                 * listPaymentAccounts
                 */
                self::setDefaultPaymentAccounts($InfoApi, $defaultCompanyID);

                $_POST = [
                    'companyID' => $defaultCompanyID,
                    'nonce'     => wp_create_nonce('wfc_scripts-ajax_nonce'),
                ];
                settingsCompany(true);
            } catch (\Exception $e) {
                if (401 === $e->getCode()) {
                    $dataException = array(
                        'message' => esc_html__('Unauthorized: the Token seems to be invalid, update it!',
                            WP_FATT_CLOUD_TEXTDOMAIN),
                        'code'    => $e->getCode(),
                    );
                } else {
                    $dataException = array(
                        'message' => esc_html('Exception when calling UserApi->getUserAndCompanyData: ' . $e->getMessage() . ' Trace: ' . $e->getTraceAsString()),
                        'code'    => $e->getCode(),
                    );
                }

                wp_send_json($dataException);
                die();
            }
        }

        return (object)array(
            'user'      => $currentUserInfo,
            'companies' => $currentUserCompanies,
        );
    }

    /**
     * setVatTypes
     *
     * @param bool $update
     *
     * @return array|mixed|void
     */
    public static function setVatTypes(bool $update = false)
    {
        $vatTypeList      = get_option('wfc_vat_types');
        $userAndCompanies = getUserAndCompanies();

        // InfoApi
        $InfoApi = self::fattureInCloudInfoApi();

        if (! $vatTypeList || $update) {
            try {
                /**
                 * listVatTypes
                 */
                $vatTypes        = $InfoApi->listVatTypes($userAndCompanies->companyID, 'detailed');
                $vatTypeListData = $vatTypes->getData();
                if (! empty($vatTypeListData)) {
                    $vatTypeList = buildFicVatTypeListCache($vatTypeListData);
                    update_option('wfc_vat_types', $vatTypeList);
                }
            } catch (\Exception $e) {
                if (401 === $e->getCode()) {
                    $dataException = array(
                        'message' => esc_html__('Unauthorized: the Token seems to be invalid, update it!',
                            WP_FATT_CLOUD_TEXTDOMAIN),
                        'code'    => $e->getCode(),
                    );
                } else {
                    $dataException = array(
                        'message' => esc_html('Exception when calling InfoApi->listVatTypes: ' . $e->getMessage() . ' Trace: ' . $e->getTraceAsString()),
                        'code'    => $e->getCode(),
                    );
                }

                wp_send_json($dataException);
                die();
            }
        }

        return $vatTypeList;
    }

    /**
     * setDefaultPaymentMethods
     *
     * @param InfoApi $InfoApi
     * @param int     $defaultCompanyID The default company ID before setting
     *
     * @return false|mixed|void
     */
    public static function setDefaultPaymentMethods(InfoApi $InfoApi, $defaultCompanyID = null)
    {
        $ajaxAction       = filterInput($_POST, 'ajaxAction', FILTER_UNSAFE_RAW);
        $paymentMethods   = get_option('wfc_payment_methods');
        $userAndCompanies = getUserAndCompanies();

        $companyID = isset($userAndCompanies->companyID) && $userAndCompanies->companyID ?
            $userAndCompanies->companyID :
            $defaultCompanyID;

        try {
            /**
             * listPaymentMethods
             */
            if (! $paymentMethods || 'fcSettingsCompanyRequest' === $ajaxAction) {
                $paymentMethodsList = $InfoApi->listPaymentMethods($companyID);
                $paymentMethodsData = $paymentMethodsList->getData();
                // Payment methods
                if (! empty($paymentMethodsData)) {
                    $paymentMethods = array();
                    foreach ($paymentMethodsData as $paymentMethod) {
                        $key                  = getKey($paymentMethod->getName());
                        $paymentMethods[$key] = array(
                            'id'                => $paymentMethod->getId(),
                            'name'              => $paymentMethod->getName(),
                            'ei_payment_method' => $paymentMethod->getEiPaymentMethod(),
                        );
                    }

                    update_option('wfc_payment_methods', $paymentMethods);
                }
            }
        } catch (\Exception $e) {
            $dataException = array(
                'message' => esc_html('Exception when calling InfoApi->listPaymentMethods: ' . $e->getMessage() . ' Trace: ' . $e->getTraceAsString()),
                'code'    => $e->getCode(),
            );

            wp_send_json($dataException);
            die();
        }

        return $paymentMethods;
    }

    /**
     * setDefaultPaymentAccounts
     *
     * @param InfoApi $InfoApi
     * @param int     $defaultCompanyID The default company ID before setting
     *
     * @return false|mixed|void
     * @see https://secure.fattureincloud.it/settings-paymentaccounts
     */
    public static function setDefaultPaymentAccounts(InfoApi $InfoApi, $defaultCompanyID = null)
    {
        $ajaxAction       = filterInput($_POST, 'ajaxAction', FILTER_UNSAFE_RAW);
        $paymentAccounts  = get_option('wfc_payment_accounts');
        $userAndCompanies = getUserAndCompanies();

        $companyID = isset($userAndCompanies->companyID) && $userAndCompanies->companyID ?
            $userAndCompanies->companyID :
            $defaultCompanyID;

        try {
            /**
             * listPaymentAccounts
             */
            if (! $paymentAccounts || 'fcSettingsCompanyRequest' === $ajaxAction) {
                $paymentAccountList = $InfoApi->listPaymentAccounts($companyID);
                $paymentAccountData = $paymentAccountList->getData();
                if (! empty($paymentAccountData)) {
                    $paymentAccounts = array();
                    foreach ($paymentAccountData as $account) {
                        $key                   = getKey($account->getName());
                        $paymentAccounts[$key] = array(
                            'id'   => $account->getId(),
                            'name' => $account->getName(),
                        );
                    }
                    update_option('wfc_payment_accounts', $paymentAccounts);
                }
            }
        } catch (\Exception $e) {
            $dataException = array(
                'message' => esc_html('Exception when calling InfoApi->listPaymentAccounts: ' . $e->getMessage() . ' Trace: ' . $e->getTraceAsString()),
                'code'    => $e->getCode(),
            );

            wp_send_json($dataException);
            die();
        }

        return $paymentAccounts;
    }

    /**
     * setPaymentsAccountsAndMethods
     *
     * @return void
     */
    public static function setPaymentsAccountsAndMethods()
    {
        // InfoApi
        $InfoApi = self::fattureInCloudInfoApi();

        try {
            /**
             * listPaymentMethods
             */
            self::setDefaultPaymentMethods($InfoApi);

            /**
             * listPaymentAccounts
             */
            self::setDefaultPaymentAccounts($InfoApi);
        } catch (\Exception $e) {
            if (401 === $e->getCode()) {
                $dataException = array(
                    'message' => esc_html__('Unauthorized: the Token seems to be invalid, update it!',
                        WP_FATT_CLOUD_TEXTDOMAIN),
                    'code'    => $e->getCode(),
                );
            } else {
                $dataException = array(
                    'message' => esc_html('Exception when calling setPaymentsAccountsAndMethods: ' . $e->getMessage() . ' Trace: ' . $e->getTraceAsString()),
                    'code'    => $e->getCode(),
                );
            }

            wp_send_json($dataException);
            die();
        }
    }

    /**
     * getVatTypes
     *
     * @return false|mixed|void
     */
    public static function getVatTypes()
    {
        return get_option('wfc_vat_types');
    }

    /**
     * getPaymentMethods
     *
     * @return false|mixed|void
     */
    public static function getPaymentMethods()
    {
        return get_option('wfc_payment_methods') ?: array();
    }

    /**
     * getPaymentAccounts
     *
     * @return false|mixed|void
     * @see https://secure.fattureincloud.it/settings-paymentaccounts
     */
    public static function getPaymentAccounts()
    {
        return get_option('wfc_payment_accounts') ?: array();
    }

    /**
     * getPaymentAccountActive
     *
     * @return false|mixed|void
     */
    public static function getPaymentAccountActive()
    {
        return get_option('wfc_payment_account_active') ?: array();
    }
}
