<?php
/**
 * Envato API Helper.
 *
 * @package PrimeLink
 */

namespace PrimeLink\Helpers;

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

final class EnvatoHelper {

    /**
     * Envato API endpoint for verification.
     * Using author endpoint which requires author token (on server, not in plugin).
     */
    const API_URL = 'https://api.envato.com/v3/market/author/sale';

    /**
     * License verification endpoint (on your server).
     * Can be overridden via filter, defaults to verify-license.php
     */
    private static function get_verify_endpoint() {
        return apply_filters( 'mt_primelink_envato_verify_endpoint', 'https://api.malotop.ro/verify-license.php' );
    }

    /**
     * Verify purchase code.
     * 
     * By default, verifies through server endpoint (secure - token stays on server).
     * Can be configured to verify directly via filter (not recommended for security).
     *
     * @param string $purchase_code Purchase code.
     * @param string $item_id       Item ID (optional).
     * @return array
     */
    public static function verify_purchase_code( $purchase_code, $item_id = '' ) {
        if ( empty( $purchase_code ) ) {
            return array(
                'success' => false,
                'error'   => __( 'Purchase code is required.', 'primelink' ),
            );
        }

        /**
         * Development / staging test code bypass.
         *
         * This allows testing activation & updates cu un cod scurt (ex. "PRIMELINK-DEV-TEST-CODE")
         * fără să treacă prin validarea de format (36 caractere) și fără să lovească Envato,
         * DAR numai dacă serverul de licențe îl tratează deja ca valid.
         *
         * IMPORTANT: Nu documenta acest cod pentru clienți finali; folosește-l doar intern.
         */
        $dev_test_code = apply_filters( 'mt_primelink_envato_dev_test_code', 'PRIMELINK-DEV-TEST-CODE' );
        if ( ! empty( $dev_test_code ) && hash_equals( (string) $dev_test_code, (string) $purchase_code ) ) {
            // Sărim complet peste validarea de lungime; verificarea reală e deja bypass-uită în verify-license.php
            return self::verify_through_server( $purchase_code, $item_id );
        }

        /**
         * Basic format validation.
         *
         * Inițial verificam lungimea minimă (~36 caractere) pentru a filtra coduri evident invalide,
         * dar asta poate bloca coduri valide dacă Envato schimbă formatul sau userul introduce alt tip de cod.
         * Lăsăm acum validarea detaliată pe seama serverului (verify-license.php / Envato API),
         * și doar blocăm cazurile complet goale (deja tratate mai sus).
         *
         * Dacă vrei totuși să impui o lungime minimă, o poți face prin filtrul:
         *   mt_primelink_envato_min_code_length
         */
        $min_length = apply_filters( 'mt_primelink_envato_min_code_length', 0 );
        if ( $min_length > 0 && strlen( $purchase_code ) < $min_length ) {
            return array(
                'success' => false,
                'error'   => __( 'Invalid purchase code format.', 'primelink' ),
            );
        }

        // Check if direct verification is enabled (via filter - not recommended)
        $use_direct_verification = apply_filters( 'mt_primelink_envato_direct_verification', false );
        
        if ( $use_direct_verification ) {
            // Direct verification (requires token in wp-config - not user-friendly)
            return self::verify_direct( $purchase_code, $item_id );
        }

        // Default: Verify through server endpoint (recommended - secure and user-friendly)
        return self::verify_through_server( $purchase_code, $item_id );
    }

