<?php
defined( 'ABSPATH' ) || exit;

/* ======================================================================
   247ChatMate — Licensing
   PHASE 2 EXPLICIT TRIAL ACTIVATION
   BATCH 7 PREP — LICENCE STATUS DIAGNOSTICS
====================================================================== */

if ( ! defined( 'MATEWA_LICENSE_OPTION' ) ) {
	define( 'MATEWA_LICENSE_OPTION', 'matewa_license_key' );
}

if ( ! defined( 'MATEWA_TRIAL_OPTION' ) ) {
	define( 'MATEWA_TRIAL_OPTION', 'matewa_trial_started' );
}

if ( ! defined( 'MATEWA_TRIAL_DAYS' ) ) {
	define( 'MATEWA_TRIAL_DAYS', 28 );
}

if ( ! defined( 'MATEWA_MASTER_KEY' ) ) {
	define( 'MATEWA_MASTER_KEY', '' );
}

if ( ! defined( 'MATEWA_LS_API_KEY' ) ) {
	define( 'MATEWA_LS_API_KEY', 'PUT_THIS_IN_WP_CONFIG' );
}

if ( ! defined( 'MATEWA_LS_CACHE_TTL' ) ) {
	define( 'MATEWA_LS_CACHE_TTL', 12 * HOUR_IN_SECONDS );
}

if ( ! defined( 'MATEWA_LICENSE_LAST_RESULT_OPTION' ) ) {
	define( 'MATEWA_LICENSE_LAST_RESULT_OPTION', 'matewa_license_last_result' );
}

if ( ! defined( 'MATEWA_LICENSE_LAST_ERROR_OPTION' ) ) {
	define( 'MATEWA_LICENSE_LAST_ERROR_OPTION', 'matewa_license_last_error' );
}

if ( ! defined( 'MATEWA_LICENSE_INSTANCE_OPTION' ) ) {
	define( 'MATEWA_LICENSE_INSTANCE_OPTION', 'matewa_license_instance_binding' );
}

if ( ! defined( 'MATEWA_LICENSE_DAILY_CHECK_HOOK' ) ) {
	define( 'MATEWA_LICENSE_DAILY_CHECK_HOOK', 'matewa_daily_license_check' );
}


if ( ! function_exists( 'matewa_should_defer_remote_license_validation' ) ) {
	function matewa_should_defer_remote_license_validation() {
		if ( function_exists( 'wp_doing_ajax' ) && wp_doing_ajax() ) {
			return true;
		}

		if ( ! is_admin() ) {
			// PAIDLICENCEFRONTENDSAFETY3F5E3:
			// Frontend requests must remain local/cache-only. Manual admin
			// checks and the daily heartbeat can still force a remote check.
			return true;
		}

		$option_page = '';
		if ( isset( $_POST['option_page'] ) ) {
			$option_page = sanitize_key( wp_unslash( $_POST['option_page'] ) );
		}

		if ( 'matewa_settings' === $option_page ) {
			return true;
		}

		// LICENCERENDERSAFETYFIX1:
		// Normal wp-admin requests must stay cached/local-only.
		// Manual licence checks and the daily heartbeat pass $force_remote=true,
		// so they bypass this guard intentionally.
		return true;
	}
}

if ( ! function_exists( 'matewa_get_license_key' ) ) {
	function matewa_get_license_key() {
		return trim( (string) get_option( MATEWA_LICENSE_OPTION, '' ) );
	}
}

if ( ! function_exists( 'matewa_license_key_is_founder_beta_access' ) ) {
	function matewa_license_key_is_founder_beta_access( $license_key = '' ) {
		$license_key = trim( (string) $license_key );

		if ( '' === $license_key ) {
			return false;
		}

		if ( function_exists( 'matewa_founder_beta_is_access_code' ) ) {
			return matewa_founder_beta_is_access_code( $license_key );
		}

		$prefix = defined( 'MATEWA_FOUNDER_BETA_CODE_PREFIX' ) ? (string) MATEWA_FOUNDER_BETA_CODE_PREFIX : 'FBETA-';
		$prefix = trim( $prefix );

		if ( '' === $prefix ) {
			return false;
		}

		return 0 === strpos( strtoupper( $license_key ), strtoupper( $prefix ) );
	}
}

if ( ! function_exists( 'matewa_get_trial_started' ) ) {
	function matewa_get_trial_started() {
		return (int) get_option( MATEWA_TRIAL_OPTION, 0 );
	}
}

if ( ! function_exists( 'matewa_trial_has_started' ) ) {
	function matewa_trial_has_started() {
		return matewa_get_trial_started() > 0;
	}
}

if ( ! function_exists( 'matewa_get_owner_email' ) ) {
	function matewa_get_owner_email() {
		return sanitize_email( (string) get_option( 'matewa_marketing_email', '' ) );
	}
}

if ( ! function_exists( 'matewa_has_valid_owner_email' ) ) {
	function matewa_has_valid_owner_email() {
		$email = matewa_get_owner_email();
		return '' !== $email && is_email( $email );
	}
}

