<?php
namespace TeknoTok\AiTranslator\Integrations;

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

use TeknoTok\AiTranslator\Utils\ErrorSanitizer;
use TeknoTok\AiTranslator\Utils\Logger;

/**
 * Manager class to interact with TeknoTok License API.
 */
class LicenseManager {
	/**
	 * Get stored license options.
	 *
	 * @return array
	 */
	public static function get_license_data() {
		$defaults = array(
			'license_key' => '',
			'status'      => 'free',
			'expires_at'  => '',
			'last_check'  => 0,
			'error_count' => 0,
			'plan_slug'   => 'free',
			'site_limit'  => 1,
			'words_limit' => 3000,
			'words_used'  => 0,
			'words_remaining' => 3000,
			'quota_period' => 'lifetime',
			'quota_period_start' => '',
			'quota_period_end' => '',
			'features' => array(),
			'user_message' => '',
		);
		$license = get_option( 'teknotok_ait_license_status', array() );
		$data = array_merge( $defaults, is_array( $license ) ? $license : array() );
		$data['user_message'] = self::normalize_quota_user_message(
			$data['user_message'] ?? '',
			self::quota_int( $data['words_remaining'] ?? 0 )
		);

		return $data;
	}

	/**
	 * Check if premium capability is authorized (with grace period support).
	 *
	 * @return bool
	 */
	public static function is_premium_active() {
		$license = self::get_license_data();
		$status  = $license['status'] ?? 'inactive';

		if ( 'active' === $status ) {
			$expires_at = $license['expires_at'] ?? '';
			if ( ! empty( $expires_at ) && strtotime( $expires_at ) < time() ) {
				return false;
			}
			return true;
		}

		// Grace period check (48 hours)
		$last_check = (int) ( $license['last_check'] ?? 0 );
		$error_count = (int) ( $license['error_count'] ?? 0 );
		
		if ( $error_count > 0 && $last_check > 0 ) {
			$delta = time() - $last_check;
			if ( $delta < 172800 ) { // 48 hours in seconds
				return true;
			}
		}

		return false;
	}

	/**
	 * Determine whether an inactive premium license should pause premium queue work.
	 *
	 * @return bool True when a saved Pro license exists but is not currently active.
	 */
	public static function has_inactive_premium_license() {
		$license = self::get_license_data();
		$key     = trim( (string) ( $license['license_key'] ?? '' ) );
		$status  = $license['status'] ?? 'inactive';

		if ( '' === $key || in_array( $status, array( 'free', 'inactive' ), true ) ) {
			return false;
		}

		return ! self::is_premium_active();
	}

	/**
	 * Register hook actions.
	 *
	 * @return void
	 */
	public function init_hooks() {
		add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_plugin_update' ) );
		add_filter( 'plugins_api', array( $this, 'plugin_info' ), 20, 3 );
	}

