<?php
namespace Aegisify\Utils;

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

class License {

    const OPTION_KEY              = 'aegisify_license_key';
    const OPTION_EMAIL            = 'aegisify_license_email';
    const TRANSIENT_STATUS        = 'aegisify_license_status';
    const OPTION_FREE_OPTIN       = 'aegisify_free_reg_optin';
    const OPTION_FREE_STATUS      = 'aegisify_free_reg_status'; 
    const OPTION_LAST_DAILY_CHECK = 'aegisify_clm_last_daily_check';
    const OPTION_LAST_STATUS_CHECK = 'aegisify_clm_last_status_check';
    const OPTION_LAST_STATUS_ROW   = 'aegisify_clm_last_status_row';

    public function get_key() : string {
        return (string) get_option(self::OPTION_KEY, '');
    }

    public function set_key(string $key) : void {
        update_option(self::OPTION_KEY, trim($key), false);
        delete_transient(self::TRANSIENT_STATUS);
    }

    public function get_cached_status() : array {
        $s = get_transient(self::TRANSIENT_STATUS);
        return is_array($s) ? $s : array();
    }

    public function get_status() : array {
        return $this->get_cached_status();
    }

    public function is_pro_active(bool $auto_check = true, string $current_version = ''): bool {
        $st = $this->get_cached_status();
        if (empty($st) && $auto_check && $current_version !== '') {
            $st = $this->check_now($current_version);
        }

        $is_pro = !empty($st['is_pro']);
        $lic_state = strtolower((string)($st['status'] ?? ''));

        if ($is_pro) {
            return true;
        }

        return in_array($lic_state, array('active','valid','licensed'), true);
    }