if ( ! function_exists( 'matewa_trial_start' ) ) {
	function matewa_trial_start( $timestamp = null ) {
		$timestamp = is_numeric( $timestamp ) ? (int) $timestamp : time();

		if ( $timestamp <= 0 ) {
			$timestamp = time();
		}

		update_option( MATEWA_TRIAL_OPTION, $timestamp, false );

		return $timestamp;
	}
}

if ( ! function_exists( 'matewa_is_master' ) ) {
	function matewa_is_master() {
		$key = matewa_get_license_key();

		if ( '' === MATEWA_MASTER_KEY || '' === $key ) {
			return false;
		}

		return hash_equals( MATEWA_MASTER_KEY, $key );
	}
}

if ( ! function_exists( 'matewa_trial_active' ) ) {
	function matewa_trial_active() {
		$started = matewa_get_trial_started();

		if ( ! $started ) {
			return false;
		}

		return time() < ( $started + ( MATEWA_TRIAL_DAYS * DAY_IN_SECONDS ) );
	}
}

if ( ! function_exists( 'matewa_trial_expired' ) ) {
	function matewa_trial_expired() {
		$started = matewa_get_trial_started();

		if ( ! $started ) {
			return false;
		}

		return ! matewa_trial_active();
	}
}

/* ======================================================================
   LICENCE VALIDATION CACHE / HEARTBEAT HELPERS
====================================================================== */

if ( ! function_exists( 'matewa_get_license_cache_key' ) ) {
	function matewa_get_license_cache_key( $license_key ) {
		return 'matewa_ls_' . md5( trim( (string) $license_key ) . home_url() );
	}
}

if ( ! function_exists( 'matewa_get_stored_license_validation_result' ) ) {
	function matewa_get_stored_license_validation_result( $license_key = '' ) {
		$stored = get_option( MATEWA_LICENSE_LAST_RESULT_OPTION, array() );

		if ( ! is_array( $stored ) || empty( $stored ) ) {
			return false;
		}

		$expected_hash = md5( trim( (string) $license_key ) . home_url() );
		$stored_hash   = isset( $stored['license_hash'] ) ? (string) $stored['license_hash'] : '';

		if ( '' === $stored_hash || ! hash_equals( $expected_hash, $stored_hash ) ) {
			return false;
		}

		$stored['valid']  = ! empty( $stored['valid'] );

		if ( $stored['valid'] && ! matewa_license_result_has_instance_binding( $stored ) ) {
			return false;
		}

		$stored['source'] = 'stored';

		return $stored;
	}
}

if ( ! function_exists( 'matewa_store_license_validation_result' ) ) {
	function matewa_store_license_validation_result( $result, $license_key = '' ) {
		if ( ! is_array( $result ) ) {
			return false;
		}

		$instance_id = isset( $result['instance_id'] ) ? sanitize_text_field( (string) $result['instance_id'] ) : '';

		$safe_result = array(
			'valid'            => ! empty( $result['valid'] ),
			'code'             => sanitize_key( (string) ( $result['code'] ?? 'unknown' ) ),
			'message'          => sanitize_text_field( (string) ( $result['message'] ?? '' ) ),
			'source'           => sanitize_key( (string) ( $result['source'] ?? 'remote' ) ),
			'checked_at'       => isset( $result['checked_at'] ) ? (int) $result['checked_at'] : time(),
			'license_hash'     => md5( trim( (string) $license_key ) . home_url() ),
			'instance_bound'   => ! empty( $result['instance_bound'] ),
			'instance_id_hash' => '' !== $instance_id ? matewa_license_binding_hash( $instance_id ) : sanitize_text_field( (string) ( $result['instance_id_hash'] ?? '' ) ),
		);

		update_option( MATEWA_LICENSE_LAST_RESULT_OPTION, $safe_result, false );

		return true;
	}
}

if ( ! function_exists( 'matewa_store_license_validation_error' ) ) {
	function matewa_store_license_validation_error( $result, $license_key = '' ) {
		if ( ! is_array( $result ) ) {
			return false;
		}

		$safe_error = array(
			'valid'        => false,
			'code'         => sanitize_key( (string) ( $result['code'] ?? 'unknown' ) ),
			'message'      => sanitize_text_field( (string) ( $result['message'] ?? '' ) ),
			'source'       => sanitize_key( (string) ( $result['source'] ?? 'remote' ) ),
			'checked_at'   => isset( $result['checked_at'] ) ? (int) $result['checked_at'] : time(),
			'license_hash' => md5( trim( (string) $license_key ) . home_url() ),
		);

		update_option( MATEWA_LICENSE_LAST_ERROR_OPTION, $safe_error, false );

		return true;
	}
}


if ( ! function_exists( 'matewa_license_binding_hash' ) ) {
	function matewa_license_binding_hash( $value ) {
		$value = trim( (string) $value );

		if ( '' === $value ) {
			return '';
		}

		if ( function_exists( 'wp_salt' ) ) {
			return hash_hmac( 'sha256', $value, wp_salt( 'auth' ) );
		}

		return hash( 'sha256', $value );
	}
}

if ( ! function_exists( 'matewa_license_site_domain' ) ) {
	function matewa_license_site_domain() {
		$host = wp_parse_url( home_url( '/' ), PHP_URL_HOST );
		$host = is_string( $host ) ? strtolower( trim( $host ) ) : '';
		$host = preg_replace( '/[^a-z0-9\.\-]/', '', $host );

		return '' !== $host ? $host : 'wordpress-site';
	}
}

