<?php
/**
 * Settings manager.
 *
 * @package LoginPageCustomizerAndDesigner
 */

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

/**
 * Class LPCD_Settings_Manager
 *
 * Read/write plugin settings from the lpcd_settings table.
 */
class LPCD_Settings_Manager {

	/**
	 * Table name (without prefix).
	 *
	 * @var string
	 */
	const TABLE = 'lpcd_settings';

	/**
	 * Create the settings table.
	 */
	public static function create_tables() {
		global $wpdb;

		$table_name      = $wpdb->prefix . self::TABLE;
		$charset_collate = $wpdb->get_charset_collate();

		$sql = "CREATE TABLE {$table_name} (
			setting_key VARCHAR(191) NOT NULL,
			setting_value LONGTEXT,
			PRIMARY KEY (setting_key)
		) {$charset_collate};";

		require_once ABSPATH . 'wp-admin/includes/upgrade.php';
		dbDelta( $sql );
	}

	/**
	 * Get all settings as a flat key-value array.
	 *
	 * @return array Settings data with defaults filled in.
	 */
	public static function get_all() {
		global $wpdb;

		$table_name = $wpdb->prefix . self::TABLE;
		$defaults   = self::get_defaults();

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		$rows = $wpdb->get_results(
			$wpdb->prepare( "SELECT setting_key, setting_value FROM %i", $table_name ),
			ARRAY_A
		);

		$settings = $defaults;

		if ( is_array( $rows ) ) {
			foreach ( $rows as $row ) {
				$key = $row['setting_key'];
				if ( array_key_exists( $key, $defaults ) ) {
					$settings[ $key ] = $row['setting_value'];

					// Cast booleans back.
					$schema = self::get_schema();
					if ( isset( $schema[ $key ] ) && 'bool' === $schema[ $key ]['type'] ) {
						$settings[ $key ] = ( '1' === $row['setting_value'] || 'true' === $row['setting_value'] );
					}
				}
			}
		}

		return $settings;
	}

	/**
	 * Get a single setting value.
	 *
	 * @param string $key     Setting key.
	 * @param mixed  $default Default value.
	 * @return mixed Setting value.
	 */
	public static function get( $key, $default = null ) {
		$all = self::get_all();
		return isset( $all[ $key ] ) ? $all[ $key ] : $default;
	}

	/**
	 * Save settings data.
	 *
	 * @param array $data Sanitized settings key-value pairs.
	 * @return bool True on success.
	 */
	public static function save( $data ) {
		global $wpdb;

		$table_name = $wpdb->prefix . self::TABLE;
		$schema     = self::get_schema();

		foreach ( $data as $key => $value ) {
			if ( ! isset( $schema[ $key ] ) ) {
				continue;
			}

			// Convert booleans to string for storage.
			if ( is_bool( $value ) ) {
				$value = $value ? '1' : '0';
			}

			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
			$wpdb->replace(
				$table_name,
				array(
					'setting_key'   => $key,
					'setting_value' => $value,
				),
				array( '%s', '%s' )
			);
		}

		return true;
	}

	/**
	 * Get the settings schema with type and default info.
	 *
	 * @return array Schema definition.
	 */
	public static function get_schema() {
		return array(
			// General.
			'pluginEnabled'      => array(
				'type'    => 'bool',
				'default' => true,
			),
			'loginPageTitle'     => array(
				'type'    => 'text',
				'default' => '',
			),
			'customFavicon'      => array(
				'type'    => 'url',
				'default' => '',
			),
			'showBackToBlogLink' => array(
				'type'    => 'bool',
				'default' => true,
			),
			'backToBlogText'     => array(
				'type'    => 'text',
				'default' => '',
			),
			'backToBlogUrl'      => array(
				'type'    => 'url',
				'default' => '',
			),

			// Security.
			'captchaProvider'    => array(
				'type'    => 'select',
				'options' => array( 'none', 'recaptcha_v2', 'recaptcha_v3', 'hcaptcha', 'turnstile' ),
				'default' => 'none',
			),
			'recaptchaSiteKey'   => array(
				'type'    => 'text',
				'default' => '',
			),
			'recaptchaSecretKey' => array(
				'type'    => 'text',
				'default' => '',
			),
			'recaptchaTheme'     => array(
				'type'    => 'select',
				'options' => array( 'light', 'dark' ),
				'default' => 'light',
			),
			'recaptchaSize'      => array(
				'type'    => 'select',
				'options' => array( 'normal', 'compact' ),
				'default' => 'normal',
			),
			'recaptchaOnLogin'   => array(
				'type'    => 'bool',
				'default' => true,
			),
			'recaptchaOnLostPw'  => array(
				'type'    => 'bool',
				'default' => false,
			),

			// reCAPTCHA v3.
			'recaptchaV3SiteKey'   => array(
				'type'    => 'text',
				'default' => '',
			),
			'recaptchaV3SecretKey' => array(
				'type'    => 'text',
				'default' => '',
			),
			'recaptchaV3Threshold' => array(
				'type'    => 'text',
				'default' => '0.5',
			),
			'recaptchaV3OnLogin'   => array(
				'type'    => 'bool',
				'default' => true,
			),
			'recaptchaV3OnLostPw'  => array(
				'type'    => 'bool',
				'default' => false,
			),

			// hCaptcha.
			'hcaptchaSiteKey'    => array(
				'type'    => 'text',
				'default' => '',
			),
			'hcaptchaSecretKey'  => array(
				'type'    => 'text',
				'default' => '',
			),
			'hcaptchaTheme'      => array(
				'type'    => 'select',
				'options' => array( 'light', 'dark' ),
				'default' => 'light',
			),
			'hcaptchaOnLogin'    => array(
				'type'    => 'bool',
				'default' => true,
			),
			'hcaptchaOnLostPw'   => array(
				'type'    => 'bool',
				'default' => false,
			),

			// Cloudflare Turnstile.
			'turnstileSiteKey'   => array(
				'type'    => 'text',
				'default' => '',
			),
			'turnstileSecretKey' => array(
				'type'    => 'text',
				'default' => '',
			),
			'turnstileTheme'     => array(
				'type'    => 'select',
				'options' => array( 'light', 'dark', 'auto' ),
				'default' => 'auto',
			),
			'turnstileOnLogin'   => array(
				'type'    => 'bool',
				'default' => true,
			),
			'turnstileOnLostPw'  => array(
				'type'    => 'bool',
				'default' => false,
			),
			'genericErrorMessages' => array(
				'type'    => 'bool',
				'default' => false,
			),

			// Messages.
			'wrongPasswordMessage'     => array(
				'type'    => 'text',
				'default' => 'The password you entered for that username is incorrect.',
			),
			'invalidUsernameMessage'   => array(
				'type'    => 'text',
				'default' => 'No account found with that username.',
			),
			'invalidEmailMessage'      => array(
				'type'    => 'text',
				'default' => 'No account found with that email address.',
			),
			'emptyUsernameMessage'     => array(
				'type'    => 'text',
				'default' => 'Please enter your username or email address.',
			),
			'emptyPasswordMessage'     => array(
				'type'    => 'text',
				'default' => 'Please enter your password.',
			),
			'captchaFailedMessage'     => array(
				'type'    => 'text',
				'default' => 'CAPTCHA verification failed. Please try again.',
			),
			'logoutSuccessMessage'     => array(
				'type'    => 'text',
				'default' => 'You have been logged out.',
			),
			'passwordResetSentMessage' => array(
				'type'    => 'text',
				'default' => 'A password reset link has been sent to your email.',
			),

			// URL & Redirects.
			'loginRedirectType'  => array(
				'type'    => 'select',
				'options' => array( 'default', 'homepage', 'custom' ),
				'default' => 'default',
			),
			'loginRedirectUrl'   => array(
				'type'    => 'url',
				'default' => '',
			),
			'enableCustomLogin'  => array(
				'type'    => 'bool',
				'default' => false,
			),
			'customLoginSlug'    => array(
				'type'    => 'text',
				'default' => '',
			),
			'defaultLoginRedirectType' => array(
				'type'    => 'select',
				'options' => array( '404', 'homepage', 'custom' ),
				'default' => '404',
			),
			'defaultLoginRedirectUrl'  => array(
				'type'    => 'url',
				'default' => '',
			),
			'registrationRedirectType' => array(
				'type'    => 'select',
				'options' => array( 'default', 'homepage', 'custom' ),
				'default' => 'default',
			),
			'registrationRedirectUrl'  => array(
				'type'    => 'url',
				'default' => '',
			),

			// Advanced.
			'globalCustomCss'    => array(
				'type'    => 'textarea',
				'default' => '',
			),
			'customJsHead'       => array(
				'type'    => 'textarea',
				'default' => '',
			),
			'customJsFooter'     => array(
				'type'    => 'textarea',
				'default' => '',
			),
			'woocommerceEnabled' => array(
				'type'    => 'bool',
				'default' => false,
			),
		);
	}

	/**
	 * Get default values for all settings.
	 *
	 * @return array Default key-value pairs.
	 */
	public static function get_defaults() {
		$schema   = self::get_schema();
		$defaults = array();
		foreach ( $schema as $key => $field ) {
			$defaults[ $key ] = $field['default'];
		}
		return $defaults;
	}
}