	private function is_manual_force_request(): bool {
		if ( ! is_admin() ) { return false; }
		if ( ! function_exists( 'current_user_can' ) || ! current_user_can( 'manage_options' ) ) { return false; }

		$has_force = false;

		if ( ! empty( $_POST['aegisify_check_license'] ) ) { $has_force = true; }
		if ( ! empty( $_POST['aegisify_activate_license'] ) ) { $has_force = true; }
		if ( ! empty( $_POST['aegisify_deactivate_license'] ) ) { $has_force = true; }

		$action = isset( $_REQUEST['action'] ) ? sanitize_key( (string) wp_unslash( $_REQUEST['action'] ) ) : '';

		$allowed_actions = array(
			'aegisify_license_activate',
			'aegisify_license_deactivate',
			'aegisify_license_check',
			'aegisify_activate_license',
			'aegisify_deactivate_license',
			'aegisify_check_license',
		);

		if ( $action && in_array( $action, $allowed_actions, true ) ) {
			$has_force = true;
		}

		if ( ! $has_force ) {
			return false;
		}

		$nonce = isset( $_REQUEST['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ) ) : '';
		if ( '' === $nonce ) {
			return false;
		}

		$expected_actions = array();

		if ( $action && in_array( $action, $allowed_actions, true ) ) {
			$expected_actions[] = $action;
		}

		if ( ! empty( $_POST['aegisify_check_license'] ) ) {
			$expected_actions[] = 'aegisify_check_license';
			$expected_actions[] = 'aegisify_license_check';
		}
		if ( ! empty( $_POST['aegisify_activate_license'] ) ) {
			$expected_actions[] = 'aegisify_activate_license';
			$expected_actions[] = 'aegisify_license_activate';
		}
		if ( ! empty( $_POST['aegisify_deactivate_license'] ) ) {
			$expected_actions[] = 'aegisify_deactivate_license';
			$expected_actions[] = 'aegisify_license_deactivate';
		}

		$expected_actions[] = 'aegisify_license';

		foreach ( array_unique( $expected_actions ) as $expected_action ) {
			if ( wp_verify_nonce( $nonce, $expected_action ) ) {
				return true;
			}
		}

		return false;
	}


    private function clm_post(string $endpoint, array $payload, int $timeout = 20) : array {
        if (!$endpoint) {
            return array('success'=>false,'status'=>'no_endpoint','message'=>'CLM endpoint is not configured.');
        }

        $args = array(
            'timeout' => $timeout,
            'headers' => array('Content-Type' => 'application/json'),
            'body'    => wp_json_encode($payload),
        );

        $resp = wp_remote_post($endpoint, $args);
        if (is_wp_error($resp)) {
            return array('success'=>false,'status'=>'wp_error','message'=>$resp->get_error_message());
        }

        $code = (int) wp_remote_retrieve_response_code($resp);
        $raw  = (string) wp_remote_retrieve_body($resp);

        if ($code < 200 || $code >= 300) {
            return array('success'=>false,'status'=>'http','message'=>'CLM HTTP '.$code,'http_code'=>$code,'raw'=>$raw);
        }

        $data = json_decode($raw, true);
        if (!is_array($data)) {
            return array('success'=>false,'status'=>'bad_json','message'=>'Invalid JSON from CLM','http_code'=>$code,'raw'=>$raw);
        }

        if (!isset($data['success'])) {
            $data['success'] = true;
        }

        $data['http_code'] = $code;
        return $data;
    }

	public function check_now(string $current_version, bool $force = false) : array {
		static $request_cache = null;
		static $request_cache_at = 0;
		if (is_array($request_cache) && $request_cache_at > 0 && (time() - $request_cache_at) < 15) {
			return $request_cache;
		}

		$min_interval = 4 * HOUR_IN_SECONDS;

		$cached    = $this->get_cached_status();
		$last_opt  = (int) get_option(self::OPTION_LAST_STATUS_CHECK, 0);
		$last_row  = get_option(self::OPTION_LAST_STATUS_ROW, array());
		$last_cached_at = (is_array($cached) && !empty($cached['checked_at'])) ? (int) $cached['checked_at'] : 0;
		$last_check_at = max($last_opt, $last_cached_at);
		$force_allowed = ($force && $this->is_manual_force_request());

		if (!$force_allowed && $last_check_at > 0 && (time() - $last_check_at) < $min_interval) {

			if (is_array($cached) && !empty($cached)) {
				$request_cache = $cached;
				$request_cache_at = time();
				return $cached;
			}
			if (is_array($last_row) && !empty($last_row)) {
				$request_cache = $last_row;
				$request_cache_at = time();
				return $last_row;
			}

			$throttled = array(
				'checked_at' => $last_check_at,
				'success'    => false,
				'status'     => 'throttled',
				'plan'       => '',
				'expires'    => '',
				'is_pro'     => 0,
				'raw'        => array('message' => 'CLM status check throttled (4-hour interval).'),
			);

			$request_cache = $throttled;
			$request_cache_at = time();
			return $throttled;
		}

		$site_url = home_url();
		$domain   = wp_parse_url($site_url, PHP_URL_HOST);


        $payload = array(
            'slug'           => defined('AEGISIFY_SLUG') ? AEGISIFY_SLUG : 'aegisify',
            'product'        => defined('AEGISIFY_SLUG') ? AEGISIFY_SLUG : 'aegisify',
            'version'        => (string) $current_version,
            'domain'         => (string) $domain,
            'site_url'       => (string) $site_url,
            'license_key'    => (string) $this->get_key(),
            'email'          => (string) get_option(self::OPTION_EMAIL, get_option('admin_email', '')),
            'wp_version'     => (string) get_bloginfo('version'),
            'php_version'    => (string) PHP_VERSION,
            'plugin_basename'=> defined('AEGISIFY_BASENAME') ? (string) AEGISIFY_BASENAME : '',
        );

        $endpoint = defined('AEGISIFY_CLM_STATUS_ENDPOINT') ? AEGISIFY_CLM_STATUS_ENDPOINT : '';
        if (!$endpoint && defined('AEGISIFY_CLM_UPDATE_ENDPOINT')) {
            $endpoint = AEGISIFY_CLM_UPDATE_ENDPOINT;
        }

        $data = $this->clm_post($endpoint, $payload, 20);

        if (is_array($data) && isset($data['status']) && is_array($data['status'])) {
            $nested = $data['status'];
            $data['_status_raw'] = $nested;

            foreach ($nested as $k => $v) {
                if (!array_key_exists($k, $data)) {
                    $data[$k] = $v;
                } else {
                    if (in_array($k, array('status','plan','expires','expires_at','is_pro','success','license_status','max_sites','domains','this_domain','bound','is_active','is_paid'), true)) {
                        $data[$k] = $v;
                    }
                }
            }
        }

        $is_pro = false;
        if (is_array($data)) {
            $candidates_true = array(
                $data['is_pro'] ?? null,
                $data['pro'] ?? null,
                $data['license_active'] ?? null,
                $data['active'] ?? null,
            );
            foreach ($candidates_true as $v) {
                if ($v === true || $v === 1 || $v === '1' || $v === 'true') { $is_pro = true; break; }
            }

            if (!$is_pro) {
                $status = strtolower((string)($data['license_status'] ?? $data['status'] ?? ''));
                $plan   = strtolower((string)($data['plan'] ?? $data['tier'] ?? $data['license_type'] ?? ''));
                if (in_array($status, array('active','valid','licensed'), true) && in_array($plan, array('pro','premium','paid','bundle','suite'), true)) {
                    $is_pro = true;
                }
                if (in_array($plan, array('pro','premium','paid','bundle','suite'), true) && $status === '') {
                    $is_pro = true;
                }
            }
        }

        $returned_domain = '';
        if (is_array($data)) {
            $returned_domain = (string)($data['domain'] ?? $data['licensed_domain'] ?? $data['site_domain'] ?? '');
            if ($returned_domain === '' && !empty($data['data']) && is_array($data['data'])) {
                $returned_domain = (string)($data['data']['domain'] ?? $data['data']['licensed_domain'] ?? $data['data']['site_domain'] ?? '');
            }
        }

        $current_domain = (string) $domain;
        if ($returned_domain !== '' && $current_domain !== '' && strcasecmp($returned_domain, $current_domain) !== 0) {
            $is_pro = false;
            if (is_array($data)) {
                $data['success'] = false;
                $data['license_status'] = 'domain_mismatch';
            }
        }
		
        $status_row = array(
            'checked_at' => time(),
            'success'    => !empty($data['success']),
            'status'     => (string)($data['license_status'] ?? $data['status'] ?? ''),
            'plan'       => (string)($data['plan'] ?? $data['tier'] ?? ''),
            'expires'    => (string)($data['expires'] ?? $data['expires_at'] ?? $data['expiration'] ?? ''),
            'is_pro'     => $is_pro ? 1 : 0,
            'raw'        => $data,
        );

        $old_status = $this->get_cached_status();

        set_transient(self::TRANSIENT_STATUS, $status_row, 6 * HOUR_IN_SECONDS);

        // Notify other Aegisify products that the suite license status changed.
        // This allows products to clear stale caches immediately after activate/deactivate.
        if (function_exists('do_action')) {
            do_action('aegisify_license_changed', $status_row, $old_status);
        }


        update_option(self::OPTION_LAST_STATUS_CHECK, (int) ($status_row['checked_at'] ?? time()), false);
        update_option(self::OPTION_LAST_STATUS_ROW, $status_row, false);
        update_option(self::OPTION_LAST_DAILY_CHECK, time(), false);

        if (function_exists('aegisify_update_log')) {
            aegisify_update_log('CLM status checked.', array(
                'http_code' => $data['http_code'] ?? null,
                'success'   => !empty($data['success']),
                'status'    => $status_row,
            ), !empty($data['success']) ? 'INFO' : 'ERROR');
        }
		
		$request_cache = $status_row;
		$request_cache_at = time();
        return $status_row;
    }

    public function activate_now(string $current_version) : array {
        $site_url = home_url();
        $domain   = wp_parse_url($site_url, PHP_URL_HOST);

        $payload = array(
            'slug'        => defined('AEGISIFY_SLUG') ? AEGISIFY_SLUG : 'aegisify',
            'product'     => defined('AEGISIFY_SLUG') ? AEGISIFY_SLUG : 'aegisify',
            'version'     => (string) $current_version,
            'domain'      => (string) $domain,
            'site_url'    => (string) $site_url,
            'license_key' => (string) $this->get_key(),
            'email'       => (string) get_option(self::OPTION_EMAIL, get_option('admin_email', '')),
        );

        $email = (string) ($payload['email'] ?? '');
        $key   = (string) ($payload['license_key'] ?? '');
        if ($key === '' || $email === '' || !is_email($email)) {
            return array('success'=>false,'status'=>'invalid_input','message'=>'License key and a valid email are required.');
        }

        $data = $this->clm_post(defined('AEGISIFY_CLM_ACTIVATE_ENDPOINT') ? AEGISIFY_CLM_ACTIVATE_ENDPOINT : '', $payload, 20);
        if (!empty($data['success'])) {
            $active_status = '';
            $active_plan   = '';
            $active_exp    = '';

            if (!empty($data['data']) && is_array($data['data'])) {
                $active_status = (string) ($data['data']['status'] ?? '');
                $active_plan   = (string) ($data['data']['plan'] ?? '');
                $active_exp    = (string) ($data['data']['expires_at'] ?? '');
                $active_is_pro = !empty($data['data']['is_pro']) || (!empty($data['data']['is_pro']) && (int)$data['data']['is_pro'] === 1);
            } else {
                $active_status = (string) ($data['status'] ?? '');
                $active_plan   = (string) ($data['plan'] ?? '');
                $active_exp    = (string) ($data['expires_at'] ?? '');
                $active_is_pro = !empty($data['is_pro']);
            }

            $row = array(
                'checked_at' => time(),
                'success'    => true,
                'status'     => $active_status !== '' ? $active_status : 'active',
                'plan'       => $active_plan,
                'expires'    => $active_exp,
                'is_pro'     => !empty($active_is_pro) ? 1 : 1, // activation implies pro for suite
                'raw'        => $data,
            );

            set_transient(self::TRANSIENT_STATUS, $row, 6 * HOUR_IN_SECONDS);
            update_option(self::OPTION_LAST_STATUS_CHECK, (int) $row['checked_at'], false);
            update_option(self::OPTION_LAST_STATUS_ROW, $row, false);
        }

        if (function_exists('aegisify_update_log')) {
            aegisify_update_log('CLM activate response.', array(
                'http_code' => $data['http_code'] ?? null,
                'success'   => !empty($data['success']),
                'data'      => $data,
            ), !empty($data['success']) ? 'INFO' : 'ERROR');
        }

        $this->check_now($current_version, true);
        $st = $this->get_cached_status();
        $st_state = strtolower((string)($st['status'] ?? ''));
        $active_after = (!empty($st['is_pro']) || in_array($st_state, array('active','valid','licensed'), true));
        if (!$active_after) {
            delete_transient(self::TRANSIENT_STATUS);
            $data['success'] = false;
            $data['status']  = 'email_or_license_mismatch';
            $data['message'] = $data['message'] ?? 'License activation failed: email and license key must match.';
        }

        return $data;
    }

    public function deactivate_now(string $current_version) : array {
        $site_url = home_url();
        $domain   = wp_parse_url($site_url, PHP_URL_HOST);

        $payload = array(
            'slug'        => defined('AEGISIFY_SLUG') ? AEGISIFY_SLUG : 'aegisify',
            'product'     => defined('AEGISIFY_SLUG') ? AEGISIFY_SLUG : 'aegisify',
            'version'     => (string) $current_version,
            'domain'      => (string) $domain,
            'site_url'    => (string) $site_url,
            'license_key' => (string) $this->get_key(),
            'email'       => (string) get_option(self::OPTION_EMAIL, get_option('admin_email', '')),
        );

        $data = $this->clm_post(defined('AEGISIFY_CLM_DEACTIVATE_ENDPOINT') ? AEGISIFY_CLM_DEACTIVATE_ENDPOINT : '', $payload, 20);

        if (function_exists('aegisify_update_log')) {
            aegisify_update_log('CLM deactivate response.', array(
                'http_code' => $data['http_code'] ?? null,
                'success'   => !empty($data['success']),
                'data'      => $data,
            ), !empty($data['success']) ? 'INFO' : 'ERROR');
        }

        delete_transient(self::TRANSIENT_STATUS);
        $this->check_now($current_version, true);

        return $data;
    }


    public function start_trial_now(string $current_version) : array {
        $site_url = home_url();
        $domain   = wp_parse_url($site_url, PHP_URL_HOST);

        $email = (string) get_option(self::OPTION_EMAIL, get_option('admin_email', ''));
        if ($email === '' || !is_email($email)) {
            $email = (string) get_option('admin_email', '');
        }

        // Collect minimal admin details (requested: admin details + domain).
        $admin_user = array();
        if (function_exists('wp_get_current_user')) {
            $u = wp_get_current_user();
            if ($u && !empty($u->ID)) {
                $admin_user = array(
                    'id'           => (int) $u->ID,
                    'user_login'   => (string) $u->user_login,
                    'display_name' => (string) $u->display_name,
                    'user_email'   => (string) $u->user_email,
                );
            }
        }

        $payload = array(
            'slug'        => defined('AEGISIFY_SLUG') ? AEGISIFY_SLUG : 'aegisify',
            'product'     => defined('AEGISIFY_SLUG') ? AEGISIFY_SLUG : 'aegisify',
            'version'     => (string) $current_version,
            'domain'      => (string) $domain,
            'site_url'    => (string) $site_url,
            'email'       => (string) $email,
            'admin_user'  => $admin_user,
            'wp_version'  => (string) get_bloginfo('version'),
            'php_version' => (string) PHP_VERSION,
        );

        $endpoint = defined('AEGISIFY_CLM_TRIAL_ENDPOINT') ? AEGISIFY_CLM_TRIAL_ENDPOINT : '';
        if (!$endpoint && defined('AEGISIFY_CLM_STATUS_ENDPOINT')) {
            $endpoint = str_replace('/status', '/trial', (string) AEGISIFY_CLM_STATUS_ENDPOINT);
        }

        $data = $this->clm_post($endpoint, $payload, 20);

        if (!empty($data['success'])) {
            $trial_key = '';
            if (!empty($data['license_key'])) {
                $trial_key = (string) $data['license_key'];
            } elseif (!empty($data['data']) && is_array($data['data']) && !empty($data['data']['license_key'])) {
                $trial_key = (string) $data['data']['license_key'];
            }

            if ($trial_key !== '') {
                $this->set_key($trial_key);
                update_option(self::OPTION_EMAIL, $email, false);

                // Force refresh so PRO is immediately enabled after trial issuance.
                $this->check_now($current_version, true);
                return $data;
            }

            $data['success'] = false;
            $data['status']  = 'missing_license_key';
            $data['message'] = $data['message'] ?? 'Trial response missing license_key.';
            return $data;
        }

        return is_array($data) ? $data : array('success'=>false,'status'=>'trial_failed','message'=>'Trial request failed.');
    }

    public function maybe_daily_check(string $current_version) : void {
        $last = (int) get_option(self::OPTION_LAST_DAILY_CHECK, 0);
        if ($last > 0 && (time() - $last) < DAY_IN_SECONDS) {
            return;
        }

        $this->check_now($current_version);

        $this->maybe_send_free_register($current_version);
    }
	
    public function maybe_send_free_register(string $current_version) : void {
        $optin = (int) get_option(self::OPTION_FREE_OPTIN, 0);
        if ($optin !== 1) {
            return;
        }

        $sent = get_transient('aegisify_clm_free_reg_sent');
        if ($sent) {
            return;
        }

        $site_url = home_url();
        $domain   = wp_parse_url($site_url, PHP_URL_HOST);

        $payload = array(
            'slug'      => defined('AEGISIFY_SLUG') ? AEGISIFY_SLUG : 'aegisify',
            'product'   => defined('AEGISIFY_SLUG') ? AEGISIFY_SLUG : 'aegisify',
            'version'   => (string) $current_version,
            'domain'    => (string) $domain,
            'site_url'  => (string) $site_url,
            'admin_email' => (string) get_option('admin_email', ''),
        );

        $endpoint = defined('AEGISIFY_CLM_FREE_REGISTER_ENDPOINT') ? AEGISIFY_CLM_FREE_REGISTER_ENDPOINT : '';
        $data = $this->clm_post($endpoint, $payload, 20);

        if (!empty($data['success'])) {
            update_option(self::OPTION_FREE_STATUS, 'registered', false);
            set_transient('aegisify_clm_free_reg_sent', 1, DAY_IN_SECONDS);
        } else {
            update_option(self::OPTION_FREE_STATUS, 'error', false);
        }

        if (function_exists('aegisify_update_log')) {
            aegisify_update_log('CLM free register response.', array('data'=>$data), !empty($data['success']) ? 'INFO' : 'ERROR');
        }
    }
}
