<?php
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

/**
 * REST API běží na gate.*; staré api.* hostname nejde na některých hostinzích vyřešit (cURL 6).
 *
 * @param string $environment
 * @return array{api_url: string, gate_url: string, create_api_url: string}
 */
function elementsell_get_thepay_urls_for_environment( $environment ) {
    $is_production = ( $environment === 'production' );
    $gate_url      = $is_production ? 'https://gate.thepay.cz/' : 'https://demo.gate.thepay.cz/';

    return [
        'api_url'        => $gate_url,
        'gate_url'       => $gate_url,
        'create_api_url' => $gate_url,
    ];
}

/**
 * @param string $api_url
 * @param string $environment
 * @return string
 */
function elementsell_normalize_thepay_api_url( $api_url, $environment = '' ) {
    $api_url = trim( (string) $api_url );

    if ( preg_match( '#^https://(demo\.)?api\.thepay\.cz/#i', $api_url ) ) {
        $env = $environment === 'production' ? 'production' : 'demo';

        return elementsell_get_thepay_urls_for_environment( $env )['api_url'];
    }

    return $api_url;
}

/**
 * @param Exception $exception
 * @return bool
 */
function elementsell_thepay_exception_is_transient( $exception ) {
    $message = strtolower( $exception->getMessage() );

    return strpos( $message, 'could not resolve host' ) !== false
        || strpos( $message, 'curl error 6' ) !== false
        || strpos( $message, 'curl error 7' ) !== false
        || strpos( $message, 'curl error 28' ) !== false
        || strpos( $message, 'connection timed out' ) !== false;
}

/**
 * @param int    $order_id
 * @param string $environment
 * @return void
 */
function elementsell_save_thepay_api_urls_for_order( $order_id, $environment ) {
    $urls = elementsell_get_thepay_urls_for_environment( $environment );

    elementsell_save_order_field( $order_id, 'api_url', $urls['api_url'] );
    elementsell_save_order_field( $order_id, 'gate_url', $urls['gate_url'] );
}

/**
 * @param int   $order_id
 * @param array $credentials
 * @return void
 */
function elementsell_save_thepay_credentials_for_order( $order_id, $credentials ) {
    if ( ! is_array( $credentials ) ) {
        return;
    }

    if ( ! empty( $credentials['environment'] ) ) {
        elementsell_save_order_field( $order_id, 'environment', (string) $credentials['environment'] );
    }

    if ( ! empty( $credentials['merchant_id'] ) ) {
        elementsell_save_order_field( $order_id, 'merchant_id', (string) $credentials['merchant_id'] );
    }

    if ( ! empty( $credentials['project_id'] ) ) {
        elementsell_save_order_field( $order_id, 'project_id', (string) (int) $credentials['project_id'] );
    }

    if ( ! empty( $credentials['api_password'] ) ) {
        elementsell_save_order_field( $order_id, 'api_password', (string) $credentials['api_password'] );
    }
}

/**
 * @param object $order
 * @return array{merchant_id: string, project_id: int, api_password: string, api_url: string, gate_url: string, environment: string}
 */