if ( ! function_exists( 'matewa_license_instance_name' ) ) {
	function matewa_license_instance_name() {
		$domain = matewa_license_site_domain();
		$name   = '247ChatMate - ' . $domain;

		return substr( sanitize_text_field( $name ), 0, 90 );
	}
}

if ( ! function_exists( 'matewa_get_license_instance_record' ) ) {
	function matewa_get_license_instance_record( $license_key = '' ) {
		$license_key = trim( (string) $license_key );
		$record      = get_option( MATEWA_LICENSE_INSTANCE_OPTION, array() );

		if ( ! is_array( $record ) || empty( $record ) ) {
			return array();
		}

		$expected_license_hash = matewa_license_binding_hash( $license_key );
		$expected_domain_hash  = matewa_license_binding_hash( matewa_license_site_domain() );
		$stored_license_hash   = isset( $record['license_hash'] ) ? (string) $record['license_hash'] : '';
		$stored_domain_hash    = isset( $record['domain_hash'] ) ? (string) $record['domain_hash'] : '';

		if ( '' === $expected_license_hash || '' === $stored_license_hash || ! hash_equals( $expected_license_hash, $stored_license_hash ) ) {
			return array();
		}

		if ( '' === $expected_domain_hash || '' === $stored_domain_hash || ! hash_equals( $expected_domain_hash, $stored_domain_hash ) ) {
			return array();
		}

		return $record;
	}
}

if ( ! function_exists( 'matewa_get_license_instance_id' ) ) {
	function matewa_get_license_instance_id( $license_key = '' ) {
		$record = matewa_get_license_instance_record( $license_key );

		return isset( $record['instance_id'] ) ? sanitize_text_field( (string) $record['instance_id'] ) : '';
	}
}

if ( ! function_exists( 'matewa_store_license_instance_binding' ) ) {
	function matewa_store_license_instance_binding( $license_key, $instance_id, $instance_name = '' ) {
		$license_key   = trim( (string) $license_key );
		$instance_id   = sanitize_text_field( (string) $instance_id );
		$instance_name = sanitize_text_field( (string) $instance_name );

		if ( '' === $license_key || '' === $instance_id ) {
			return false;
		}

		$record = array(
			'license_hash'  => matewa_license_binding_hash( $license_key ),
			'domain_hash'   => matewa_license_binding_hash( matewa_license_site_domain() ),
			'instance_id'   => $instance_id,
			'instance_name' => '' !== $instance_name ? $instance_name : matewa_license_instance_name(),
			'created_at'    => time(),
		);

		update_option( MATEWA_LICENSE_INSTANCE_OPTION, $record, false );

		return true;
	}
}

if ( ! function_exists( 'matewa_license_result_has_instance_binding' ) ) {
	function matewa_license_result_has_instance_binding( $result ) {
		return is_array( $result ) && ! empty( $result['instance_bound'] ) && ! empty( $result['instance_id_hash'] );
	}
}

if ( ! function_exists( 'matewa_activate_license_instance' ) ) {
	function matewa_activate_license_instance( $license_key ) {
		$license_key = trim( (string) $license_key );

		$result = array(
			'valid'      => false,
			'code'       => 'activation_failed',
			'message'    => 'Licence activation failed. Check the saved licence key and try again.',
			'source'     => 'remote_activation',
			'checked_at' => time(),
			'instance_bound' => false,
		);

		if ( '' === $license_key ) {
			$result['code']    = 'missing_key';
			$result['message'] = 'No licence key saved.';
			return $result;
		}

		$response = wp_remote_post(
			'https://api.lemonsqueezy.com/v1/licenses/activate',
			array(
				'timeout' => 8,
				'headers' => array(
					'Accept'       => 'application/json',
					'Content-Type' => 'application/x-www-form-urlencoded',
				),
				'body'    => array(
					'license_key'   => $license_key,
					'instance_name' => matewa_license_instance_name(),
				),
			)
		);

		if ( is_wp_error( $response ) ) {
			$result['code']    = 'activation_request_error';
			$result['message'] = 'Licence activation request failed. Try again later.';
			return $result;
		}

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

		if ( ! is_array( $body ) ) {
			$result['code']    = 'activation_invalid_response';
			$result['message'] = 'Licence activation server returned an invalid response.';
			return $result;
		}

		$error_message = '';
		if ( ! empty( $body['error'] ) && is_string( $body['error'] ) ) {
			$error_message = sanitize_text_field( $body['error'] );
		}

		if ( 200 !== $status_code || empty( $body['activated'] ) ) {
			$result['code']    = 'activation_failed';
			$result['message'] = '' !== $error_message ? $error_message : 'Licence activation failed. This key may already be in use or over its activation limit.';
			return $result;
		}

		$instance_id = '';
		if ( isset( $body['instance']['id'] ) && is_string( $body['instance']['id'] ) ) {
			$instance_id = sanitize_text_field( $body['instance']['id'] );
		}

		if ( '' === $instance_id ) {
			$result['code']    = 'activation_missing_instance';
			$result['message'] = 'Licence activated, but no site instance was returned. Pro access has not been granted.';
			return $result;
		}

		$instance_name = isset( $body['instance']['name'] ) && is_string( $body['instance']['name'] )
			? sanitize_text_field( $body['instance']['name'] )
			: matewa_license_instance_name();

		matewa_store_license_instance_binding( $license_key, $instance_id, $instance_name );

		$result['valid']          = true;
		$result['code']           = 'activated';
		$result['message']        = 'Licence activated for this website.';
		$result['instance_bound'] = true;
		$result['instance_id_hash'] = matewa_license_binding_hash( $instance_id );

		return $result;
	}
}

