<?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
 * @copyright   Copyright (c) 2025, WeCodeArt Framework
 * @since 		6.1.2
 * @version		6.6.8
 */

namespace WeCodeArt\Admin;

defined( 'ABSPATH' ) || exit;

use WeCodeArt\Config\Traits\Singleton;
use WeCodeArt\Config\Interfaces\Installable;
use function WeCodeArt\Functions\get_prop;

/**
 * Installer
 */
abstract class Installer implements Installable {
	/**
	 * Container of valid json properties.
	 *
	 * @var array
	 */
	const VALID_PROPERTIES = [
		'slug',
		'version',
		'source',
	];

	/**
	 * Slug.
	 *
	 * @var string
	 */
	protected	$slug = '';

	/**
	 * Source.
	 *
	 * @var string
	 */
	protected	$source = '';
	
	/**
	 * Version.
	 *
	 * @var string
	 */
	protected 	$version = '';
	
	/**
	 * Remote API.
	 *
	 * @var string
	 */
	protected 	$remote = '';
	
	/**
	 * Remote Package.
	 *
	 * @var string
	 */
	protected 	$package = '';

	/**
	 * Status.
	 *
	 * @var string
	 */
	protected	$status;

	/**
	 * Constructor.
	 */
	public function __construct( $args ) {
        $valid = wp_array_slice_assoc( $args, self::VALID_PROPERTIES );
		$valid = array_map( 'sanitize_text_field', $valid );
		$valid = wp_parse_args( $valid, [
			// Should be github based on set_api_url() but lets keep WP as default.
			'source' => 'wordpress'
		] );

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

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

		add_action( 'upgrader_post_install', [ $this, 'upgrader_post_install' ], 20, 3 );
    }
	
	/**
	 * Runs the install process.
	 *
	 * @since 	6.1.2
	 *
	 * @return 	mixed
	 */
	abstract public function install();

	/**
	 * Post install process.
	 *
	 * @since 	6.1.2
	 *
	 * @return 	mixed
	 */
	abstract public function upgrader_post_install( $true, $hook_extra, $result ): array;

	/**
	 * Sets remote.
	 *
	 * @since 	6.1.2
	 *
	 * @return 	bool
	 */
	public function set_api_url(): bool {
		$this->remote = 'https://api.github.com/repos/%s/releases/latest';

		return true;
	}

	/**
	 * Set zip url.
	 *
	 * @since 	6.1.2
	 * @version 6.6.8
	 *
	 * @return 	mixed
	 */
	public function set_zip_url() {
		switch ( $this->source ) {
			case 'custom':
				return $this->package = $this->slug;
			case 'wordpress':
				$api_url  = sprintf( $this->remote, rtrim( basename( $this->slug ), '.php' ) );
				$zip_key  = 'download_link';
				break;
			case 'github':
				$api_url  = sprintf( $this->remote, $this->slug );
				$zip_key  = 'zipball_url';
				break;
			default:
				return null;
		}
		
		$request = new Request( $api_url, [] );
		$request->send( $request::METHOD_GET );
		$response = $request->get_response_body( true );

		$this->version  = get_prop( $response, [ 'tag_name' ] );
	 	$this->package 	= get_prop( $response, [ $zip_key ] );

		return true;
	}

	/**
	 * Get installer dir.
	 *
	 * @since 	6.1.2
	 *
	 * @return 	string	the installer directory
	 */
	public function get_dir(): string {
		$dir = (string) $this->slug;

		switch ( $this->source ) {
			case 'github':
				$dir = preg_replace( '/^.*\//', '', $dir );
				break;
			case 'custom':
				$dir = substr( $dir, strrpos( $dir, '/' ) + 1, strrpos( $dir, '.zip' ) - strrpos( $dir, '/' ) - 1 );
				break;
			default:
				$dir = preg_replace( '/\/[^/]*$/', '', $dir );
				break;
		}
	
		return $dir;
	}

	/**
	 * Get installer version.
	 *
	 * @since 	6.2.9
	 *
	 * @return 	string
	 */
	public function get_ver(): string {
		return str_replace( 'v', '', (string) $this->version );
	}

	/**
	 * Get status.
	 *
	 * @since 	6.1.2
	 *
	 * @return 	mixed
	 */
	public function ok() {
		return $this->status;
	}
}