    /**
     * Verify purchase code through server endpoint (secure - token stays on server).
     *
     * @param string $purchase_code Purchase code.
     * @param string $item_id       Item ID (optional).
     * @return array
     */
    private static function verify_through_server( $purchase_code, $item_id = '' ) {
        // Get verification endpoint URL
        $endpoint = self::get_verify_endpoint();
        if ( empty( $endpoint ) ) {
            return array(
                'success' => false,
                'error'   => __( 'License verification endpoint is not configured.', 'primelink' ),
            );
        }

        // Make request to server endpoint (server has token and verifies with Envato API)
        // Use form-encoded body so verify-license.php sees $_POST values.
        $payload = array(
            'purchase_code' => $purchase_code,
            'site_url'      => home_url(),
        );

        $response = HttpHelper::post( $endpoint, array(
            'body'    => http_build_query( $payload ),
            'headers' => array(
                'Content-Type' => 'application/x-www-form-urlencoded',
            ),
            'timeout' => 15,
        ) );

        // Handle HTTP errors (like 403, 400, etc.)
        if ( ! $response['success'] || ( isset( $response['code'] ) && $response['code'] >= 400 ) ) {
            // Try to extract error from response body
            $error_message = __( 'Failed to verify purchase code. Please check your connection.', 'primelink' );
            
            if ( ! empty( $response['body'] ) ) {
                $error_body = json_decode( $response['body'], true );
                if ( is_array( $error_body ) && ! empty( $error_body['error'] ) ) {
                    // Use error message from server response
                    $error_message = $error_body['error'];
                } elseif ( ! empty( $response['error'] ) ) {
                    // Remove technical prefixes like "Client error:" or "Server error:"
                    $raw_error = $response['error'];
                    $error_message = preg_replace( '/^(Client error|Server error):\s*/i', '', $raw_error );
                    
                    // Try to extract JSON error from the message
                    if ( preg_match( '/"error"\s*:\s*"([^"]+)"/', $error_message, $matches ) ) {
                        $error_message = $matches[1];
                    }
                }
            }
            
            return array(
                'success' => false,
                'error'   => $error_message,
            );
        }

        $body = json_decode( $response['body'], true );

        // Check if response is valid
        if ( json_last_error() !== JSON_ERROR_NONE || ! is_array( $body ) ) {
            return array(
                'success' => false,
                'error'   => __( 'Invalid response from license verification server.', 'primelink' ),
            );
        }

        // Server endpoint returns: success, error, buyer, license, purchase_date, item
        if ( ! isset( $body['success'] ) || ! $body['success'] ) {
            return array(
                'success' => false,
                'error'   => $body['error'] ?? __( 'Invalid purchase code.', 'primelink' ),
            );
        }

        return array(
            'success'      => true,
            'verified'     => true,
            'buyer'        => $body['buyer'] ?? '',
            'license'      => $body['license'] ?? '',
            'purchase_date' => $body['purchase_date'] ?? '',
            'item'         => $body['item'] ?? array(),
        );
    }

    /**
     * Verify purchase code directly with Envato API (requires token in wp-config).
     * NOT RECOMMENDED: Token must be configured by users, not user-friendly.
     * Use only if you really need it and understand the security implications.
     *
     * @param string $purchase_code Purchase code.
     * @param string $item_id       Item ID (optional).
     * @return array
     */
    private static function verify_direct( $purchase_code, $item_id = '' ) {
        // Get Envato API token from wp-config
        $token = self::get_api_token();
        if ( empty( $token ) ) {
            return array(
                'success' => false,
                'error'   => __( 'Envato API token is not configured. Please contact support.', 'primelink' ),
            );
        }

        // Build API URL - using author endpoint
        $url = self::API_URL . '?code=' . urlencode( $purchase_code );

        // Make API request directly
        $response = HttpHelper::get( $url, array(
            'headers' => array(
                'Authorization' => 'Bearer ' . $token,
            ),
            'timeout' => 15,
        ) );

        if ( ! $response['success'] ) {
            return array(
                'success' => false,
                'error'   => $response['error'] ?? __( 'Failed to verify purchase code.', 'primelink' ),
            );
        }

        $body = json_decode( $response['body'], true );

        // Check if purchase code is valid
        if ( ! isset( $body['buyer'] ) ) {
            return array(
                'success' => false,
                'error'   => __( 'Invalid purchase code or purchase code does not belong to any of your items.', 'primelink' ),
            );
        }

        // Check if item info is present in response
        if ( ! isset( $body['item']['id'] ) ) {
            return array(
                'success' => false,
                'error'   => __( 'Invalid purchase code response from Envato API.', 'primelink' ),
            );
        }

        // Get configured item ID (optional)
        if ( empty( $item_id ) ) {
            $item_id = apply_filters( 'mt_primelink_envato_item_id', '' );
        }

        // If item ID is configured, verify purchase code is for that specific item
        if ( ! empty( $item_id ) ) {
            if ( (string) $body['item']['id'] !== (string) $item_id ) {
                return array(
                    'success' => false,
                    'error'   => __( 'This purchase code is not for PrimeLink plugin. Please use a purchase code from the correct CodeCanyon item.', 'primelink' ),
                );
            }
        }

        return array(
            'success'       => true,
            'verified'      => true,
            'buyer'         => $body['buyer'] ?? '',
            'license'       => $body['license'] ?? '',
            'purchase_date' => $body['sold_at'] ?? '',
            'item'          => $body['item'] ?? array(),
        );
    }