if ( ! function_exists( 'matewa_clear_paid_license_validation_state' ) ) {
	function matewa_clear_paid_license_validation_state( $old_license_key = '', $new_license_key = '' ) {
		$old_license_key = trim( (string) $old_license_key );
		$new_license_key = trim( (string) $new_license_key );

		if ( $old_license_key === $new_license_key ) {
			return false;
		}

		// PAIDLICENCECLEARSYNC3F5E3:
		// A changed or cleared saved licence key must not keep an old paid
		// LemonSqueezy validation snapshot alive. This keeps Pro from remaining
		// active after the paid key is removed or replaced.
		foreach ( array_unique( array_filter( array( $old_license_key, $new_license_key ) ) ) as $license_key ) {
			if ( function_exists( 'delete_transient' ) ) {
				delete_transient( matewa_get_license_cache_key( $license_key ) );
			}
		}

		delete_option( MATEWA_LICENSE_LAST_RESULT_OPTION );
		delete_option( MATEWA_LICENSE_LAST_ERROR_OPTION );
		delete_option( MATEWA_LICENSE_INSTANCE_OPTION );

		return true;
	}
}

if ( ! function_exists( 'matewa_sync_paid_license_validation_state_on_option_update' ) ) {
	function matewa_sync_paid_license_validation_state_on_option_update( $old_value, $value, $option ) {
		if ( MATEWA_LICENSE_OPTION !== $option ) {
			return;
		}

		matewa_clear_paid_license_validation_state( $old_value, $value );
	}
}

add_action( 'update_option_' . MATEWA_LICENSE_OPTION, 'matewa_sync_paid_license_validation_state_on_option_update', 10, 3 );

/* ======================================================================
   LEMON SQUEEZY VALIDATION
   Minimal diagnostic layer for admin feedback
====================================================================== */