function elementsell_get_thepay_credentials_for_order( $order ) {
    $order_id = (int) $order->id;

    $merchant_id  = (string) elementsell_get_order_field( $order_id, 'merchant_id' );
    $project_id   = (int) elementsell_get_order_field( $order_id, 'project_id' );
    $api_password = (string) elementsell_get_order_field( $order_id, 'api_password' );
    $environment  = (string) elementsell_get_order_field( $order_id, 'environment' );
    $api_url      = (string) elementsell_get_order_field( $order_id, 'api_url' );
    $gate_url     = (string) elementsell_get_order_field( $order_id, 'gate_url' );
    $is_landing_demo = (string) elementsell_get_order_field( $order_id, 'landing_demo' ) === '1';

    if ( $is_landing_demo ) {
        $environment = 'demo';
    } elseif ( $environment === '' ) {
        // Bez site-wide „aktivního režimu“ — odhadni z uložených URL objednávky.
        $urls_blob = trim( $gate_url . ' ' . $api_url );

        if ( $urls_blob !== '' && stripos( $urls_blob, 'demo' ) !== false ) {
            $environment = 'demo';
        } elseif ( $urls_blob !== '' ) {
            $environment = 'production';
        } else {
            $environment = 'demo';
        }
    }

    $env_key = $environment === 'production' ? 'production' : 'demo';

    if ( $merchant_id === '' ) {
        if ( $is_landing_demo && function_exists( 'elementsell_resolve_thepay_credentials_from_options_strict' ) ) {
            $strict_credentials = elementsell_resolve_thepay_credentials_from_options_strict( 'demo' );
            $merchant_id        = $strict_credentials['merchant_id'];
        } else {
            $merchant_id = (string) get_option(
                'elementsell_thepay_' . $env_key . '_merchant_id',
                get_option( 'my_merchant_id', '' )
            );
        }
    }

    if ( $project_id <= 0 ) {
        if ( $is_landing_demo && function_exists( 'elementsell_resolve_thepay_credentials_from_options_strict' ) ) {
            $strict_credentials = $strict_credentials ?? elementsell_resolve_thepay_credentials_from_options_strict( 'demo' );
            $project_id         = (int) $strict_credentials['project_id'];
        } else {
            $project_id = (int) get_option(
                'elementsell_thepay_' . $env_key . '_project_id',
                get_option( 'my_project_id', 0 )
            );
        }
    }

    if ( $api_password === '' ) {
        if ( $is_landing_demo && function_exists( 'elementsell_resolve_thepay_credentials_from_options_strict' ) ) {
            $strict_credentials = $strict_credentials ?? elementsell_resolve_thepay_credentials_from_options_strict( 'demo' );
            $api_password       = $strict_credentials['api_password'];
        } else {
            $api_password = (string) get_option(
                'elementsell_thepay_' . $env_key . '_api_password',
                get_option( 'my_api_password', '' )
            );
        }
    }

    if ( $api_url === '' || $gate_url === '' || $is_landing_demo ) {
        $urls     = elementsell_get_thepay_urls_for_environment( $environment );
        $api_url  = $urls['api_url'];
        $gate_url = $urls['gate_url'];
    }

    $api_url  = elementsell_normalize_thepay_api_url( $api_url, $environment );
    $gate_url = elementsell_normalize_thepay_api_url( $gate_url, $environment );

    if ( $gate_url === '' ) {
        $gate_url = $api_url;
    }

    return [
        'merchant_id'  => $merchant_id,
        'project_id'   => $project_id,
        'api_password' => $api_password,
        'api_url'      => $api_url,
        'gate_url'     => $gate_url,
        'environment'  => $environment,
    ];
}

/**
 * @param array  $credentials
 * @param string $api_url
 * @param string $payment_uid
 * @return \ThePay\ApiClient\Model\Payment
 */
function elementsell_thepay_fetch_payment( $credentials, $api_url, $payment_uid ) {
    $client = elementsell_create_thepay_client(
        $credentials['merchant_id'],
        $credentials['project_id'],
        $credentials['api_password'],
        $api_url,
        $credentials['gate_url'] !== '' ? $credentials['gate_url'] : $api_url
    );

    return $client->getPayment( $payment_uid );
}

/**
 * @param object $order
 * @return \ThePay\ApiClient\Model\Payment
 */
function elementsell_verify_thepay_payment( $order ) {
    $autoload = dirname( __DIR__, 2 ) . '/vendor/autoload.php';

    if ( ! file_exists( $autoload ) ) {
        throw new Exception( 'Chybí vendor/autoload.php pro ThePay.' );
    }

    require_once $autoload;

    $credentials = elementsell_get_thepay_credentials_for_order( $order );

    if (
        $credentials['merchant_id'] === ''
        || $credentials['project_id'] <= 0
        || $credentials['api_password'] === ''
    ) {
        throw new Exception( 'Chybí uložené údaje k ThePay u objednávky.' );
    }

    $fallback_urls = elementsell_get_thepay_urls_for_environment( $credentials['environment'] );
    $api_urls      = array_values(
        array_unique(
            array_filter(
                [
                    $credentials['api_url'],
                    $credentials['gate_url'],
                    $fallback_urls['api_url'],
                ]
            )
        )
    );

    $last_exception = null;

    foreach ( $api_urls as $api_url ) {
        try {
            return elementsell_thepay_fetch_payment( $credentials, $api_url, $order->payment_uid );
        } catch ( Exception $exception ) {
            $last_exception = $exception;

            if ( ! elementsell_thepay_exception_is_transient( $exception ) ) {
                throw $exception;
            }
        }
    }

    if ( $last_exception ) {
        throw $last_exception;
    }

    throw new Exception( 'Nepodařilo se ověřit platbu u ThePay.' );
}