    /**
     * Get Envato API token.
     * 
     * Only used when direct verification is enabled (not recommended).
     * Token should be in wp-config.php: define( 'MT_PRIMELINK_ENVATO_API_TOKEN', 'your-token' );
     * 
     * @return string Token or empty string.
     */
    private static function get_api_token() {
        // Allow token to be set via constant or filter (only for direct verification mode)
        $token = defined( 'MT_PRIMELINK_ENVATO_API_TOKEN' ) ? MT_PRIMELINK_ENVATO_API_TOKEN : '';
        $token = apply_filters( 'mt_primelink_envato_api_token', $token );
        
        return $token;
    }

    /**
     * Check if purchase code is already activated on another site.
     *
     * @param string $purchase_code Purchase code.
     * @return bool
     */
    public static function is_code_already_used( $purchase_code ) {
        // This would typically check against a remote database
        // For now, we'll just verify the code format
        return false;
    }

    /**
     * Activate purchase code for this site.
     *
     * @param string $purchase_code Purchase code.
     * @return array
     */
    public static function activate_purchase_code( $purchase_code ) {
        $verification = self::verify_purchase_code( $purchase_code );

        if ( ! $verification['success'] ) {
            return $verification;
        }

        // Store activation info
        $activation_data = array(
            'purchase_code'  => $purchase_code,
            'activated_at'   => current_time( 'mysql' ),
            'site_url'      => home_url(),
            'site_name'     => get_bloginfo( 'name' ),
        );

        update_option( 'mt_primelink_license_activation', $activation_data, false );

        return array(
            'success' => true,
            'message' => __( 'License activated successfully!', 'primelink' ),
            'data'    => $activation_data,
        );
    }

    /**
     * Deactivate purchase code.
     *
     * @return bool
     */
    public static function deactivate_purchase_code() {
        delete_option( 'mt_primelink_license_activation' );
        return true;
    }

    /**
     * Get license status.
     *
     * @return array
     */
    public static function get_license_status() {
        // Development-only bypass: treat license as active without remote checks.
        // Enable in wp-config.php with: define( 'MT_PRIMELINK_DEV_LICENSE_BYPASS', true );
        // IMPORTANT: Do NOT enable this on production sites or in the Envato release build.
        if ( defined( 'MT_PRIMELINK_DEV_LICENSE_BYPASS' ) && MT_PRIMELINK_DEV_LICENSE_BYPASS ) {
            return array(
                'activated'     => true,
                'status'        => 'active',
                'purchase_code' => 'DEV-BYPASS',
                'activated_at'  => '',
            );
        }

        $activation = get_option( 'mt_primelink_license_activation', array() );
        $settings = \PrimeLink\Core\Rest\ImportRest::get_settings();
        $license_key = $settings['license_key'] ?? '';

        // Check both activation data and settings
        $activation_code = $activation['license_code'] ?? $activation['purchase_code'] ?? '';
        $has_activation = ! empty( $activation ) && ! empty( $activation_code );
        $has_settings_license = ! empty( $license_key );

        if ( ! $has_activation && ! $has_settings_license ) {
            return array(
                'activated' => false,
                'status'    => 'inactive',
            );
        }

        // Use activation data if available, otherwise use settings
        $purchase_code = ! empty( $activation_code ) ? $activation_code : $license_key;
        
        return array(
            'activated'     => true,
            'status'        => 'active',
            'purchase_code' => $purchase_code,
            'activated_at'  => $activation['activated_at'] ?? '',
        );
    }