if ( ! function_exists( 'matewa_get_license_validation_result' ) ) {
	function matewa_get_license_validation_result( $license_key = '', $force_remote = false ) {
		static $request_cache = array();

		$license_key = trim( (string) $license_key );

		$result = array(
			'valid'      => false,
			'code'       => 'unknown',
			'message'    => '',
			'source'     => 'runtime',
			'checked_at' => time(),
		);

		if ( '' === $license_key ) {
			$result['code']    = 'missing_key';
			$result['message'] = 'No licence key saved.';
			return $result;
		}

		if ( matewa_license_key_is_founder_beta_access( $license_key ) ) {
			// PAIDBETASEPARATIONSAFETY3F5E3:
			// Private Founder Beta keys must not be sent to LemonSqueezy or
			// stored as failed paid licence checks. Founder Beta remains a
			// separate entitlement source below paid LemonSqueezy validation.
			$result['code']    = 'founder_beta_key';
			$result['message'] = 'Private Founder Beta access key saved. LemonSqueezy validation skipped.';
			$result['source']  = 'local';
			return $result;
		}

		$cache_key = matewa_get_license_cache_key( $license_key );

		if ( $force_remote ) {
			delete_transient( $cache_key );
		} elseif ( isset( $request_cache[ $cache_key ] ) && is_array( $request_cache[ $cache_key ] ) ) {
			return $request_cache[ $cache_key ];
		}

		$cached = $force_remote ? false : get_transient( $cache_key );

		if ( is_array( $cached ) ) {
			$cached = array_merge( $result, $cached );
			$cached['valid']  = ! empty( $cached['valid'] );

			if ( $cached['valid'] && ! matewa_license_result_has_instance_binding( $cached ) ) {
				$cached['valid']   = false;
				$cached['code']    = 'instance_not_bound';
				$cached['message'] = 'Licence must be activated for this website before Pro access is granted.';
			}

			$cached['source'] = 'cache';

			$request_cache[ $cache_key ] = $cached;

			return $cached;
		}

		if ( false !== $cached ) {
			$result['valid']   = (bool) $cached;
			$result['code']    = $result['valid'] ? 'valid_cached' : 'invalid_cached';
			$result['message'] = $result['valid']
				? 'Licence validation passed from cache.'
				: 'Licence validation failed from cache.';
			$result['source']  = 'cache';

			$request_cache[ $cache_key ] = $result;

			return $result;
		}

		if ( ! $force_remote && matewa_should_defer_remote_license_validation() ) {
			$stored = matewa_get_stored_license_validation_result( $license_key );

			if ( is_array( $stored ) ) {
				$request_cache[ $cache_key ] = $stored;

				return $stored;
			}

			$result['code']    = 'deferred_admin_request';
			$result['message'] = 'Licence validation deferred during this admin request.';
			$result['source']  = 'deferred';

			$request_cache[ $cache_key ] = $result;

			return $result;
		}

		$instance_id = matewa_get_license_instance_id( $license_key );

		if ( $force_remote && '' === $instance_id ) {
			$activation_result = matewa_activate_license_instance( $license_key );

			if ( empty( $activation_result['valid'] ) ) {
				set_transient( $cache_key, $activation_result, HOUR_IN_SECONDS );
				matewa_store_license_validation_result( $activation_result, $license_key );
				$request_cache[ $cache_key ] = $activation_result;

				return $activation_result;
			}

			$instance_id = matewa_get_license_instance_id( $license_key );
		}

		if ( '' === $instance_id ) {
			$result['valid']    = false;
			$result['code']     = 'instance_not_bound';
			$result['message']  = 'Licence must be activated for this website before Pro access is granted.';
			$result['source']   = 'local';
			$result['instance_bound'] = false;

			$request_cache[ $cache_key ] = $result;

			return $result;
		}

		$validation_body = array(
			'license_key' => $license_key,
			'instance_id' => $instance_id,
		);

		$response = wp_remote_post(
			'https://api.lemonsqueezy.com/v1/licenses/validate',
			array(
				'timeout' => 5,
				'headers' => array(
					'Accept'       => 'application/json',
					'Content-Type' => 'application/x-www-form-urlencoded',
				),
				'body'    => $validation_body,
			)
		);

		if ( is_wp_error( $response ) ) {
			$result['code']    = 'request_error';
			$result['message'] = 'Licence validation request failed.';
			$result['source']  = 'remote';

			matewa_store_license_validation_error( $result, $license_key );
			$request_cache[ $cache_key ] = $result;

			return $result;
		}

		$status_code = (int) wp_remote_retrieve_response_code( $response );
		$body_raw    = wp_remote_retrieve_body( $response );
		$body        = json_decode( $body_raw, true );

		if ( ! is_array( $body ) ) {
			$result['code']    = 'invalid_response';
			$result['message'] = 'Licence server returned an invalid response.';
			$result['source']  = 'remote';

			matewa_store_license_validation_error( $result, $license_key );
			$request_cache[ $cache_key ] = $result;

			return $result;
		}

		// LICENCEINVALIDRESPONSELOCK1:
		// LemonSqueezy returns expected 4xx JSON responses for invalid, missing,
		// or malformed licence keys. Those are not server failures; store them
		// as a clean invalid licence result so the UI and frontend can fall back
		// safely instead of showing "unexpected response".
		if ( in_array( $status_code, array( 400, 404, 422 ), true ) ) {
			$error_message = '';

			if ( ! empty( $body['error'] ) && is_string( $body['error'] ) ) {
				$error_message = sanitize_text_field( $body['error'] );
			}

			$result['valid']   = false;
			$result['code']    = 'invalid';
			$result['message'] = '' !== $error_message
				? $error_message
				: 'Licence validation failed. Check the saved licence key and try again.';
			$result['source']  = 'remote';

			set_transient( $cache_key, $result, HOUR_IN_SECONDS );
			matewa_store_license_validation_result( $result, $license_key );
			$request_cache[ $cache_key ] = $result;

			return $result;
		}

		if ( 200 !== $status_code ) {
			$result['code']    = 'invalid_response';
			$result['message'] = 'Licence server returned an invalid response.';
			$result['source']  = 'remote';

			matewa_store_license_validation_error( $result, $license_key );
			$request_cache[ $cache_key ] = $result;

			return $result;
		}

		$license_status = '';
		if ( isset( $body['license_key']['status'] ) && is_string( $body['license_key']['status'] ) ) {
			$license_status = sanitize_key( $body['license_key']['status'] );
		}

		$response_instance_id = '';
		if ( isset( $body['instance']['id'] ) && is_string( $body['instance']['id'] ) ) {
			$response_instance_id = sanitize_text_field( $body['instance']['id'] );
		}

		$valid                 = ! empty( $body['valid'] );
		$valid_paid_statuses   = array( '', 'active', 'inactive' );
		$blocked_paid_statuses = array( 'cancelled', 'canceled', 'refunded', 'expired', 'disabled', 'deactivated' );

		// PAIDLICENCECANCELLATIONREFUNDEXPIREDAUDIT3F5E11:
		// LemonSqueezy remains the paid licence authority, but local entitlement
		// must fail closed for explicit cancellation/refund/expiry/disabled style
		// lifecycle statuses and any unrecognised status that arrives with a true
		// `valid` flag. The paid registry mirror is not consulted here.
		if ( in_array( $license_status, $blocked_paid_statuses, true ) || ! in_array( $license_status, $valid_paid_statuses, true ) ) {
			$valid = false;
		}

		if ( $valid && '' === $response_instance_id ) {
			$valid          = false;
			$license_status = 'instance_not_validated';
		}

		if ( $valid && ! hash_equals( $instance_id, $response_instance_id ) ) {
			$valid          = false;
			$license_status = 'instance_mismatch';
		}

		$result['valid']            = $valid;
		$result['code']             = $valid ? 'valid' : ( '' !== $license_status ? $license_status : 'invalid' );
		$result['source']           = 'remote';
		$result['instance_bound']   = $valid && '' !== $response_instance_id;
		$result['instance_id']      = $response_instance_id;
		$result['instance_id_hash'] = '' !== $response_instance_id ? matewa_license_binding_hash( $response_instance_id ) : '';

		if ( $valid ) {
			$result['message'] = 'Licence validation passed.';
		} elseif ( ! empty( $body['error'] ) && is_string( $body['error'] ) ) {
			$result['message'] = sanitize_text_field( $body['error'] );
		} elseif ( 'cancelled' === $license_status || 'canceled' === $license_status ) {
			$result['message'] = 'Licence key has been cancelled.';
		} elseif ( 'refunded' === $license_status ) {
			$result['message'] = 'Licence key has been refunded.';
		} elseif ( 'expired' === $license_status ) {
			$result['message'] = 'Licence key has expired.';
		} elseif ( 'disabled' === $license_status ) {
			$result['message'] = 'Licence key has been disabled.';
		} elseif ( 'deactivated' === $license_status ) {
			$result['message'] = 'Licence key has been deactivated.';
		} elseif ( 'instance_not_validated' === $license_status ) {
			$result['message'] = 'Licence key is valid, but this website instance was not validated. Pro access has not been granted.';
		} elseif ( 'instance_mismatch' === $license_status ) {
			$result['message'] = 'Licence key is linked to a different website instance. Pro access has not been granted.';
		} else {
			$result['message'] = 'Licence validation failed.';
		}

		set_transient( $cache_key, $result, MATEWA_LS_CACHE_TTL );
		matewa_store_license_validation_result( $result, $license_key );
		$request_cache[ $cache_key ] = $result;

		return $result;
	}
}