	/**
	 * Request License API helper.
	 *
	 * @param string $endpoint Endpoint slug (e.g. 'activate', 'check', 'deactivate').
	 * @param array  $body     Optional extra payload.
	 * @return array|\WP_Error Response object array or WP_Error.
	 */
	private function make_request( $endpoint, $body = array() ) {
		$license = self::get_license_data();
		$key     = $body['license_key'] ?? ( $license['license_key'] ?? '' );

		// Local mock response for test licenses
		if ( 0 === strpos( $key, 'TEKNOTOK-TEST-' ) ) {
			$mock_body = array(
				'success'     => true,
				'status'      => 'active',
				'message'     => 'License active (Test Mode).',
				'expires_at'  => date( 'c', strtotime( '+1 year' ) ),
				'plan_slug'   => 'pro',
				'site_limit'  => 1,
				'words_limit' => 100000,
				'words_used'  => 0,
				'words_remaining' => 100000,
				'quota_period' => 'yearly',
				'quota_period_start' => date( 'c' ),
				'quota_period_end' => date( 'c', strtotime( '+1 year' ) ),
				'features'    => array(
					'ai_translation' => true,
					'updates'        => true,
				),
				'user_message' => '',
				'new_version' => '1.1.6',
				'url'         => 'https://soft.teknotok.com/teknotok-translator-pro/',
				'tested'      => '6.5',
				'requires'    => '7.4',
				'sections'    => array(
					'description' => 'One-click AI translation plugin for WordPress and WooCommerce.',
					'changelog'   => 'Major multilingual SEO enhancements and performance fixes.',
				),
			);
			return array(
				'response' => array( 'code' => 200 ),
				'body'     => json_encode( $mock_body ),
			);
		}

		$payload = array(
			'license_key'    => $key,
			'product_slug'   => TEKNOTOK_AIT_LICENSE_PRODUCT_SLUG,
			'site_url'       => get_site_url(),
			'plugin_version' => TEKNOTOK_AIT_VERSION,
		);

		$url = TEKNOTOK_AIT_LICENSE_API . $endpoint;

		if ( self::can_use_local_gateway() ) {
			$response = self::request_local_gateway( $endpoint, $payload );
			if ( $response ) {
				return $response;
			}
		}

		$response = wp_remote_post(
			$url,
			array(
				'body'    => $payload,
				'timeout' => 15,
			)
		);

		return $response;
	}

	/**
	 * Normalize quota fields returned by License Manager 1.4.0+.
	 *
	 * @param array $body API response body.
	 * @param array $existing Existing stored license data.
	 * @return array Normalized quota fields.
	 */
	private static function quota_fields_from_body( $body, $existing = array() ) {
		$body     = is_array( $body ) ? $body : array();
		$existing = is_array( $existing ) ? $existing : array();
		$limit    = self::quota_int( $body['words_limit'] ?? ( $body['limit'] ?? ( $existing['words_limit'] ?? 3000 ) ) );
		$used     = self::quota_int( $body['words_used'] ?? ( $body['word_count'] ?? ( $existing['words_used'] ?? 0 ) ) );
		$remaining = self::quota_int( $body['words_remaining'] ?? max( 0, $limit - $used ) );
		$user_message = self::normalize_quota_user_message(
			$body['user_message'] ?? ( $existing['user_message'] ?? '' ),
			$remaining
		);

		return array(
			'plan_slug'          => self::sanitize_key_value( $body['plan_slug'] ?? ( $existing['plan_slug'] ?? ( ! empty( $existing['license_key'] ) ? 'pro' : 'free' ) ) ),
			'site_limit'         => self::quota_int( $body['site_limit'] ?? ( $body['activation_limit'] ?? ( $existing['site_limit'] ?? 1 ) ) ),
			'words_limit'        => $limit,
			'words_used'         => $used,
			'words_remaining'    => $remaining,
			'quota_period'       => self::sanitize_key_value( $body['quota_period'] ?? ( $existing['quota_period'] ?? 'lifetime' ) ),
			'quota_period_start' => self::sanitize_text_value( $body['quota_period_start'] ?? ( $existing['quota_period_start'] ?? '' ) ),
			'quota_period_end'   => self::sanitize_text_value( $body['quota_period_end'] ?? ( $existing['quota_period_end'] ?? '' ) ),
			'features'           => self::normalize_features( $body['features'] ?? ( $existing['features'] ?? array() ) ),
			'user_message'       => $user_message,
		);
	}

	/**
	 * Normalize quota status messaging so stale exhausted-copy is not shown with remaining words.
	 *
	 * @param mixed $message Raw user-facing message from server or stored state.
	 * @param int   $remaining Remaining words.
	 * @return string Normalized message.
	 */
	private static function normalize_quota_user_message( $message, $remaining ) {
		$message = self::sanitize_text_value( $message );
		if ( $remaining > 0 ) {
			return '';
		}

		if ( '' === $message ) {
			return ErrorSanitizer::quota_exceeded_message();
		}

		return $message;
	}

