<?php
/**
 * Plugin Name: Freefactu - Toolkit para Verifactu
 * Plugin URI: https://aleixpellicer.com/freefactu/
 * Description: Herramientas técnicas para integrar los requisitos de facturación Verifactu de la AEAT española. Plugin de WordPress con licencia GPLv2 para desarrolladores.
 * Version: 1.0.0
 * Author: Aleix Pellicer
 * Author URI: https://github.com/aleixpellicer/
 * License: GPLv2 or later
 * Text Domain: freefactu
 * Requires at least: 5.8
 * Requires PHP: 8.2
 * Requires Plugins: woocommerce
 * WC requires at least: 6.0
 * WC tested up to: 9.4
 */

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

// Define plugin constants
define( 'FREEFACTU_VERSION', '1.0.0' );
define( 'FREEFACTU_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
define( 'FREEFACTU_PLUGIN_URL', plugin_dir_url( __FILE__ ) );

// Load Composer autoloader - scoped dependencies via PHP-Scoper live in vendor/
// This prevents conflicts with other WordPress plugins using the same libraries
if ( file_exists( FREEFACTU_PLUGIN_DIR . 'vendor/autoload.php' ) ) {
	require_once FREEFACTU_PLUGIN_DIR . 'vendor/autoload.php';
}

// Check DOMPDF availability (supports both scoped and non-scoped namespaces)
add_action( 'admin_init', function() {
	$dompdf_available = class_exists( 'Freefactu_Vendor\\Dompdf\\Dompdf' ) || class_exists( 'Dompdf\\Dompdf' );
	if ( ! $dompdf_available ) {
		add_action( 'admin_notices', function() {
			echo '<div class="notice notice-error"><p><strong>Freefactu:</strong> ';
			echo esc_html__( 'Error: La librería PDF no se ha cargado correctamente. Por favor, reinstala el plugin o contacta con soporte.', 'freefactu' );
			echo '</p></div>';
		} );
	}
} );

/**
 * Check if WooCommerce is active before loading the plugin.
 *
 * This plugin requires WooCommerce to function. If WooCommerce is not active,
 * display an admin notice and prevent the plugin from loading.
 *
 * @return bool True if WooCommerce is active, false otherwise.
 */
function freefactu_is_woocommerce_active() {
	// Check if WooCommerce is active using multiple methods for reliability
	if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'freefactu_active_plugins', get_option( 'active_plugins' ) ), true ) ) {
		return true;
	}

	// Check for multisite network-activated WooCommerce
	if ( is_multisite() ) {
		$plugins = get_site_option( 'active_sitewide_plugins' );
		if ( isset( $plugins['woocommerce/woocommerce.php'] ) ) {
			return true;
		}
	}

	return false;
}

// Check WooCommerce dependency before loading the plugin
if ( ! freefactu_is_woocommerce_active() ) {
	add_action( 'admin_notices', function() {
		echo '<div class="notice notice-error"><p><strong>Freefactu:</strong> ';
		echo esc_html__( 'Este plugin requiere WooCommerce para funcionar. Por favor, instala y activa WooCommerce primero.', 'freefactu' );
		echo '</p></div>';
	} );
	return; // Stop loading the plugin
}

// Declare HPOS (High-Performance Order Storage) compatibility
add_action( 'before_woocommerce_init', function() {
	if ( class_exists( \Automattic\WooCommerce\Utilities\FeaturesUtil::class ) ) {
		\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, true );
	}
} );

// Load Bootstrap class and initialize all dependencies
require_once FREEFACTU_PLUGIN_DIR . 'includes/core/class-freefactu-bootstrap.php';
require_once FREEFACTU_PLUGIN_DIR . 'includes/core/class-freefactu-checkout-fields.php';
Freefactu_Bootstrap::init();
Freefactu_Checkout_Fields::init();

/**
 * Main Freefactu Class
 *
 * @since 0.5.0
 */
class Freefactu {

	/**
	 * Instance of this class.
	 *
	 * @since 0.5.0
	 * @var Freefactu|null
	 */
	protected static $instance = null;

	/**
	 * Return an instance of this class (Singleton pattern).
	 *
	 * What this function does:
	 * - Returns the single instance of the Freefactu class
	 * - Creates the instance if it doesn't exist yet
	 * - Ensures only one instance exists throughout the plugin lifecycle
	 *
	 * Where it's called from:
	 * - freefactu.php: add_action( 'plugins_loaded', array( 'Freefactu', 'get_instance' ) )
	 *
	 * @since 0.5.0
	 * @return Freefactu A single instance of this class.
	 */
	public static function get_instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Verifactu client instance.
	 *
	 * @since 0.5.0
	 * @var Freefactu_Client
	 */
	public $client;

