<?php

/**
 * WooNooW Software Updater
 *
 * Embed this class in your WordPress plugin or theme to enable
 * automatic updates from your WooNooW-powered store.
 *
 * @version 1.0.0
 * @package WooNooW_Updater
 * @link https://woonoow.com/docs/developer/software-updates
 *
 * USAGE:
 * 
 * 1. Copy this file to your plugin/theme (e.g., includes/class-woonoow-updater.php)
 * 
 * 2. Include and initialize in your main plugin file:
 * 
 *    require_once plugin_dir_path(__FILE__) . 'includes/class-woonoow-updater.php';
 *    
 *    new WooNooW_Updater([
 *        'api_url'     => 'https://your-store.com/',
 *        'slug'        => 'my-plugin',
 *        'version'     => MY_PLUGIN_VERSION,
 *        'license_key' => get_option('my_plugin_license_key'),
 *        'plugin_file' => __FILE__,  // For plugins
 *        // OR
 *        'theme_slug'  => 'my-theme', // For themes
 *    ]);
 */

if (!class_exists('WooNooW_Updater')) {

    class WooNooW_Updater
    {
        /**
         * @var string API base URL
         */
        private $api_url;

        /**
         * @var string Software slug
         */
        private $slug;

        /**
         * @var string Plugin file path (for plugins)
         */
        private $plugin_file;

        /**
         * @var string Theme slug (for themes)
         */
        private $theme_slug;

        /**
         * @var string Current version
         */
        private $version;

        /**
         * @var string License key
         */
        private $license_key;

        /**
         * @var string Cache key for transient
         */
        private $cache_key;

        /**
         * @var int Cache TTL in seconds (default: 12 hours)
         */
        private $cache_ttl = 43200;

        /**
         * @var bool Is this a theme update?
         */
        private $is_theme = false;

        /**
         * Initialize the updater
         *
         * @param array $config Configuration array
         */
        public function __construct($config)
        {
            $this->api_url = trailingslashit($config['api_url'] ?? '');
            $this->slug = $config['slug'] ?? '';
            $this->version = $config['version'] ?? '1.0.0';
            $this->license_key = $config['license_key'] ?? '';
            $this->cache_key = 'woonoow_update_' . md5($this->slug);

            // Determine if plugin or theme
            if (!empty($config['theme_slug'])) {
                $this->is_theme = true;
                $this->theme_slug = $config['theme_slug'];
            } else {
                $this->plugin_file = $config['plugin_file'] ?? '';
            }

            // Set cache TTL if provided
            if (!empty($config['cache_ttl'])) {
                $this->cache_ttl = (int) $config['cache_ttl'] * 3600; // Convert hours to seconds
            }

            // Don't proceed if no API URL or license
            if (empty($this->api_url) || empty($this->slug)) {
                return;
            }

            // Hook into WordPress update system
            if ($this->is_theme) {
                add_filter('pre_set_site_transient_update_themes', [$this, 'check_theme_update']);
                add_filter('themes_api', [$this, 'theme_info'], 20, 3);
            } else {
                add_filter('pre_set_site_transient_update_plugins', [$this, 'check_plugin_update']);
                add_filter('plugins_api', [$this, 'plugin_info'], 20, 3);
            }

            // Clear cache on upgrade
            add_action('upgrader_process_complete', [$this, 'clear_cache'], 10, 2);
        }

        /**
         * Check for plugin updates
         *
         * @param object $transient Update transient
         * @return object Modified transient
         */
        public function check_plugin_update($transient)
        {
            if (empty($transient->checked)) {
                return $transient;
            }

            $remote = $this->get_remote_info();

            if ($remote && !empty($remote->latest_version)) {
                if (version_compare($this->version, $remote->latest_version, '<')) {
                    $plugin_file = plugin_basename($this->plugin_file);

                    $transient->response[$plugin_file] = (object) [
                        'slug' => $this->slug,
                        'plugin' => $plugin_file,
                        'new_version' => $remote->latest_version,
                        'package' => $remote->download_url ?? '',
                        'url' => $remote->homepage ?? '',
                        'tested' => $remote->wordpress->tested ?? '',
                        'requires' => $remote->wordpress->requires ?? '',
                        'requires_php' => $remote->wordpress->requires_php ?? '',
                        'icons' => (array) ($remote->wordpress->icons ?? []),
                        'banners' => (array) ($remote->wordpress->banners ?? []),
                    ];
                } else {
                    // No update available
                    $transient->no_update[plugin_basename($this->plugin_file)] = (object) [
                        'slug' => $this->slug,
                        'plugin' => plugin_basename($this->plugin_file),
                        'new_version' => $this->version,
                    ];
                }
            }

            return $transient;
        }

        /**
         * Check for theme updates
         *
         * @param object $transient Update transient
         * @return object Modified transient
         */
        public function check_theme_update($transient)
        {
            if (empty($transient->checked)) {
                return $transient;
            }

            $remote = $this->get_remote_info();

            if ($remote && !empty($remote->latest_version)) {
                if (version_compare($this->version, $remote->latest_version, '<')) {
                    $transient->response[$this->theme_slug] = [
                        'theme' => $this->theme_slug,
                        'new_version' => $remote->latest_version,
                        'package' => $remote->download_url ?? '',
                        'url' => $remote->homepage ?? '',
                        'requires' => $remote->wordpress->requires ?? '',
                        'requires_php' => $remote->wordpress->requires_php ?? '',
                    ];
                }
            }

            return $transient;
        }

        /**
         * Provide plugin information for details popup
         *
         * @param mixed $result Default result
         * @param string $action Action being performed
         * @param object $args Arguments
         * @return mixed Plugin info or default result
         */
        public function plugin_info($result, $action, $args)
        {
            if ($action !== 'plugin_information' || !isset($args->slug) || $args->slug !== $this->slug) {
                return $result;
            }

            $remote = $this->get_remote_info();

            if (!$remote) {
                return $result;
            }

            return (object) [
                'name' => $remote->product->name ?? $this->slug,
                'slug' => $this->slug,
                'version' => $remote->latest_version,
                'tested' => $remote->wordpress->tested ?? '',
                'requires' => $remote->wordpress->requires ?? '',
                'requires_php' => $remote->wordpress->requires_php ?? '',
                'author' => $remote->author ?? '',
                'homepage' => $remote->homepage ?? '',
                'download_link' => $remote->download_url ?? '',
                'sections' => [
                    'description' => $remote->description ?? '',
                    'changelog' => nl2br($remote->changelog ?? ''),
                ],
                'banners' => (array) ($remote->wordpress->banners ?? []),
                'icons' => (array) ($remote->wordpress->icons ?? []),
                'last_updated' => $remote->release_date ?? '',
            ];
        }

        /**
         * Provide theme information for details popup
         *
         * @param mixed $result Default result
         * @param string $action Action being performed
         * @param object $args Arguments
         * @return mixed Theme info or default result
         */
        public function theme_info($result, $action, $args)
        {
            if ($action !== 'theme_information' || !isset($args->slug) || $args->slug !== $this->theme_slug) {
                return $result;
            }

            $remote = $this->get_remote_info();

            if (!$remote) {
                return $result;
            }

            return (object) [
                'name' => $remote->product->name ?? $this->theme_slug,
                'slug' => $this->theme_slug,
                'version' => $remote->latest_version,
                'requires' => $remote->wordpress->requires ?? '',
                'requires_php' => $remote->wordpress->requires_php ?? '',
                'author' => $remote->author ?? '',
                'homepage' => $remote->homepage ?? '',
                'download_link' => $remote->download_url ?? '',
                'sections' => [
                    'description' => $remote->description ?? '',
                    'changelog' => nl2br($remote->changelog ?? ''),
                ],
                'last_updated' => $remote->release_date ?? '',
            ];
        }

        /**
         * Get remote version info from API
         *
         * @return object|null Remote info or null on failure
         */
        private function get_remote_info()
        {
            // Check cache first
            $cached = get_transient($this->cache_key);
            if ($cached !== false) {
                if ($cached === 'no_update') {
                    return null;
                }
                return $cached;
            }

            // Make API request
            $response = wp_remote_post($this->api_url . 'wp-json/woonoow/v1/software/check', [
                'timeout' => 15,
                'headers' => [
                    'Content-Type' => 'application/json',
                ],
                'body' => wp_json_encode([
                    'license_key' => $this->license_key,
                    'slug' => $this->slug,
                    'version' => $this->version,
                    'site_url' => home_url(),
                    'wp_version' => get_bloginfo('version'),
                    'php_version' => phpversion(),
                ]),
            ]);

            if (is_wp_error($response) || wp_remote_retrieve_response_code($response) !== 200) {
                // Cache failure for shorter time to retry sooner
                set_transient($this->cache_key, 'no_update', 3600);
                return null;
            }

            $data = json_decode(wp_remote_retrieve_body($response));

            if (!$data || empty($data->success)) {
                set_transient($this->cache_key, 'no_update', 3600);
                return null;
            }

            if (empty($data->update_available)) {
                set_transient($this->cache_key, 'no_update', $this->cache_ttl);
                return null;
            }

            // Cache the update info
            set_transient($this->cache_key, $data, $this->cache_ttl);

            return $data;
        }

        /**
         * Clear update cache after upgrade
         *
         * @param object $upgrader Upgrader instance
         * @param array $options Upgrade options
         */
        public function clear_cache($upgrader, $options)
        {
            if ($this->is_theme) {
                if ($options['action'] === 'update' && $options['type'] === 'theme') {
                    if (isset($options['themes']) && in_array($this->theme_slug, $options['themes'])) {
                        delete_transient($this->cache_key);
                    }
                }
            } else {
                if ($options['action'] === 'update' && $options['type'] === 'plugin') {
                    if (isset($options['plugins']) && in_array(plugin_basename($this->plugin_file), $options['plugins'])) {
                        delete_transient($this->cache_key);
                    }
                }
            }
        }

        /**
         * Force check for updates (bypass cache)
         */
        public function force_check()
        {
            delete_transient($this->cache_key);
            return $this->get_remote_info();
        }

        /**
         * Get license status
         *
         * @return array|null License status or null on failure
         */
        public function get_license_status()
        {
            if (empty($this->license_key)) {
                return ['valid' => false, 'error' => 'no_license'];
            }

            $response = wp_remote_post($this->api_url . 'wp-json/woonoow/v1/licenses/validate', [
                'timeout' => 15,
                'headers' => [
                    'Content-Type' => 'application/json',
                ],
                'body' => wp_json_encode([
                    'license_key' => $this->license_key,
                ]),
            ]);

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

            return json_decode(wp_remote_retrieve_body($response), true);
        }
    }
}