if ( ! function_exists( 'matewa_validate_license_ls' ) ) {
	function matewa_validate_license_ls( $license_key ) {
		$result = matewa_get_license_validation_result( $license_key );
		return ! empty( $result['valid'] );
	}
}

/* ======================================================================
   CONTROLLED DAILY LICENCE HEARTBEAT
====================================================================== */

if ( ! function_exists( 'matewa_run_daily_license_check' ) ) {
	function matewa_run_daily_license_check() {
		$license_key = matewa_get_license_key();

		if ( '' === $license_key || matewa_is_master() ) {
			return false;
		}

		if ( matewa_license_key_is_founder_beta_access( $license_key ) ) {
			return false;
		}

		return matewa_get_license_validation_result( $license_key, true );
	}
}

if ( ! function_exists( 'matewa_schedule_daily_license_check' ) ) {
	function matewa_schedule_daily_license_check() {
		if ( ! function_exists( 'wp_next_scheduled' ) || ! function_exists( 'wp_schedule_event' ) ) {
			return;
		}

		if ( wp_next_scheduled( MATEWA_LICENSE_DAILY_CHECK_HOOK ) ) {
			return;
		}

		wp_schedule_event( time() + HOUR_IN_SECONDS, 'daily', MATEWA_LICENSE_DAILY_CHECK_HOOK );
	}
}

if ( ! function_exists( 'matewa_clear_daily_license_check' ) ) {
	function matewa_clear_daily_license_check() {
		if ( ! function_exists( 'wp_next_scheduled' ) || ! function_exists( 'wp_unschedule_event' ) ) {
			return;
		}

		$timestamp = wp_next_scheduled( MATEWA_LICENSE_DAILY_CHECK_HOOK );

		if ( $timestamp ) {
			wp_unschedule_event( $timestamp, MATEWA_LICENSE_DAILY_CHECK_HOOK );
		}
	}
}

add_action( MATEWA_LICENSE_DAILY_CHECK_HOOK, 'matewa_run_daily_license_check' );
add_action( 'init', 'matewa_schedule_daily_license_check' );

if ( defined( 'MATEWA_MAIN_FILE' ) && function_exists( 'register_deactivation_hook' ) ) {
	register_deactivation_hook( MATEWA_MAIN_FILE, 'matewa_clear_daily_license_check' );
}

/* ======================================================================
   DEVELOPMENT OVERRIDE (SAFE)
====================================================================== */

if ( ! defined( 'MATEWA_DEV_FORCE_PRO' ) ) {
	define( 'MATEWA_DEV_FORCE_PRO', false );
}

