<?php
/**
 * Plugin Name: Billy
 * Plugin URI: https://wordpress.org/plugins/billy
 * Description: A business-oriented billing suite powered by WordPress.
 * Version: 2.4.0
 * Author: them.es
 * Author URI: https://them.es/plugins/billy
 * License: GPL-2.0+
 * License URI: https://www.gnu.org/licenses/gpl-2.0.txt
 * Text Domain: billy
 */

// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;

// Billy constants.
define( 'BILLY_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
define( 'BILLY_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
define( 'BILLY_PLUGIN_FILE', __FILE__ );
define( 'BILLY_REQUIRED_WP', '6.6' );
define( 'BILLY_REQUIRED_PHP', '7.4' );

if ( ! function_exists( 'wp_get_wp_version' ) ) {
	/**
	 * Fallback of core wp_get_wp_version().
	 * https://developer.wordpress.org/reference/functions/wp_get_wp_version/
	 *
	 * @return string
	 */
	function wp_get_wp_version(): string {
		static $wp_version;

		if ( ! isset( $wp_version ) ) {
			require ABSPATH . WPINC . '/version.php';
		}

		return $wp_version;
	}
}

/**
 * On plugin deactivation.
 *
 * @return void
 */
function billy_deactivate(): void {
	deactivate_plugins( plugin_basename( BILLY_PLUGIN_FILE ) );
}

/**
 * Test if plugin is active.
 *
 * @param string $plugin Plugin slug.
 *
 * @return bool
 */
function billy_is_plugin_active( $plugin = '' ): bool {
	return in_array( $plugin, (array) get_option( 'active_plugins', array() ), true );
}

/**
 * Register "Billy" menu.
 *
 * @return void
 */
function billy_register_menu_page(): void {
	add_menu_page( 'Billy', 'Billy', 'edit_private_posts', 'billy', '', 'dashicons-tickets', 10 );
}
add_action( 'admin_menu', 'billy_register_menu_page' );
define( 'BILLY_ADMIN_MENU', true );

/**
 * On load:
 * 1. Check plugin conflicts and compatibility.
 * 2. Initialize plugin.
 *
 * @return void
 */
function billy_plugins_loaded(): void {
	// Potential plugin conflicts.
	$billy_pro = 'billy-pro/billy-pro.php';
	if ( billy_is_plugin_active( $billy_pro ) ) {
		$billy_pro_version     = get_file_data( WP_PLUGIN_DIR . '/' . $billy_pro, array( 'Version' => 'Version' ) )['Version'];
		$billy_pro_min_version = '2.1.0'; // [2.1.0] Fix fatal error "Declaration of Billy_Pro::init() must be compatible with Billy::init(): void".

		if ( version_compare( $billy_pro_version, $billy_pro_min_version, '<' ) ) {
			add_action(
				'admin_notices',
				function (): void {
					printf( '<div class="%1$s"><p>%2$s</p></div>', 'notice notice-error notice-billy', wp_kses_post( sprintf( __( '<strong>Warning!</strong> %1$s requires the latest version of %1$s Pro to function properly. Please download and install the latest version: <a href="%2$s">them.es</a>', 'billy' ), 'Billy', 'https://them.es/account/' ) ) );

					$activate = filter_input( INPUT_GET, 'activate', FILTER_VALIDATE_BOOLEAN );

					if ( true === $activate ) {
						unset( $_GET['activate'] );
					}
				}
			);

			deactivate_plugins( plugin_basename( BILLY_PRO_PLUGIN_FILE ) );
			// return;
		}
	}

	if ( billy_is_plugin_active( 'classic-editor/classic-editor.php' ) || billy_is_plugin_active( 'disable-gutenberg/disable-gutenberg.php' ) ) {
		add_action(
			'admin_notices',
			function (): void {
				printf( '<div class="%1$s"><p>%2$s</p></div>', 'notice notice-error notice-billy', wp_kses_post( sprintf( __( '<strong>Warning!</strong> %s is not compatible with the Classic Editor. Please deactivate the Classic Editor Plugin.', 'billy' ), 'Billy' ) ) );

				$activate = filter_input( INPUT_GET, 'activate', FILTER_VALIDATE_BOOLEAN );

				if ( true === $activate ) {
					unset( $_GET['activate'] );
				}
			}
		);

		add_action( 'admin_init', 'billy_deactivate' );

		return;
	}

	if ( version_compare( PHP_VERSION, BILLY_REQUIRED_PHP, '<=' ) ) {
		add_action(
			'admin_notices',
			function (): void {
				printf( '<div class="%1$s"><p>%2$s</p></div>', 'notice notice-error notice-billy', wp_kses_post( sprintf( __( '<strong>Warning!</strong> %1$s requires PHP %2$s (or higher) to function properly. Please upgrade your PHP version.', 'billy' ), 'Billy', esc_html( BILLY_REQUIRED_PHP ) ) ) );

				$activate = filter_input( INPUT_GET, 'activate', FILTER_VALIDATE_BOOLEAN );

				if ( true === $activate ) {
					unset( $_GET['activate'] );
				}
			}
		);

		// add_action( 'admin_init', 'billy_deactivate' );

		return;
	}

	if ( version_compare( wp_get_wp_version(), BILLY_REQUIRED_WP, '<=' ) ) {
		add_action(
			'admin_notices',
			function (): void {
				printf( '<div class="%1$s"><p>%2$s</p></div>', 'notice notice-error notice-billy', wp_kses_post( sprintf( __( '<strong>Warning!</strong> You are currently using an outdated WordPress version which is not compatible with %s. Please update WordPress to the latest version.', 'billy' ), 'Billy' ) ) );

				$activate = filter_input( INPUT_GET, 'activate', FILTER_VALIDATE_BOOLEAN );

				if ( true === $activate ) {
					unset( $_GET['activate'] );
				}
			}
		);

		// add_action( 'admin_init', 'billy_deactivate' );

		return;
	}

	if ( isset( $_REQUEST['post_type'] ) && str_starts_with( (string) wp_unslash( $_REQUEST['post_type'] ), 'billy-' ) && ! wp_is_writable( __DIR__ . '/mpdf/tmp' ) ) {
		add_action(
			'admin_notices',
			function (): void {
				printf( '<div class="%1$s"><p>%2$s</p></div>', 'notice notice-error notice-billy', wp_kses_post( sprintf( __( 'The temp directory %s is not writable. Please change the read/write permissions.', 'billy' ), '/mpdf/tmp' ) ) );
			}
		);
	}

	// Initialize classes.
	include_once __DIR__ . '/inc/class-billy.php';

	if ( ! class_exists( 'Billy' ) ) {
		return;
	}

	new Billy();

	// Define an array of classes to initialize.
	$classes = array(
		'Billy_Admin'      => 'class-admin.php',
		'Billy_Blocks'     => 'class-blocks.php',
		'Billy_PDF_Export' => 'class-pdfexport.php',
	);

	// Loop through the classes to include and instantiate.
	foreach ( $classes as $class => $file ) {
		include_once __DIR__ . '/inc/' . $file;

		if ( class_exists( $class ) ) {
			new $class();
		} else {
			error_log( "Class $class could not be initialized." );
		}
	}
}
add_action( 'plugins_loaded', 'billy_plugins_loaded', 998 );

/**
 * Yoast Duplicate Post: Enable the plugin for the WooCommerce "product" post type, which is unavailable by default.
 *
 * @param array $enabled_post_types The array of post type names for which the plugin is enabled.
 *
 * @return array The filtered array of post types names.
 */
function billy_custom_enabled_post_types( $enabled_post_types ): array {
	$enabled_post_types[] = 'billy-invoice';
	$enabled_post_types[] = 'billy-quote';

	return $enabled_post_types;
}
add_filter( 'duplicate_post_enabled_post_types', 'billy_custom_enabled_post_types' );

/**
 * Yoast Duplicate Post: Filters out custom fields from being duplicated in addition to the defaults.
 *
 * @param array $meta_excludelist The default exclusion list, based on the “Do not copy these fields” setting, plus some other field names.
 *
 * @return array The custom fields to exclude.
 */
function billy_custom_fields_filter( $meta_excludelist ): array {
	return array_merge( $meta_excludelist, array( '_invoice_number', '_quote_number' ) );
}
add_filter( 'duplicate_post_excludelist_filter', 'billy_custom_fields_filter' );

/**
 * Yoast Duplicate Post: Performs some actions after the WordPress standard fields of a post, or a non-hierarchical custom type item, have been copied.
 *
 * @param int     $new_post_id The newly created post's ID.
 * @param WP_Post $post        The original post's object.
 * @param string  $status      The destination status as set by the calling method: e.g. ‘draft’ if the function has been called using the “New Draft” links. Empty otherwise.
 *
 * @return void
 */
function billy_custom_dp_duplicate_post( $new_post_id, $post, $status ): void {
	$contact_uuid = get_post_meta( $post->ID, '_contact_uuid', true );

	if ( $contact_uuid ) {
		update_post_meta( $new_post_id, '_contact_uuid', $contact_uuid );
	}
}
add_action( 'dp_duplicate_post', 'billy_custom_dp_duplicate_post', 10, 3 );