	/**
	 * Sanitize a key-like API value.
	 *
	 * @param mixed $value Raw value.
	 * @return string Sanitized value.
	 */
	private static function sanitize_key_value( $value ) {
		if ( function_exists( 'sanitize_key' ) ) {
			return sanitize_key( $value );
		}

		return preg_replace( '/[^a-z0-9_\-]/', '', strtolower( (string) $value ) );
	}

	/**
	 * Sanitize a short text API value.
	 *
	 * @param mixed $value Raw value.
	 * @return string Sanitized value.
	 */
	private static function sanitize_text_value( $value ) {
		if ( function_exists( 'sanitize_text_field' ) ) {
			return sanitize_text_field( $value );
		}

		return trim( strip_tags( (string) $value ) );
	}

	/**
	 * Normalize a quota number.
	 *
	 * @param mixed $value Raw value.
	 * @return int Non-negative integer.
	 */
	private static function quota_int( $value ) {
		return max( 0, (int) $value );
	}

	/**
	 * Normalize feature flags from API.
	 *
	 * @param mixed $features Feature flags.
	 * @return array
	 */
	private static function normalize_features( $features ) {
		if ( is_string( $features ) ) {
			$decoded = json_decode( $features, true );
			$features = is_array( $decoded ) ? $decoded : array();
		}

		return is_array( $features ) ? $features : array();
	}

	/**
	 * Check whether the License Manager REST gateway is on this WordPress install.
	 *
	 * @return bool True when local REST dispatch is available.
	 */
	private static function can_use_local_gateway() {
		if ( ! class_exists( '\WP_REST_Request' ) || ! function_exists( 'rest_do_request' ) ) {
			return false;
		}

		$gateway = wp_parse_url( TEKNOTOK_AIT_GATEWAY_BASE_URL );
		$home    = wp_parse_url( home_url() );

		if ( empty( $gateway['host'] ) || empty( $home['host'] ) || strtolower( $gateway['host'] ) !== strtolower( $home['host'] ) ) {
			return false;
		}

		$gateway_port = isset( $gateway['port'] ) ? (int) $gateway['port'] : null;
		$home_port    = isset( $home['port'] ) ? (int) $home['port'] : null;

		return $gateway_port === $home_port;
	}

	/**
	 * Dispatch a same-site gateway request internally to avoid loopback timeouts.
	 *
	 * @param string $endpoint Endpoint slug.
	 * @param array  $payload  Request payload.
	 * @return array|null HTTP-like response, or null when dispatch is unavailable.
	 */
	private static function request_local_gateway( $endpoint, $payload ) {
		$request = new \WP_REST_Request( 'POST', '/teknotok-license/v1/' . sanitize_key( $endpoint ) );

		foreach ( $payload as $key => $value ) {
			$request->set_param( $key, $value );
		}

		$response = rest_do_request( $request );
		if ( ! $response instanceof \WP_REST_Response ) {
			return null;
		}

		return array(
			'response' => array( 'code' => $response->get_status() ),
			'body'     => wp_json_encode( $response->get_data() ),
		);
	}

	/**
	 * Activate a license key.
	 *
	 * @param string $key License Key.
	 * @return bool|\WP_Error True on success, WP_Error on failure.
	 */
	public function activate( $key ) {
		if ( empty( $key ) ) {
			return new \WP_Error( 'missing_key', __( 'Please enter a license key.', 'teknotok-ai-translator' ) );
		}

		$response = $this->make_request( 'activate', array( 'license_key' => $key ) );

		if ( is_wp_error( $response ) ) {
			return $response;
		}

		$code = wp_remote_retrieve_response_code( $response );
		$body = json_decode( wp_remote_retrieve_body( $response ), true );

		if ( 200 !== $code ) {
			$msg = $body['message'] ?? __( 'Activation failed. Please check your key.', 'teknotok-ai-translator' );
			return new \WP_Error( 'activation_error', $msg );
		}

		$data = array_merge( array(
			'license_key' => $key,
			'status'      => 'active',
			'expires_at'  => $body['expires_at'] ?? '',
			'last_check'  => time(),
			'error_count' => 0
		), self::quota_fields_from_body( $body ) );

		update_option( 'teknotok_ait_license_status', $data, false );
		self::clear_usage_caches();
		return true;
	}