if ( ! function_exists( 'matewa_get_entitlement_state' ) ) {
	function matewa_get_entitlement_state() {
		if ( defined( 'MATEWA_DEV_FORCE_PRO' ) && true === MATEWA_DEV_FORCE_PRO ) {
			return MATEWA_MODE_PRO;
		}

		if ( matewa_is_master() ) {
			return MATEWA_MODE_MASTER;
		}

		$license = matewa_get_license_key();

		$license_is_agency_access = function_exists( 'matewa_agency_registry_is_access_code' )
			? matewa_agency_registry_is_access_code( $license )
			: false;

		// AGENCYFREEKEYREGISTRYLOCK1:
		// Free agency own-site access is validated by the 247ChatMate registry.
		// It can unlock Pro/Agency Hub eligibility for the agency's own website,
		// but it must never be sent through LemonSqueezy or grant client seats.
		if ( $license_is_agency_access && function_exists( 'matewa_agency_own_site_access_is_active' ) && matewa_agency_own_site_access_is_active() ) {
			return MATEWA_MODE_PRO;
		}

		if ( function_exists( 'matewa_agency_client_entitlement_is_active' ) && matewa_agency_client_entitlement_is_active() ) {
			return MATEWA_MODE_PRO;
		}

		if ( '' !== $license && ! $license_is_agency_access && ! matewa_license_key_is_founder_beta_access( $license ) && matewa_validate_license_ls( $license ) ) {
			return MATEWA_MODE_PRO;
		}

		if ( function_exists( 'matewa_founder_beta_is_active' ) && matewa_founder_beta_is_active() ) {
			return MATEWA_MODE_PRO;
		}

		if ( matewa_trial_active() ) {
			return MATEWA_MODE_TRIAL;
		}

		if ( matewa_trial_expired() ) {
			return MATEWA_MODE_TRIAL_EXPIRED;
		}

		return MATEWA_MODE_FREE;
	}
}

if ( ! function_exists( 'matewa_license_status' ) ) {
	function matewa_license_status() {
		return matewa_get_entitlement_state();
	}
}

if ( ! function_exists( 'matewa_is_pro' ) ) {
	function matewa_is_pro() {
		$state = matewa_get_entitlement_state();

		return in_array( $state, array( MATEWA_MODE_PRO, MATEWA_MODE_MASTER ), true );
	}
}

if ( ! function_exists( 'matewa_get_license_diagnostics' ) ) {
	function matewa_get_license_diagnostics() {
		$state       = matewa_get_entitlement_state();
		$license_key = matewa_get_license_key();

		$data = array(
			'entitlement_state' => $state,
			'has_license_key'   => ( '' !== $license_key ),
			'is_master'         => false,
			'is_dev_forced'     => false,
			'license'           => array(
				'valid'      => false,
				'code'       => 'not_checked',
				'message'    => 'Licence validation not checked.',
				'source'     => 'runtime',
				'checked_at' => time(),
			),
			'trial'             => array(
				'has_started' => matewa_trial_has_started(),
				'started_at'  => matewa_get_trial_started(),
				'active'      => matewa_trial_active(),
				'expired'     => matewa_trial_expired(),
			),
		);

		if ( defined( 'MATEWA_DEV_FORCE_PRO' ) && true === MATEWA_DEV_FORCE_PRO ) {
			$data['is_dev_forced'] = true;
			$data['license']       = array(
				'valid'      => true,
				'code'       => 'dev_force_pro',
				'message'    => 'Pro is active via development override.',
				'source'     => 'constant',
				'checked_at' => time(),
			);

			return $data;
		}

		if ( matewa_is_master() ) {
			$data['is_master'] = true;
			$data['license']   = array(
				'valid'      => true,
				'code'       => 'master_key',
				'message'    => 'Master access is active.',
				'source'     => 'constant',
				'checked_at' => time(),
			);

			return $data;
		}

		$paid_license_result      = array();
		$license_key_is_agency  = function_exists( 'matewa_agency_registry_is_access_code' )
			? matewa_agency_registry_is_access_code( $license_key )
			: false;

		// AGENCYFREEKEYREGISTRYLOCK1:
		// Agency own-site access is a registry entitlement, not a LemonSqueezy
		// paid licence. It unlocks Pro on the agency's own website and prepares
		// Agency Hub eligibility, but reports zero client seats at this checkpoint.
		if ( $license_key_is_agency ) {
			$agency_summary = function_exists( 'matewa_agency_entitlement_get_summary' )
				? matewa_agency_entitlement_get_summary()
				: array();

			$data['agency'] = $agency_summary;

			if ( function_exists( 'matewa_agency_own_site_access_is_active' ) && matewa_agency_own_site_access_is_active() ) {
				$data['license'] = array(
					'valid'       => true,
					'code'        => 'agency_own_site_active',
					'message'     => 'Agency own-site access is active from the registry response.',
					'source'      => 'agency_registry',
					'checked_at'  => isset( $agency_summary['checked_at'] ) ? (int) $agency_summary['checked_at'] : time(),
					'agency_id'   => isset( $agency_summary['agency_id'] ) ? sanitize_key( (string) $agency_summary['agency_id'] ) : '',
					'agency_name' => isset( $agency_summary['agency_name'] ) ? sanitize_text_field( (string) $agency_summary['agency_name'] ) : '',
					'client_seats'=> 0,
				);

				return $data;
			}

			$data['license'] = array(
				'valid'      => false,
				'code'       => isset( $agency_summary['code'] ) ? sanitize_key( (string) $agency_summary['code'] ) : 'agency_access_not_active',
				'message'    => isset( $agency_summary['message'] ) && '' !== $agency_summary['message'] ? sanitize_text_field( (string) $agency_summary['message'] ) : 'Agency own-site access is not active.',
				'source'     => 'agency_registry',
				'checked_at' => isset( $agency_summary['checked_at'] ) ? (int) $agency_summary['checked_at'] : time(),
			);
		} elseif ( '' !== $license_key && ! matewa_license_key_is_founder_beta_access( $license_key ) ) {
			// PAIDLICENCEPLANNING3F5E1:
			// Preserve the existing LemonSqueezy validation path, but make admin
			// diagnostics follow the real entitlement priority. A valid paid
			// licence should be shown as the active source before Founder Beta.
			$paid_license_result = matewa_get_license_validation_result( $license_key );

			if ( ! empty( $paid_license_result['valid'] ) ) {
				$data['license'] = $paid_license_result;

				return $data;
			}
		} elseif ( '' !== $license_key ) {
			$paid_license_result = array(
				'valid'      => false,
				'code'       => 'founder_beta_key',
				'message'    => 'Private Founder Beta access key saved. LemonSqueezy validation skipped.',
				'source'     => 'local',
				'checked_at' => time(),
			);
		}

		if ( function_exists( 'matewa_founder_beta_is_active' ) && matewa_founder_beta_is_active() ) {
			$founder_beta = function_exists( 'matewa_founder_beta_get_last_result' ) ? matewa_founder_beta_get_last_result() : array();
			$data['license'] = array(
				'valid'       => true,
				'code'        => 'founder_beta_active',
				'message'     => 'Founder Beta access is active from the registry response.',
				'source'      => 'founder_beta_registry',
				'checked_at'  => isset( $founder_beta['checked_at'] ) ? (int) $founder_beta['checked_at'] : time(),
				'beta_start'  => isset( $founder_beta['beta_start'] ) ? sanitize_text_field( (string) $founder_beta['beta_start'] ) : '',
				'beta_expiry' => isset( $founder_beta['beta_expiry'] ) ? sanitize_text_field( (string) $founder_beta['beta_expiry'] ) : '',
			);

			return $data;
		}

		if ( '' !== $license_key ) {
			$data['license'] = $paid_license_result;
		} else {
			$data['license'] = array(
				'valid'      => false,
				'code'       => 'missing_key',
				'message'    => 'No licence key saved.',
				'source'     => 'runtime',
				'checked_at' => time(),
			);
		}

		return $data;
	}
}

