<?php
namespace Phox\import\demo;

use Phox\core\admin\DB_Proxy;

/**
 * Demo
 *
 * @package Phox
 * @author WHMCSdes
 * @link https://whmcsdes.com
 */


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

abstract class Demo {

	public $config;

	// Base URL for demo downloads (constant, doesn't change)
	const DEMO_DOWNLOAD_BASE_URL = 'https://wdes.org/download';

	// Source parameter (constant, always WordPress)
	const DEMO_SOURCE = 'wordpress';

	public function __construct() {

		$this->config = $this->config();

		add_filter('wdes/demo-import/files', array( $this, 'register_demo' ));
		add_action( 'wdes/demo-import/'.$this->config['demo_id'].'/after-import', array( $this, 'set_theme_options' ) );
		add_action( 'wdes/demo-import/'.$this->config['demo_id'].'/after-import', array( $this, 'import_slider' ) );
		add_action( 'wdes/demo-import/'.$this->config['demo_id'].'/after-import', array( $this, 'replace_demo_url' ) );
        add_action('wdes/demo-import/' . $this->config['demo_id'] . '/after-import', array($this, 'store_demo_name'));
        add_filter( 'wdes/demo-import/'.$this->config['demo_id'].'/before_widgets_import_data', array( $this, 'widgets_import' ) );

	}

	abstract public function config();

	/**
	 * Get theme options
	 *
	 * This method can return options in two ways:
	 * 1. Return the options array directly (old method - still supported)
	 * 2. Return null/false to use the extracted JSON file (new method)
	 *
	 * @return array|null|false Theme options array or null/false to use local file
	 */
	public function theme_option() {
		return null;
	}

	public function register_demo( $demo ) {

		$demo[] = $this->config;
		return $demo ;

	}

	public function set_theme_options() {

		$options = $this->theme_option();

		// If theme_option() returns null/false, try to load from local file
		if (empty($options)) {
			$demo_id = $this->config['demo_id'] ?? null;
			if ($demo_id) {
				$upload_dir = wp_upload_dir();
				$file_path = trailingslashit($upload_dir['basedir']) . 'phox-demo-import/' . $demo_id . '/theme-options.json';

				if (file_exists($file_path)) {
					$json_content = file_get_contents($file_path);
					$options = json_decode($json_content, true);
				}
			}
		}

		$site_url = get_site_url();
		$demo_args = $this->config ;
		$demo_url = $demo_args['preview_url'];

		$image_url = $demo_url . '/wp-content/uploads/sites/'. $demo_args['demo_num'];
		$n_image_url = $site_url . '/wp-content/uploads';

		if ( (array) $options ) {
            $options = array_map(function ($option) use ($image_url, $n_image_url) {
                if(is_array($option)) return $option;
                if (preg_match('/^https?:\/\/[^\/]+\/[^\/]+\/wp-content\/uploads\/sites\/\d+\/\d+\/\w+\.\w+$/', $option)) {
                        return $option;
                    }
                    if (is_string($option)) {
                        return str_replace($image_url, $n_image_url, $option);
                    }
                    return $option;
                }, $options);

            $db = new DB_Proxy();

            $db->update_options($options);

		}

	}

	/**
	 * Import Slider
	 *
	 * Use to import RevSlider to the demo
	 * Now supports local slider files from extracted ZIP (new system)
	 * with fallback to remote download (old system) for backward compatibility
	 *
	 * @return bool|\WP_Error
	 */
	public function import_slider(){

		$demo_args = $this->config ;

		if ( ! class_exists( 'RevSliderSlider' ) ){
			return false;
		}

		if( ! is_callable( [ new \RevSliderSlider , 'importSliderFromPost' ] ) ){
			return new \WP_Error( 'rev_update', 'Revolution Slider is outdated . Please <a href="admin.php?page=wdes-plugins">Update Plugin</a>.' );
		}

		if ( ! isset( $demo_args['revslider'] ) ){
			return false;
		}

		$revslider = new \RevSliderSlider();
		$sliders = [];

		// Build sliders array
		if( is_array( $demo_args['revslider'] ) ){
			foreach ( $demo_args['revslider'] as $slider ){
				$sliders[] = $slider . '.zip';
			}
		} else {
			$sliders[] = $demo_args['revslider'] . '.zip';
		}

		// Check if we have local extracted slider files
		$upload_dir = wp_upload_dir();
		$local_sliders_dir = trailingslashit($upload_dir['basedir']) . 'phox-demo-import/' . $demo_args['demo_id'];
		$use_local_files = file_exists($local_sliders_dir);

		foreach ( $sliders as $slider ) {

			$slider_file = null;

			if ($use_local_files) {
				// Try to use local slider file from extracted ZIP
				$local_slider_path = $local_sliders_dir . '/' . $slider;

				if (file_exists($local_slider_path)) {
					$slider_file = $local_slider_path;
					error_log('Phox Demo Import: Using local slider file: ' . $slider);
				}
			}

			// Fallback to downloading from remote server (backward compatibility)
			if (empty($slider_file)) {
				$downloader = new \OCDI\Downloader();
				$slider_import_start_time = date('Y-m-d__H-i-s');
				$demo_path = 'https://whmcsdes.com/phoxdemo/' . $demo_args['demo_id'];

				$content_filename = apply_filters( 'wdes/downloaded_content_file_prefix', $slider . '_' ) . $slider_import_start_time . apply_filters( 'wdes/downloaded_content_file_suffix_and_file_extension', '.zip' );
				$file_uri = wp_normalize_path( $demo_path . DIRECTORY_SEPARATOR . $slider );
				$slider_file = $downloader->download_file( $file_uri, $content_filename );

				error_log('Phox Demo Import: Downloaded slider from remote: ' . $slider);
			}

			// Import the slider
			if (!empty($slider_file) && file_exists($slider_file)) {
				ob_start();
				$revslider->importSliderFromPost( true, false, $slider_file);
				ob_clean();
				ob_end_clean();
			} else {
				error_log('Phox Demo Import: Failed to find slider file: ' . $slider);
			}

		}

		return true;

	}