	/**
	 * Deactivate the currently active license key.
	 *
	 * @return bool|\WP_Error True on success, WP_Error on failure.
	 */
	public function deactivate() {
		$license = self::get_license_data();
		$key = $license['license_key'] ?? '';

		if ( empty( $key ) ) {
			return true;
		}

		$response = $this->make_request( 'deactivate' );

		if ( is_wp_error( $response ) ) {
			return $response;
		}

		$code = wp_remote_retrieve_response_code( $response );
		$body = json_decode( wp_remote_retrieve_body( $response ), true );

		if ( 200 !== $code ) {
			$msg = $body['message'] ?? __( 'Deactivation failed.', 'teknotok-ai-translator' );
			return new \WP_Error( 'deactivation_error', $msg );
		}

		$data = array(
			'license_key' => '',
			'status'      => 'free',
			'expires_at'  => '',
			'last_check'  => time(),
			'error_count' => 0,
			'plan_slug'   => 'free',
			'site_limit'  => 1,
			'words_limit' => 3000,
			'words_used'  => 0,
			'words_remaining' => 3000,
			'quota_period' => 'lifetime',
			'quota_period_start' => '',
			'quota_period_end' => '',
			'features' => array(),
			'user_message' => '',
		);

		update_option( 'teknotok_ait_license_status', $data, false );
		self::clear_usage_caches();
		return true;
	}

	/**
	 * Perform license validation check.
	 *
	 * @return bool|\WP_Error True on success, WP_Error on failure.
	 */
	public function check() {
		$license = self::get_license_data();
		$key = $license['license_key'] ?? '';

		if ( empty( $key ) ) {
			return new \WP_Error( 'no_key', __( 'No license key entered.', 'teknotok-ai-translator' ) );
		}

		$response = $this->make_request( 'check' );

		if ( is_wp_error( $response ) ) {
			// Increment error count, trigger grace period validation
			$license['error_count'] = (int) ( $license['error_count'] ?? 0 ) + 1;
			update_option( 'teknotok_ait_license_status', $license, false );
			return $response;
		}

		$code = wp_remote_retrieve_response_code( $response );
		$body = json_decode( wp_remote_retrieve_body( $response ), true );

		if ( 200 !== $code ) {
			$license['status']      = 'free';
			$license['error_count'] = 0;
			update_option( 'teknotok_ait_license_status', $license, false );
			$msg = $body['message'] ?? __( 'License is invalid or expired. Switched to Free tier.', 'teknotok-ai-translator' );
			return new \WP_Error( 'check_error', $msg );
		}

		$license['status']      = 'active';
		$license['expires_at']  = $body['expires_at'] ?? '';
		$license['last_check']  = time();
		$license['error_count'] = 0;
		$license = array_merge( $license, self::quota_fields_from_body( $body, $license ) );

		update_option( 'teknotok_ait_license_status', $license, false );
		self::clear_usage_caches();
		return true;
	}

	/**
	 * Clear cached quota/free usage snapshots.
	 *
	 * @return void
	 */
	private static function clear_usage_caches() {
		if ( function_exists( 'delete_transient' ) ) {
			delete_transient( 'teknotok_ait_quota_status_cache' );
			delete_transient( 'teknotok_ait_free_usage_cache' );
		}
	}

