<?php
/**
 * WeCodeArt Framework.
 *
 * WARNING: This file is part of the core WeCodeArt Framework. DO NOT edit this file under any circumstances.
 * Please do all modifications in the form of a child theme.
 *
 * @package 	WeCodeArt Framework
 * @subpackage 	Admin\Installer\Module
 * @copyright   Copyright (c) 2025, WeCodeArt Framework
 * @since 		6.2.9
 * @version		6.6.8
 */

namespace WeCodeArt\Admin\Installer;

defined( 'ABSPATH' ) || exit;

use WeCodeArt\Admin\Request;
use WeCodeArt\Admin\Installer;
use function WeCodeArt\Functions\get_prop;

/**
 * Module Installer
 */
class Module extends Installer {
	/**
	 * Container of valid json properties.
	 *
	 * @var array
	 */
	const VALID_PROPERTIES = [
		'slug',
		'version',
		'destination'
	];

	/**
	 * Destination.
	 *
	 * @var string
	 */
	protected	$source = 'github';

	/**
	 * Destination.
	 *
	 * @var string
	 */
	protected	$destination = '';

	/**
	 * Constructor.
	 */
	public function __construct( $args ) {
        $valid = wp_array_slice_assoc( $args, self::VALID_PROPERTIES );
		$valid = array_map( 'sanitize_text_field', $valid );

		foreach( $valid as $key => $value ) $this->{ $key } = $value;

		$this->set_api_url();
		$this->set_zip_url();
    }

	/**
	 * Sets remote.
	 *
	 * @since 	6.3.7
	 *
	 * @return 	bool
	 */
	public function set_api_url(): bool {
		if ( $this->version === '' ) {
		 	parent::set_api_url();

			return true;
		}
		
		$this->remote = 'https://api.github.com/repos/%s/zipball/refs/tags/%s';

		return true;
	}

	/**
	 * Set zip url.
	 *
	 * @since 	6.3.7
	 * @version 6.6.8
	 *
	 * @return 	mixed
	 */
	public function set_zip_url() {
		if ( $this->version === '' ) {
			parent::set_zip_url();
	
			return true;
		}
		
		$this->package = sprintf( $this->remote, $this->slug, 'v' . $this->version );

		return true;
	}

	/**
	 * Install the module.
	 *
	 * @since 	6.2.9
	 *
	 * @return 	mixed
	 */
	public function install() {
		if( ! $this->package ) {
			return $this->status = null;
		}

		// Include the necessary files
		include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
        require_once ABSPATH . 'wp-admin/includes/file.php';

		// Create an instance of the module upgrader
		$skin 		= new Skin();
		$upgrader 	= new \WP_Upgrader( $skin );

		$result 	= $upgrader->run( [
			'package'						=> $this->package,
			'destination'					=> $this->get_dir(),
			'clear_destination'				=> true,
			'abort_if_destination_exists' 	=> false
		] );

		// Security validation after installation
		$this->validate_module_security();

		// Update options
		$modules		= wecodeart_option( 'modules', [] );
		$current_module	= array_search( $this->slug, array_column( $modules, 'slug' ) );

		$module = [
			'slug'			=> $this->slug,
			'source'		=> $this->source,
			'version'       => $this->get_ver(),
			'update'		=> false,
			'destination'   => $this->destination ?: basename( $this->get_dir() ),
		];
		
		if ( $current_module !== false ) {
			$modules[$current_module] = $module;
		} else {
			$modules[] = $module;
		}

		wecodeart_option( [
			'modules' => $modules
		] );
		
		return $this->status = $this->get_ver();
	}

	/**
	 * Validate module security after installation
	 *
	 * @since 	6.7.0
	 *
	 * @return 	void
	 */
	private function validate_module_security(): void {
		$module_path = $this->get_dir();
		
		if ( ! is_dir( $module_path ) ) {
			return;
		}

		// Initialize security validation
		$security = \WeCodeArt\Support\Modules\Security::get_instance();
		
		// Run security checks
		$is_secure = $security->validate_module( $module_path );
		
		// If security issues found, log them but don't prevent installation
		if ( ! $is_secure ) {
			error_log( sprintf( 
				'WeCodeArt Module Security: Security issues detected in module "%s" but installation continued', 
				basename( $module_path )
			) );
		}
	}

	/**
	 * Uninstall the module.
	 *
	 * @since 	6.2.9
	 *
	 * @return 	mixed
	 */
	public function uninstall() {
		$folder = $this->get_dir();

		if ( is_dir( $folder ) ) {
            $objects = new \RecursiveIteratorIterator(
                new \RecursiveDirectoryIterator( $folder, \RecursiveDirectoryIterator::SKIP_DOTS ),
                \RecursiveIteratorIterator::CHILD_FIRST
            );

            foreach ( $objects as $object ) {
                if ( $object->isDir() ) rmdir( $object->getPathname() );
         		else unlink( $object->getPathname() );
            }

            $removed = rmdir( $folder );
			
			if( $removed ) {
				$modules = wecodeart_option( 'modules', [] );
				$modules = wp_list_filter( $modules, [ 'slug' => $this->slug ], 'NOT' );
				
				wecodeart_option( [
					'modules' => array_values( $modules )
				] );
			}
        }
		
		return $this->status = true;
	}

	/**
	 * Get installer dir.
	 *
	 * @since 	6.2.9
	 *
	 * @return 	string	the installer directory
	 */
	public function get_dir(): string {
		$path = get_prop( wecodeart_config( 'paths' ), [ 'directory' ], '' ) . '/inc/support/modules/';

		if( ! empty( $this->destination ) ) {
			$path .= $this->destination;

			return (string) $path;
		}

		$path .= preg_replace( '/^.*\//', '', $this->slug );

		return (string) wp_normalize_path( $path );
	}

	/**
	 * Fix GitHub path.
	 *
	 * @since 	6.2.9
	 *
	 * @param 	boolean $true       always true
	 * @param 	mixed   $hook_extra not used
	 * @param 	array   $result     the result of the move
	 *
	 * @return 	array 	$result		the result of the move
	 */
	public function upgrader_post_install( $true, $hook_extra, $result ): array {}
}