	/**
	 * Replace Url
	 *
	 * This is use to remove all default url from the elementor editor
	 *
	 * @since 1.5.7
	 */
	public function replace_demo_url(){

		$site_url = get_site_url();
		$demo_args = $this->config ;
		$demo_url = $demo_args['preview_url'];

		if ( ! defined( 'ELEMENTOR__FILE__' ) ){
			return false;
		}

		if( ! is_callable( ['Elementor\Utils','replace_urls'] ) ){
			return new \WP_Error( 'ُElementor', 'Elementor is outdated . Please <a href="admin.php?page=wdes-plugins">Update Plugin</a>.' );
		}

		$elementorUtils = new \Elementor\Utils ;


		if (  isset($demo_args['update_media_url']) && isset( $demo_url ) && isset($site_url) ){

			//fix new directory demos
			$_demo_url = str_replace( '/demos', '',$demo_url );

			//TODO: check images dynamic by using demo number on next demo after fancy

			//check images url
			$image_url = $demo_url . '/wp-content/uploads/sites/'. $demo_args['demo_num'];
			$n_image_url = $site_url . '/wp-content/uploads';
			$elementorUtils-> replace_urls($image_url, $n_image_url);

			//recheck all site links
            $elementorUtils-> replace_urls($_demo_url, $site_url);
            $elementorUtils-> replace_urls($demo_url, $site_url);

		}

		//setup demo elementor kit
		if( isset( $demo_args['elementor_kit'] ) ){

			$elementor_query = new \WP_Query([
				'post_type' => 'elementor_library',
				'title' => $demo_args['elementor_kit']
			]);

			if( $elementor_query->have_posts() ){
				while ( $elementor_query->have_posts() ) {
					$elementor_query->the_post();
					update_option( 'elementor_active_kit', get_the_ID() );
				}
			}
		}

	}

	/**
	 * Before Widget Import
	 * check all links in widget and replace it
	 * it work with all demos
	 *
	 * @since 1.5.7
	 * @param $import_files
	 * @return mixed
	 */
	public function widgets_import($import_files){
		return $import_files;
	}


    /**
     * Store Demo Name
     *
     * Stores the imported demo name in WordPress options
     *
     * @since 2.5.0
     * @return void
     */
    public function store_demo_name()
    {
        if (isset($this->config['demo_name'])) {
            update_option('phox_active_demo', $this->config['demo_name']);
        }
    }

	/**
	 * Build Demo Download URL
	 *
	 * Constructs the download URL for demo imports using the base URL and purchase code.
	 * The URL follows the pattern: https://wdes.org/download?purchase-code=xxx&url=xxx&file=xxx&type=xxx&source=wordpress
	 *
	 * @param string|null $file_name The file name/ID for the demo (e.g., 'primary', 'galaxy')
     * @param string $site_url The URL of the current site (e.g., 'https://example.com')
	 * @return string|false The constructed URL or false if purchase code is not available
	 *@since 2.5.0
	 */
	public function build_demo_url(string $file_name = null, string $site_url= ''): bool|string
    {
		// Use config demo_id if file_name not provided
		if (empty($file_name) && isset($this->config['demo_id'])) {
			$file_name = str_replace('-demo', '', $this->config['demo_id']);
		}

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

		// Get purchase code from license activation
		$purchase_code = $this->get_purchase_code();

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

        //Get the site url
        if(empty($site_url)){
            $site_url = get_site_url();
        }

		// Build query parameters
		$query_params = [
			'purchase-code' => $purchase_code,
			'url'           => $site_url,
			'file'          => sanitize_text_field($file_name),
			'type'          => 'demo',
			'source'        => self::DEMO_SOURCE,
		];

		// Construct the URL
		$url = self::DEMO_DOWNLOAD_BASE_URL . '?' . http_build_query($query_params);

		return $url;
	}

	/**
	 * Get Purchase Code from License Activation
	 *
	 * Retrieves the purchase code from the license activation system.
	 *
	 * @since 2.5.0
	 * @return string|false The purchase code or false if not available
	 */
	private function get_purchase_code()
	{
		try {
			// Check if the License_Activation class exists
			if (!class_exists('Phox\\core\\License_Activation')) {
				return false;
			}

			// Create an instance and check if license is activated
			$license = new \Phox\core\License_Activation();

			if ($license->does_activated()) {

				$license_info = $license->get_license_information();

				return $license_info['purchase_code'] ?? false;
			}

			return false;
		} catch (\Exception $e) {
			// Log error and return false
			error_log('Phox Demo: Error getting purchase code - ' . $e->getMessage());
			return false;
		}
	}

}