	/**
	 * Fetch current quota status from the License Manager.
	 *
	 * @return array|\WP_Error Quota data.
	 */
	public function get_quota_status() {
		$cache = get_transient( 'teknotok_ait_quota_status_cache' );
		if ( false !== $cache ) {
			return $cache;
		}

		$response = $this->make_request( 'quota' );

		if ( is_wp_error( $response ) ) {
			return $response;
		}

		$code = wp_remote_retrieve_response_code( $response );
		$body = json_decode( wp_remote_retrieve_body( $response ), true );

		if ( 404 === (int) $code ) {
			$license = self::get_license_data();
			$is_free = empty( $license['license_key'] ) || 'free' === ( $license['status'] ?? 'free' );
			$warning = __( 'The TeknoTok License Manager on the license server does not support the quota endpoint yet. Free usage is shown with a compatibility fallback. Please update teknotok-license-manager on the license server.', 'teknotok-ai-translator' );

			if ( $is_free ) {
				$free_usage = $this->get_free_usage();
				if ( is_wp_error( $free_usage ) ) {
					return $free_usage;
				}

				$quota = self::quota_fields_from_body( is_array( $free_usage ) ? $free_usage : array(), array( 'plan_slug' => 'free' ) );
				$quota['success'] = true;
				$quota['license_status'] = 'free';
				$quota['server_warning'] = $warning;
				$quota['compatibility_fallback'] = 'free-usage';

				set_transient( 'teknotok_ait_quota_status_cache', $quota, 15 );

				return $quota;
			}

			return new \WP_Error( 'quota_endpoint_missing', $warning );
		}

		if ( 200 !== $code || ! is_array( $body ) ) {
			return new \WP_Error( 'quota_status_error', $body['message'] ?? __( 'Failed to fetch quota details.', 'teknotok-ai-translator' ) );
		}

		$quota = self::quota_fields_from_body( $body, self::get_license_data() );
		$quota['success'] = ! empty( $body['success'] );
		$quota['license_status'] = self::sanitize_key_value( $body['license_status'] ?? ( empty( $quota['plan_slug'] ) ? 'free' : 'active' ) );

		$license = self::get_license_data();
		if ( ! empty( $license['license_key'] ) || 'free' !== ( $quota['plan_slug'] ?? 'free' ) ) {
			update_option( 'teknotok_ait_license_status', array_merge( $license, $quota ), false );
		}

		set_transient( 'teknotok_ait_quota_status_cache', $quota, 15 );

		return $quota;
	}

	/**
	 * Get free translation usage stats from the central server.
	 *
	 * @return array|\WP_Error
	 */
	public function get_free_usage() {
		$cache = get_transient( 'teknotok_ait_free_usage_cache' );
		if ( false !== $cache ) {
			return $cache;
		}

		$response = $this->make_request( 'free-usage' );

		if ( is_wp_error( $response ) ) {
			return $response;
		}

		$code = wp_remote_retrieve_response_code( $response );
		$body = json_decode( wp_remote_retrieve_body( $response ), true );

		if ( 200 !== $code ) {
			return new \WP_Error( 'free_usage_error', $body['message'] ?? __( 'Failed to fetch free usage details.', 'teknotok-ai-translator' ) );
		}

		if ( is_array( $body ) ) {
			$quota = self::quota_fields_from_body( $body, array( 'plan_slug' => 'free' ) );
			$body['limit'] = $body['limit'] ?? $quota['words_limit'];
			$body['word_count'] = $body['word_count'] ?? $quota['words_used'];
			$body = array_merge( $body, $quota );
		}

		set_transient( 'teknotok_ait_free_usage_cache', $body, 15 );

		return $body;
	}

	/**
	 * Daily cron check callback.
	 *
	 * @return void
	 */
	public function daily_check() {
		$license = self::get_license_data();
		$key = $license['license_key'] ?? '';

		if ( empty( $key ) ) {
			// Unlicensed/Free version: register/ping the server so the admin knows the domain is active
			wp_remote_post(
				TEKNOTOK_AIT_LICENSE_API . 'register-free',
				array(
					'method'      => 'POST',
					'timeout'     => 15,
					'redirection' => 5,
					'httpversion' => '1.0',
					'blocking'    => false,
					'headers'     => array(
						'Content-Type' => 'application/json',
					),
					'body'        => wp_json_encode( array(
							'product_slug' => TEKNOTOK_AIT_LICENSE_PRODUCT_SLUG,
						'site_url'     => get_site_url(),
					) ),
				)
			);
		} else {
			$this->check();
		}
	}