if ( ! function_exists( 'matewa_can_start_trial' ) ) {
	function matewa_can_start_trial() {
		$state = matewa_get_entitlement_state();

		if ( MATEWA_MODE_FREE !== $state ) {
			return false;
		}

		return matewa_has_valid_owner_email();
	}
}

if ( ! function_exists( 'matewa_start_trial_if_allowed' ) ) {
	function matewa_start_trial_if_allowed() {
		$state = matewa_get_entitlement_state();

		$result = array(
			'ok'      => false,
			'code'    => 'unknown',
			'message' => '',
			'state'   => $state,
		);

		/*
		 * PROTRIALREGISTRYLIVEFILES1:
		 * Paid / master entitlement must not be blocked by registry availability.
		 * Registry validation only runs before a new local trial is started.
		 */
		if ( MATEWA_MODE_PRO === $state || MATEWA_MODE_MASTER === $state ) {
			$result['code']    = 'already_pro';
			$result['message'] = 'Pro is already active.';
			$result['state']   = $state;
			return $result;
		}

		if ( MATEWA_MODE_TRIAL === $state ) {
			$result['code']    = 'already_trial';
			$result['message'] = 'Trial is already active.';
			$result['state']   = $state;
			return $result;
		}

		if ( MATEWA_MODE_TRIAL_EXPIRED === $state ) {
			$result['code']    = 'trial_expired';
			$result['message'] = 'This trial has already expired.';
			$result['state']   = $state;
			return $result;
		}

		if ( ! matewa_has_valid_owner_email() ) {
			$result['code']    = 'missing_email';
			$result['message'] = 'Add a valid marketing email before starting the trial.';
			return $result;
		}

		if ( ! function_exists( 'matewa_pro_trial_registry_start_trial' ) ) {
			$result['code']    = 'registry_client_missing';
			$result['message'] = 'Pro trial validation is not available in this build. Trial start has been blocked safely.';
			return $result;
		}

		$registry_result = matewa_pro_trial_registry_start_trial();

		if ( ! is_array( $registry_result ) || empty( $registry_result['ok'] ) ) {
			$result['code']    = sanitize_key( (string) ( $registry_result['code'] ?? 'registry_unavailable' ) );
			$result['message'] = sanitize_text_field( (string) ( $registry_result['message'] ?? 'Pro trial validation failed. Trial start has been blocked safely.' ) );
			return $result;
		}

		$started_at = isset( $registry_result['trial_started_at'] ) ? (int) $registry_result['trial_started_at'] : 0;
		if ( $started_at <= 0 ) {
			$started_at = time();
		}

		matewa_trial_start( $started_at );

		$result['ok']              = true;
		$result['code']            = sanitize_key( (string) ( $registry_result['code'] ?? 'trial_started' ) );
		$result['message']         = sanitize_text_field( (string) ( $registry_result['message'] ?? 'Your 28-day trial has started.' ) );
		$result['state']           = MATEWA_MODE_TRIAL;
		$result['trial_reference'] = sanitize_text_field( (string) ( $registry_result['trial_reference'] ?? '' ) );

		return $result;
	}
}