	/**
	 * Flag indicating if Verifactu invoice is being generated.
	 *
	 * @since 0.5.0
	 * @var bool
	 */
	public static $is_generating_verifactu = false;

	/**
	 * Initialize the plugin (Constructor - private for Singleton pattern).
	 *
	 * What this function does:
	 * - Initializes the logger system
	 * - Checks logger status and displays admin notices if needed
	 * - Initializes admin classes (Admin, Debug, History)
	 * - Registers standalone hooks for order list actions
	 * - Creates generator and environment instances using Factory pattern
	 * - Initializes the Verifactu client with dependency injection
	 * - Loads plugin text domain for translations
	 *
	 * Where it's called from:
	 * - freefactu.php: get_instance() method when creating the singleton instance
	 *
	 * @since 0.5.0
	 */
	private function __construct() {
		Freefactu_Logger::init();
		add_action( 'admin_notices', array( $this, 'check_logger_status' ) );
		add_action( 'admin_notices', array( $this, 'check_test_environment_notice' ) );

		// Initialize Admin
		if ( is_admin() ) {
			$admin = new Freefactu_Admin();
			new Freefactu_Debug();
			new Freefactu_History();

			// Register standalone hooks for order list actions
			new Freefactu_Standalone_Hooks( $admin );
		}

		// Create Generator and Environment using Factory
		$generator = Freefactu_Factory::create_generator();
		$environment = Freefactu_Factory::create_environment();
		$generator->register_output_hooks();

		// Initialize Client with dependency injection
		$this->client = new Freefactu_Client( $generator, $environment );
		add_action( 'plugins_loaded', array( $this, 'load_plugin_textdomain' ) );
	}

	/**
	 * Check logger status and display admin notice if there are issues.
	 *
	 * What this function does:
	 * - Checks if the log directory is writable
	 * - Displays an admin error notice if the directory cannot be written to
	 * - Shows the log directory path to help administrators fix permissions
	 *
	 * Where it's called from:
	 * - freefactu.php: add_action( 'admin_notices', array( $this, 'check_logger_status' ) ) in __construct()
	 *
	 * @return void
	 */
	public function check_logger_status() {
		if ( ! current_user_can( 'manage_options' ) || Freefactu_Logger::check_directory_writable() ) {
			return;
		}

		$log_dir = Freefactu_Logger::get_log_directory();
		echo '<div class="notice notice-error"><p><strong>Freefactu:</strong> ';
		printf(
			/* translators: %s: log directory path */
			esc_html__( 'El directorio de logs no se puede escribir: %s. Por favor, verifica los permisos del directorio.', 'freefactu' ),
			'<code>' . esc_html( $log_dir ) . '</code>'
		);
		echo '</p></div>';
	}

	/**
	 * Check if the plugin is in test mode and display a warning.
	 *
	 * @return void
	 */
	public function check_test_environment_notice() {
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}

		$options = get_option( 'freefactu_settings', array() );
		$env = isset( $options['environment'] ) ? $options['environment'] : 'test';

		if ( 'test' === $env ) {
			echo '<div class="notice notice-warning"><p><strong>Freefactu:</strong> ';
			echo esc_html__( '⚠️ VeriFactu está actualmente en Modo de Pruebas (Sandbox). Las facturas no se están enviando al entorno fiscal real de la AEAT.', 'freefactu' );
			echo '</p></div>';
		}
	}

	/**
	 * Load the plugin text domain for translation.
	 *
	 * What this function does:
	 * - Loads the plugin's translation files from the /languages directory
	 * - Enables multilingual support for the plugin
	 *
	 * Where it's called from:
	 * - freefactu.php: add_action( 'plugins_loaded', array( $this, 'load_plugin_textdomain' ) ) in __construct()
	 *
	 * @return void
	 */
	public function load_plugin_textdomain() {
		// phpcs:ignore PluginCheck.CodeAnalysis.DiscouragedFunctions.load_plugin_textdomainFound
		load_plugin_textdomain( 'freefactu', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' );
	}
}

// Initialize the plugin
add_action( 'plugins_loaded', array( 'Freefactu', 'get_instance' ) );

/**
 * Add plugin action links in the WordPress plugins list.
 *
 * What this function does:
 * - Adds a "Configuración" link to the plugin's settings page
 * - Appears before the "Deactivate" link in the plugins list
 *
 * @param array $links Existing plugin action links.
 * @return array Modified plugin action links.
 */
function freefactu_plugin_action_links( $links ) {
	$settings_link = '<a href="' . admin_url( 'admin.php?page=freefactu&tab=settings' ) . '">' . __( 'Configuración', 'freefactu' ) . '</a>';
	array_unshift( $links, $settings_link );
	return $links;
}
add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'freefactu_plugin_action_links' );