    /**
     * Verify license (periodic check).
     * 
     * Verifică periodic codul de achiziție stocat, folosind integrarea Envato.
     *
     * @param bool $time_based_check Whether to use time-based periodic check.
     * @return array Status & message describing license validity.
     */
    public static function verify_license( $time_based_check = false ) {
        // Development-only bypass: skip remote verification and always treat license as valid.
        // Enable in wp-config.php with: define( 'MT_PRIMELINK_DEV_LICENSE_BYPASS', true );
        // IMPORTANT: Do NOT enable this on production sites or in the Envato release build.
        if ( defined( 'MT_PRIMELINK_DEV_LICENSE_BYPASS' ) && MT_PRIMELINK_DEV_LICENSE_BYPASS ) {
            return array(
                'status'  => true,
                'message' => __( 'Development license bypass is active. Remote verification is skipped.', 'primelink' ),
            );
        }

        $activation = get_option( 'mt_primelink_license_activation', array() );
        $purchase_code = $activation['purchase_code'] ?? '';

        if ( empty( $purchase_code ) ) {
            return array(
                'status'  => false,
                'message' => __( 'No purchase code found. Please activate your license.', 'primelink' ),
            );
        }

        // Time-based check: only verify once per day (or configured period)
        if ( $time_based_check ) {
            $verification_period = apply_filters( 'mt_primelink_envato_verification_period', 1 ); // days
            $transient_key = 'mt_primelink_envato_license_verify_' . md5( $purchase_code );
            $last_check = get_transient( $transient_key );
            
            if ( $last_check !== false ) {
                // Return cached result (convert to LicenseBox format)
                return self::convert_to_licensebox_format( $last_check );
            }
        }

        // Verify purchase code
        $verification = self::verify_purchase_code( $purchase_code );

        // Convert to LicenseBox-compatible format
        $result = array(
            'status'  => $verification['success'] ?? false,
            'message' => $verification['message'] ?? ( $verification['error'] ?? '' ),
        );

        // Cache result for time-based checks
        if ( $time_based_check && isset( $verification['success'] ) ) {
            $cache_duration = apply_filters( 'mt_primelink_envato_verification_period', 1 ) * DAY_IN_SECONDS;
            set_transient( 'mt_primelink_envato_license_verify_' . md5( $purchase_code ), $verification, $cache_duration );
        }

        return $result;
    }

    /**
     * Convert Envato verification result to LicenseBox format.
     *
     * @param array $result Envato verification result.
     * @return array LicenseBox-compatible format.
     */
    private static function convert_to_licensebox_format( $result ) {
        return array(
            'status'  => $result['success'] ?? false,
            'message' => $result['message'] ?? ( $result['error'] ?? '' ),
        );
    }

    /**
     * Get current plugin version.
     *
     * @return string
     */
    public static function get_current_version() {
        return defined( 'MT_PRIMELINK_VERSION' ) ? MT_PRIMELINK_VERSION : '1.0.0';
    }

