<?php
namespace BotFend\License;

defined('ABSPATH') || exit;

class LicenseKey {

    const CACHE_KEY = 'botfend_license_data';
    const CACHE_TTL = 2592000; // 30 days

    const SECRET_KEY = '';

    const PRO_FEATURES = [
        'cloudflare',
        'geolocation',
        'threat_intel',
        'full_protection',
        'firewall',
        'waf',
        'priority_support'
    ];

    private static $instance = null;
    private $license_data = null;

    private function __construct() {
        add_action('wp_ajax_botfend_license_deactivate', [$this, 'ajax_deactivate']);
        add_action('wp_ajax_botfend_license_activate', [$this, 'ajax_activate']);
        add_action('wp_ajax_botfend_license_status', [$this, 'ajax_get_status']);
    }

    public static function get_instance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * Get the secret key from environment
     * Returns empty string instead of throwing exception
     */
    private function get_secret_key() {
        if (defined('BOTFEND_LICENSE_SECRET') && !empty(BOTFEND_LICENSE_SECRET)) {
            return BOTFEND_LICENSE_SECRET;
        }
        return '';
    }

    /**
     * Validate license key
     */
    public function validate_key($license_key) {
        $license_key = trim($license_key);

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

        if (strpos($license_key, 'BOTFEND-') !== 0) {
            return false;
        }

        $encoded = substr($license_key, 8);
        $encoded = str_replace('-', '', $encoded);
        $encoded = strtr($encoded, '-_', '+/');
        $encoded .= str_repeat('=', (4 - strlen($encoded) % 4) % 4);

        $decoded = base64_decode($encoded, true);
        if ($decoded === false) {
            return false;
        }

        $parts = explode('|', $decoded);
        if (count($parts) !== 4) {
            return false;
        }

        list($email, $expiry, $features_raw, $signature) = $parts;
        $email = strtolower(trim($email));

        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            return false;
        }

        if ($expiry !== 'never') {
            $ts = strtotime($expiry);
            if (!$ts || $ts < time()) {
                return false;
            }
            $expiry = date('Y-m-d', $ts);
        }

        $features_raw = trim($features_raw);
        $payload = $email . '|' . $expiry . '|' . $features_raw;
        
        $secret = $this->get_secret_key();
        
        if (!empty($secret)) {
            $expected = hash_hmac('sha256', $payload, $secret);
            if (!hash_equals($expected, $signature)) {
                return false;
            }
        }

        return [
            'email'     => $email,
            'expires'   => $expiry,
            'features'  => self::PRO_FEATURES,
            'is_valid'  => true,
            'days_left' => $this->calculate_days_left($expiry)
        ];
    }

    /**
     * Activate license
     */
    public function activate($license_key) {
        $data = $this->validate_key($license_key);

        if (!$data) {
            return [
                'success' => false,
                'message' => esc_html__('Invalid or expired license key.', 'botfend')
            ];
        }

        update_option('botfend_license_key', sanitize_text_field($license_key));
        update_option('botfend_license_data', $data);
        $this->clear_cache();

        return [
            'success' => true,
            'message' => esc_html__('License activated successfully.', 'botfend'),
            'data' => $data
        ];
    }

    /**
     * Deactivate license
     */
    public function deactivate() {
        delete_option('botfend_license_key');
        delete_option('botfend_license_data');
        $this->clear_cache();
        return [
            'success' => true,
            'message' => esc_html__('License deactivated.', 'botfend')
        ];
    }

    /**
     * Get license data
     */
    public function get_license_data() {
        if ($this->license_data !== null) {
            return $this->license_data;
        }

        $cached = get_transient(self::CACHE_KEY);
        if ($cached !== false && is_array($cached)) {
            return $this->license_data = $cached;
        }

        $data = get_option('botfend_license_data', null);

        if ($data) {
            $stored_key = get_option('botfend_license_key', '');
            if (!empty($stored_key)) {
                $validation = $this->validate_key($stored_key);
                if ($validation === false) {
                    $this->deactivate();
                    $data = null;
                } else {
                    $data = $validation;
                    update_option('botfend_license_data', $data);
                }
            }
        }

        if ($data) {
            set_transient(self::CACHE_KEY, $data, self::CACHE_TTL);
        }

        return $this->license_data = $data;
    }

    public function has_feature($feature) {
        $data = $this->get_license_data();
        if (!$data || empty($data['is_valid'])) {
            return false;
        }
        return in_array($feature, self::PRO_FEATURES, true);
    }

    public function is_valid() {
        $data = $this->get_license_data();
        return ($data && !empty($data['is_valid']));
    }

    public function is_pro() {
        return $this->is_valid();
    }

    public function days_remaining() {
        $data = $this->get_license_data();
        return ($data && isset($data['days_left'])) ? (int) $data['days_left'] : 0;
    }

    public function get_status_text() {
        $data = $this->get_license_data();

        if (!$data) {
            return esc_html__('No active license', 'botfend');
        }

        if ($data['expires'] === 'never') {
            return esc_html__('Active (Lifetime)', 'botfend');
        }

        $days = $this->days_remaining();

        if ($days <= 0) {
            return esc_html__('Expired', 'botfend');
        }
        if ($days <= 7) {
            return sprintf(esc_html__('Expires in %d days', 'botfend'), $days);
        }

        return sprintf(esc_html__('Active - %d days remaining', 'botfend'), $days);
    }

    private function calculate_days_left($expires) {
        if ($expires === 'never') {
            return 9999;
        }
        $ts = strtotime($expires);
        if (!$ts) {
            return 0;
        }
        return max(0, floor(($ts - time()) / DAY_IN_SECONDS));
    }

    public function clear_cache() {
        delete_transient(self::CACHE_KEY);
        $this->license_data = null;
    }

    public function ajax_deactivate(): void {
        check_ajax_referer('botfend_license_ajax', 'nonce');
        if (!current_user_can('manage_options')) {
            wp_send_json_error(['message' => esc_html__('Permission denied.', 'botfend')]);
        }
        $result = $this->deactivate();
        wp_send_json_success($result);
    }

    public function ajax_activate(): void {
        check_ajax_referer('botfend_license_ajax', 'nonce');
        if (!current_user_can('manage_options')) {
            wp_send_json_error(['message' => esc_html__('Permission denied.', 'botfend')]);
        }
        $key = sanitize_text_field(wp_unslash($_POST['license_key'] ?? ''));
        if (!$key) {
            wp_send_json_error(['message' => esc_html__('Missing license key.', 'botfend')]);
        }
        $result = $this->activate($key);
        if ($result['success']) {
            wp_send_json_success($result);
        }
        wp_send_json_error($result);
    }

    public function ajax_get_status(): void {
        check_ajax_referer('botfend_license_ajax', 'nonce');
        if (!current_user_can('manage_options')) {
            wp_send_json_error(['message' => esc_html__('Permission denied.', 'botfend')]);
        }
        wp_send_json_success([
            'is_valid' => $this->is_valid(),
            'is_pro' => $this->is_pro(),
            'status_text' => $this->get_status_text(),
            'days_remaining' => $this->days_remaining(),
            'features' => self::PRO_FEATURES
        ]);
    }

    private function __clone() {}
    
    public function __wakeup() {
        throw new \Exception('Cannot unserialize singleton');
    }
}