/**
 * Plugin activation hook - creates database tables and sets default options.
 *
 * What this function does:
 * - Loads required utility classes (Filesystem, Logger, DB, Series_Store)
 * - Initializes the logger system
 * - Creates the freefactu_invoices database table
 * - Creates the freefactu_series database table for invoice series management
 * - Sets default plugin options (environment: test, ssl_verify: true)
 * - Stores the plugin version in options
 * - Sets a transient to cache table existence check
 *
 * Where it's called from:
 * - freefactu.php: register_activation_hook( __FILE__, 'freefactu_activate' )
 * - WordPress: Called automatically when the plugin is activated
 *
 * @return void
 */
function freefactu_activate() {
	// Load required utility classes
	require_once FREEFACTU_PLUGIN_DIR . 'includes/utilities/class-freefactu-filesystem.php';
	require_once FREEFACTU_PLUGIN_DIR . 'includes/utilities/class-freefactu-logger.php';
	require_once FREEFACTU_PLUGIN_DIR . 'includes/utilities/class-freefactu-db.php';
	require_once FREEFACTU_PLUGIN_DIR . 'includes/utilities/class-freefactu-series-store.php';

	// Initialize logger and create database tables
	Freefactu_Logger::init();
	Freefactu_DB::create_table();
	Freefactu_DB::create_declarations_table();

	// Create series table for invoice numbering
	Freefactu_Series_Store::create_table();

	// Set default options
	if ( ! get_option( 'freefactu_settings' ) ) {
		update_option( 'freefactu_settings', array(
			'environment' => 'test',
			'ssl_verify'  => true,
		) );
	}

	update_option( 'freefactu_version', FREEFACTU_VERSION );
	set_transient( 'freefactu_table_exists', true, DAY_IN_SECONDS );

	// Add custom capability for VeriFactu management (compliance requirement §14.1)
	$admin_role = get_role( 'administrator' );
	if ( $admin_role ) {
		$admin_role->add_cap( 'manage_verifactu' );
	}
	$shop_manager = get_role( 'shop_manager' );
	if ( $shop_manager ) {
		$shop_manager->add_cap( 'manage_verifactu' );
	}

	// Enable WooCommerce orders "actions" column for all admin users
	freefactu_enable_wc_actions_column();
}
register_activation_hook( __FILE__, 'freefactu_activate' );

/**
 * Enable the WooCommerce orders "actions" column for all admin users.
 *
 * What this function does:
 * - Removes 'wc_actions' from the hidden columns list for the WooCommerce orders screen
 * - Supports both legacy (shop_order post type) and HPOS (woocommerce_page_wc-orders) storage modes
 * - Updates user meta for all administrators and shop managers
 *
 * Where it's called from:
 * - freefactu.php: freefactu_activate() function during plugin activation
 *
 * @return void
 */
function freefactu_enable_wc_actions_column() {
	// Meta keys for hidden columns in different WooCommerce storage modes
	$meta_keys = array(
		'manageedit-shop_ordercolumnshidden',          // Legacy CPT storage
		'managewoocommerce_page_wc-orderscolumnshidden', // HPOS storage
	);

	// Get all users with admin or shop_manager capabilities
	$users = get_users( array(
		'role__in' => array( 'administrator', 'shop_manager' ),
		'fields'   => 'ID',
	) );

	foreach ( $users as $user_id ) {
		foreach ( $meta_keys as $meta_key ) {
			$hidden_columns = get_user_meta( $user_id, $meta_key, true );

			// If no hidden columns are set, skip (column is visible by default)
			if ( ! is_array( $hidden_columns ) ) {
				continue;
			}

			// Remove 'wc_actions' from the hidden columns array
			$key = array_search( 'wc_actions', $hidden_columns, true );
			if ( false !== $key ) {
				unset( $hidden_columns[ $key ] );
				$hidden_columns = array_values( $hidden_columns ); // Re-index array
				update_user_meta( $user_id, $meta_key, $hidden_columns );
			}
		}
	}
}

/**
 * Plugin deactivation hook - clears scheduled events and transients.
 *
 * What this function does:
 * - Clears any scheduled WordPress cron events (freefactu_cleanup)
 * - Deletes the table existence transient cache
 * - Performs cleanup operations when plugin is deactivated
 *
 * Where it's called from:
 * - freefactu.php: register_deactivation_hook( __FILE__, 'freefactu_deactivate' )
 * - WordPress: Called automatically when the plugin is deactivated
 *
 * @return void
 */
function freefactu_deactivate() {
	wp_clear_scheduled_hook( 'freefactu_cleanup' );
	delete_transient( 'freefactu_table_exists' );
}
register_deactivation_hook( __FILE__, 'freefactu_deactivate' );