    /**
     * Activate license with purchase code and client name.
     * 
     * Uses Envato verification to activate and store license data locally.
     *
     * @param string $license_code Purchase code.
     * @param string $client_name  Client name (Envato username or name).
     * @param bool   $create_lic_file Deprecated flag (kept for backwards compatibility, no local license file is created).
     * @return array Activation result with status and message.
     */
    public static function activate_license( $license_code, $client_name, $create_lic_file = true ) {
        // Development / staging: allow dev test code to bypass external verification
        $dev_test_code = apply_filters( 'mt_primelink_envato_dev_test_code', 'PRIMELINK-DEV-TEST-CODE' );
        if ( ! empty( $dev_test_code ) && hash_equals( (string) $dev_test_code, (string) $license_code ) ) {
            // Store activation info locally without remote Envato check
            $activation_data = array(
                'license_code'  => $license_code,
                'purchase_code' => $license_code,
                'client_name'   => sanitize_text_field( $client_name ),
                'activated_at'  => current_time( 'mysql' ),
                'site_url'      => home_url(),
                'site_name'     => get_bloginfo( 'name' ),
                'buyer'         => 'dev-buyer',
                'license'       => 'Regular License (DEV)',
                'purchase_date' => current_time( 'mysql' ),
            );

            update_option( 'mt_primelink_license_activation', $activation_data, false );

            // Clear verification cache (if any)
            delete_transient( 'mt_primelink_envato_license_verify_' . md5( $license_code ) );

            return array(
                'status'  => true,
                'message' => __( 'License activated successfully!', 'primelink' ),
            );
        }

        // Production: Verify purchase code with Envato API
        $verification = self::verify_purchase_code( $license_code );

        if ( ! $verification['success'] ) {
            return array(
                'status'  => false,
                'message' => $verification['error'] ?? __( 'License activation failed.', 'primelink' ),
            );
        }

        // Store activation info
        $activation_data = array(
            'license_code'  => $license_code,
            'purchase_code' => $license_code, // Alias for compatibility
            'client_name'   => sanitize_text_field( $client_name ),
            'activated_at'  => current_time( 'mysql' ),
            'site_url'      => home_url(),
            'site_name'     => get_bloginfo( 'name' ),
            'buyer'         => $verification['buyer'] ?? '',
            'license'       => $verification['license'] ?? '',
            'purchase_date' => $verification['purchase_date'] ?? '',
        );

        update_option( 'mt_primelink_license_activation', $activation_data, false );

        // Clear verification cache
        delete_transient( 'mt_primelink_envato_license_verify_' . md5( $license_code ) );

        return array(
            'status'  => true,
            'message' => __( 'License activated successfully!', 'primelink' ),
        );
    }

    /**
     * Deactivate license.
     * 
     * Removes stored activation data and clears cached verification status.
     *
     * @param string $license_code Optional license code (not used, kept for compatibility).
     * @param string $client_name  Optional client name (not used, kept for compatibility).
     * @return array Deactivation result with status and message.
     */
    public static function deactivate_license( $license_code = false, $client_name = false ) {
        $activation = get_option( 'mt_primelink_license_activation', array() );
        
        if ( empty( $activation ) ) {
            return array(
                'status'  => false,
                'message' => __( 'No active license found.', 'primelink' ),
            );
        }

        $purchase_code = $activation['purchase_code'] ?? $activation['license_code'] ?? '';
        
        // Remove activation data
        delete_option( 'mt_primelink_license_activation' );
        
        // Clear verification cache
        if ( ! empty( $purchase_code ) ) {
            delete_transient( 'mt_primelink_envato_license_verify_' . md5( $purchase_code ) );
        }

        return array(
            'status'  => true,
            'message' => __( 'License deactivated successfully.', 'primelink' ),
        );
    }

    /**
     * Check for updates.
     * 
     * Note: For Envato compliance, we don't use external update servers here.
     * Updates should be handled through Envato's official system or WordPress update mechanism.
     *
     * @return array Simple response indicating that external update checks are not used.
     */
    public static function check_update() {
        // For Envato compliance, we don't check for updates via external servers
        // Updates should be distributed through CodeCanyon/Envato's official channels
        return array(
            'status'  => false,
            'message' => __( 'Update checking via external servers is not supported. Please check for updates on CodeCanyon.', 'primelink' ),
        );
    }
}