	/**
	 * Check for updates against the TeknoTok License Manager.
	 *
	 * @param object $transient Update transient.
	 * @return object
	 */
	public function check_plugin_update( $transient ) {
		if ( empty( $transient->checked ) ) {
			return $transient;
		}

		$license = self::get_license_data();
		$key     = $license['license_key'] ?? '';

		$response = $this->make_request( 'update-check' );
		if ( is_wp_error( $response ) ) {
			return $transient;
		}

		$code = wp_remote_retrieve_response_code( $response );
		$body = json_decode( wp_remote_retrieve_body( $response ), true );

		if ( 200 !== $code || empty( $body ) || ! isset( $body['new_version'] ) ) {
			return $transient;
		}

		if ( version_compare( TEKNOTOK_AIT_VERSION, $body['new_version'], '<' ) ) {
			$slug = TEKNOTOK_AIT_PRODUCT_SLUG;
			$plugin_file = TEKNOTOK_AIT_BASENAME;
			$package_url = TEKNOTOK_AIT_LICENSE_API . 'download/' . rawurlencode( $key );

			$obj = new \stdClass();
			$obj->slug        = $slug;
			$obj->plugin      = $plugin_file;
			$obj->new_version = $body['new_version'];
			$obj->url         = $body['url'] ?? 'https://soft.teknotok.com/teknotok-translator-pro/';
			$obj->package     = $package_url;

			$transient->response[ $plugin_file ] = $obj;
		}

		return $transient;
	}

	/**
	 * Intercept plugin info query to display update details in admin popup.
	 *
	 * @param object|bool $result Response object or false.
	 * @param string      $action The API action being performed.
	 * @param object      $args   API arguments.
	 * @return object|bool
	 */
	public function plugin_info( $result, $action, $args ) {
		if ( 'plugin_information' !== $action ) {
			return $result;
		}

		if ( TEKNOTOK_AIT_PRODUCT_SLUG !== ( $args->slug ?? '' ) ) {
			return $result;
		}

		$license = self::get_license_data();
		$key     = $license['license_key'] ?? '';

		$response = $this->make_request( 'update-check' );
		if ( is_wp_error( $response ) ) {
			return $result;
		}

		$code = wp_remote_retrieve_response_code( $response );
		$body = json_decode( wp_remote_retrieve_body( $response ), true );

		if ( 200 !== $code || empty( $body ) ) {
			return $result;
		}

		$package_url = TEKNOTOK_AIT_LICENSE_API . 'download/' . rawurlencode( $key );

		$res = new \stdClass();
		$res->name           = 'TeknoTok AI Translator';
		$res->slug           = TEKNOTOK_AIT_PRODUCT_SLUG;
		$res->version        = $body['new_version'] ?? TEKNOTOK_AIT_VERSION;
		$res->author         = '<a href="https://soft.teknotok.com">TeknoTok Soft</a>';
		$res->homepage       = 'https://soft.teknotok.com/teknotok-translator-pro/';
		$res->download_link  = $package_url;
		$res->tested         = $body['tested'] ?? '';
		$res->requires       = $body['requires'] ?? '';
		$res->sections       = array(
			'description' => $body['sections']['description'] ?? __( 'One-click AI translation plugin for WordPress and WooCommerce.', 'teknotok-ai-translator' ),
			'changelog'   => $body['sections']['changelog'] ?? __( 'Major multilingual SEO enhancements and performance fixes.', 'teknotok-ai-translator' ),
		);

		return $res;
	}

}
