<?php
/**
 * Main plugin class for the WordPress.org free build.
 *
 * @package CF7MasterPro\Core
 */

namespace CF7MasterPro\Core;

defined( 'ABSPATH' ) || exit;

/**
 * Main plugin singleton.
 */
class Plugin {

	/**
	 * Instance.
	 *
	 * @var Plugin|null
	 */
	private static $instance = null;

	/**
	 * Loader.
	 *
	 * @var Loader
	 */
	private $loader;

	/**
	 * Get instance.
	 *
	 * @return Plugin
	 */
	public static function instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Constructor.
	 */
	private function __construct() {
		$this->loader = new Loader();
	}

	/**
	 * Start plugin.
	 */
	public function run() {
		$this->register_hooks();
		$this->init_modules();
		$this->loader->run();
	}

	/**
	 * Register common hooks.
	 */
	private function register_hooks() {
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_assets' ) );
		add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_frontend_assets' ) );
	}

	/**
	 * Initialize free modules.
	 */
	private function init_modules() {
		( new \CF7MasterPro\Admin\AdminMenu() )->register();
		( new \CF7MasterPro\Admin\SettingsPage() )->register();
		( new \CF7MasterPro\Admin\Notices() )->register();
		( new \CF7MasterPro\Form\MultiStep() )->register();
		( new \CF7MasterPro\Form\ConditionalLogic() )->register();
		( new \CF7MasterPro\Database\Submission() )->register();
		( new \CF7MasterPro\Security\Honeypot() )->register();
		// v2.1で正式公開（既定=有効）。無効化する場合は cf7mp_enable_mw_migration フィルタで false を返す
		if ( apply_filters( 'cf7mp_enable_mw_migration', true ) && class_exists( '\CF7MasterPro\Migration\MigrationPage' ) ) {
			( new \CF7MasterPro\Migration\MigrationPage() )->register();
		}
	}

	/**
	 * Enqueue admin assets.
	 *
	 * @param string $hook Current admin hook.
	 */
	public function enqueue_admin_assets( $hook ) {
		if ( false === strpos( $hook, 'frontierline-forms' ) ) {
			return;
		}
		wp_enqueue_style(
			'cf7mp-admin',
			CF7MP_PLUGIN_URL . 'assets/css/admin.css',
			array(),
			CF7MP_VERSION
		);
		wp_enqueue_script(
			'cf7mp-admin-ui',
			CF7MP_PLUGIN_URL . 'assets/js/admin/cf7mp-admin.js',
			array( 'jquery' ),
			CF7MP_VERSION,
			true
		);
		wp_localize_script(
			'cf7mp-admin-ui',
			'cf7mpAdmin',
			array(
				'ajaxUrl'      => admin_url( 'admin-ajax.php' ),
				'dismissNonce' => wp_create_nonce( 'cf7mp_dismiss' ),
			)
		);
	}

	/**
	 * Enqueue frontend assets.
	 */
	public function enqueue_frontend_assets() {
		wp_enqueue_style(
			'cf7mp-frontend',
			CF7MP_PLUGIN_URL . 'assets/css/frontend.css',
			array(),
			CF7MP_VERSION
		);
		wp_enqueue_script(
			'cf7mp-frontend',
			CF7MP_PLUGIN_URL . 'assets/js/frontend/main.js',
			array( 'jquery' ),
			CF7MP_VERSION,
			true
		);

		$modules = array(
			'multistep'   => 'assets/js/frontend/multistep.js',
			'conditional' => 'assets/js/frontend/conditional.js',
			'validator'   => 'assets/js/frontend/validator.js',
		);
		foreach ( $modules as $handle => $rel_path ) {
			wp_enqueue_script(
				'cf7mp-frontend-' . $handle,
				CF7MP_PLUGIN_URL . $rel_path,
				array( 'cf7mp-frontend' ),
				CF7MP_VERSION,
				true
			);
		}

		$settings = (array) get_option( 'cf7mp_settings', array() );
		wp_localize_script(
			'cf7mp-frontend',
			'cf7mpFrontend',
			array(
				'ajaxUrl'            => admin_url( 'admin-ajax.php' ),
				'nonce'              => wp_create_nonce( 'cf7mp_frontend' ),
				'enableConfirmation' => ! empty( $settings['enable_confirmation'] ),
				'progressStyle'      => $settings['progress_style'] ?? 'step',
				'isAdmin'            => is_user_logged_in() && current_user_can( 'manage_options' ),
				'completeMessage'    => $settings['complete_message'] ?? '',
				'redirectUrl'        => $settings['redirect_url'] ?? '',
			)
		);

		$this->output_brand_css( $settings );
	}

	/**
	 * Output brand CSS variables from discrete settings only.
	 *
	 * @param array $settings Settings.
	 */
	private function output_brand_css( array $settings ) {
		$vars = array(
			'--cf7mp-primary'   => $this->sanitize_css_color( $settings['css_primary'] ?? '' ),
			'--cf7mp-secondary' => $this->sanitize_css_color( $settings['css_secondary'] ?? '' ),
			'--cf7mp-bg'        => $this->sanitize_css_color( $settings['css_bg'] ?? '' ),
			'--cf7mp-border'    => $this->sanitize_css_color( $settings['css_border'] ?? '' ),
			'--cf7mp-success'   => $this->sanitize_css_color( $settings['css_success'] ?? '' ),
			'--cf7mp-radius'    => $this->sanitize_css_radius( $settings['css_radius'] ?? '' ),
			'--cf7mp-font'      => $this->sanitize_css_font_family( $settings['css_font'] ?? '' ),
		);
		$declarations = '';
		foreach ( $vars as $name => $value ) {
			if ( '' !== $value ) {
				$declarations .= $name . ':' . $value . ';';
			}
		}
		if ( '' === $declarations ) {
			return;
		}
		wp_add_inline_style( 'cf7mp-frontend', '.wpcf7-form{' . $declarations . '}' );
	}

	/**
	 * Allow hex colors only.
	 *
	 * @param mixed $value Raw value.
	 * @return string
	 */
	private function sanitize_css_color( $value ) {
		$color = sanitize_hex_color( (string) $value );
		return $color ? $color : '';
	}

	/**
	 * Allow 0-50px radius values only.
	 *
	 * @param mixed $value Raw value.
	 * @return string
	 */
	private function sanitize_css_radius( $value ) {
		if ( ! preg_match( '/^(\d{1,2})(?:px)?$/', trim( (string) $value ), $m ) ) {
			return '';
		}
		return min( 50, (int) $m[1] ) . 'px';
	}

	/**
	 * Allow known font family tokens only.
	 *
	 * @param mixed $value Raw value.
	 * @return string
	 */
	private function sanitize_css_font_family( $value ) {
		$allowed = array(
			'system-ui',
			'sans-serif',
			'serif',
			'monospace',
			'Noto Sans JP',
			'Noto Serif JP',
			'Arial',
			'Helvetica',
			'Verdana',
			'Georgia',
			'Times New Roman',
		);
		$parts   = array_map( 'trim', explode( ',', (string) $value ) );
		$clean   = array();
		foreach ( $parts as $part ) {
			$part = trim( $part, "\"'" );
			if ( in_array( $part, $allowed, true ) ) {
				$clean[] = $part;
			}
		}
		return implode( ', ', array_unique( $clean ) );
	}

	/**
	 * Get loader.
	 *
	 * @return Loader
	 */
	public function loader() {
		return $this->loader;
	}
}
