<?php
/**
 * Plugin Name:       EmberPrice – Supplier Price List Import for WooCommerce
 * Plugin URI:        https://emberprice.com
 * Description:       Import supplier price lists (Excel or CSV) into WooCommerce with automatic product matching, margin rules, preview, and one-click rollback.
 * Version:           1.0.2
 * Requires at least: 6.4
 * Requires PHP:      8.2
 * Requires Plugins:  woocommerce
 * Author:            Tribu Inquebrantable
 * License:           GPL-2.0-or-later
 * License URI:       https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain:       emberprice
 *
 * WC requires at least: 8.0
 *
 * @package EmberPrice
 */

defined( 'ABSPATH' ) || exit;

define( 'EMBP_VERSION', '1.0.2' );
define( 'EMBP_PLUGIN_FILE', __FILE__ );
define( 'EMBP_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
define( 'EMBP_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
define( 'EMBP_DB_VERSION', 2 );

// Autoload (Composer). Las dependencias de terceros se cargan desde vendor-prefixed (Strauss).
if ( file_exists( EMBP_PLUGIN_DIR . 'vendor/autoload.php' ) ) {
	require_once EMBP_PLUGIN_DIR . 'vendor/autoload.php';
}
if ( file_exists( EMBP_PLUGIN_DIR . 'vendor-prefixed/autoload.php' ) ) {
	require_once EMBP_PLUGIN_DIR . 'vendor-prefixed/autoload.php';
}

if ( class_exists( 'EmberPrice\\Core\\Plugin' ) ) {
	register_activation_hook( __FILE__, array( 'EmberPrice\\Core\\Activator', 'activate' ) );
	register_deactivation_hook( __FILE__, array( 'EmberPrice\\Core\\Deactivator', 'deactivate' ) );
	add_action( 'admin_init', array( 'EmberPrice\\Core\\Activator', 'maybe_self_deactivate' ) );
	add_action( 'plugins_loaded', array( 'EmberPrice\\Core\\Plugin', 'instance' ) );

	// Hooked directly (not inside plugins_loaded): before_woocommerce_init can fire
	// before plugins_loaded depending on plugin load order.
	add_action( 'before_woocommerce_init', array( 'EmberPrice\\Core\\Plugin', 'declare_hpos_compatibility' ) );

	// Composition root for the Admin layer: Core can't import Admin (see the
	// dependency matrix in CLAUDE.md), so it's wired up here instead, once
	// Core\Plugin::boot() confirms requirements are met.
	if ( is_admin() ) {
		add_action( 'embp_loaded', 'embp_register_admin_page' );
		add_action( 'embp_loaded', 'embp_register_review_prompt' );
	}

	// REST routes aren't admin-only (requests don't load wp-admin), so this
	// isn't gated behind is_admin(). rest_api_init fires later than init, so
	// hooking it from within embp_loaded (itself on init) is safe timing-wise.
	add_action( 'embp_loaded', 'embp_register_rest_routes' );

	// The Action Scheduler hooks that run match/apply batches must be
	// registered on every request (not just admin/REST ones), since Action
	// Scheduler itself may invoke them from a cron/async request that never
	// touches wp-admin or the REST API.
	add_action( 'embp_loaded', 'embp_register_match_scheduler' );
	add_action( 'embp_loaded', 'embp_register_apply_scheduler' );
	add_action( 'embp_loaded', 'embp_register_rollback_scheduler' );
	add_action( 'embp_loaded', 'embp_register_llm_adjudication_scheduler' );
	add_action( 'embp_loaded', 'embp_register_snapshot_retention' );
	add_action( 'embp_loaded', 'embp_register_job_retention' );
	add_action( 'embp_loaded', 'embp_migrate_private_uploads' );

	// `wp embp:regression` (T-208): a dev-only quality gate against
	// tests/fixtures/, registered only under WP-CLI itself.
	if ( defined( 'WP_CLI' ) && WP_CLI ) {
		WP_CLI::add_command( 'embp:regression', array( new EmberPrice\Rest\RegressionCommand(), 'run' ) );
	}
}

/**
 * Registers the unified EmberPrice admin page.
 */
function embp_register_admin_page(): void {
	$settings      = new EmberPrice\Core\Settings( EmberPrice\Core\Crypto::for_site() );
	$settings_page = new EmberPrice\Admin\SettingsPage( $settings );
	( new EmberPrice\Admin\AdminPage( $settings_page ) )->register();
}

/**
 * Registers the post-3rd-successful-import wordpress.org review nudge.
 */
function embp_register_review_prompt(): void {
	( new EmberPrice\Admin\ReviewPrompt() )->register();
}

/**
 * Registers all `emberprice/v1` REST routes.
 */
function embp_register_rest_routes(): void {
	add_action( 'rest_api_init', array( new EmberPrice\Rest\JobsController(), 'register_routes' ) );
	add_action( 'rest_api_init', array( new EmberPrice\Rest\RowsController(), 'register_routes' ) );
	add_action( 'rest_api_init', array( new EmberPrice\Rest\SuppliersController(), 'register_routes' ) );
	add_action( 'rest_api_init', array( new EmberPrice\Rest\ProductsController(), 'register_routes' ) );

	// SettingsController is /settings/llm only -- excluded from the free
	// build along with the rest of the AI/LLM module (SPEC §9, L-7).
	if ( class_exists( 'EmberPrice\\Rest\\SettingsController' ) ) {
		add_action( 'rest_api_init', array( new EmberPrice\Rest\SettingsController(), 'register_routes' ) );
	}
}

/**
 * Wires the Action Scheduler hook that runs one match batch (see
 * Rest\JobMatchScheduler).
 */
function embp_register_match_scheduler(): void {
	( new EmberPrice\Rest\JobMatchScheduler() )->register_hook();
}

/**
 * Wires the Action Scheduler hook that runs one apply batch (see
 * Rest\JobApplyScheduler).
 */
function embp_register_apply_scheduler(): void {
	( new EmberPrice\Rest\JobApplyScheduler() )->register_hook();
}

/**
 * Wires the Action Scheduler hook that runs one rollback batch (see
 * Rest\JobRollbackScheduler).
 */
function embp_register_rollback_scheduler(): void {
	( new EmberPrice\Rest\JobRollbackScheduler() )->register_hook();
}

/**
 * Wires the Action Scheduler hook that runs one LLM adjudication batch (see
 * Rest\JobLlmAdjudicationScheduler) -- a no-op when the AI/LLM module isn't
 * part of this build (SPEC §9, L-7).
 */
function embp_register_llm_adjudication_scheduler(): void {
	if ( class_exists( 'EmberPrice\\Rest\\JobLlmAdjudicationScheduler' ) ) {
		( new EmberPrice\Rest\JobLlmAdjudicationScheduler() )->register_hook();
	}
}

/**
 * Wires the daily snapshot retention cleanup (see Core\SnapshotRetention)
 * and, the first time it runs on a given site, schedules its recurring
 * Action Scheduler action.
 */
function embp_register_snapshot_retention(): void {
	$retention = new EmberPrice\Core\SnapshotRetention();
	$retention->register_hook();
	$retention->schedule();
}

/**
 * Wires the daily cleanup for completed jobs, rows and encrypted uploads.
 */
function embp_register_job_retention(): void {
	( new EmberPrice\Ingestion\JobRetention() )->register();
}

/**
 * One-time upgrade cleanup: 1.0.0 stored source documents as plaintext
 * under uploads. The job log keeps filename/hash, so those files can be
 * removed safely before new encrypted `.embp` sources are written.
 */
function embp_migrate_private_uploads(): void {
	if ( get_option( 'embp_private_uploads_migrated', false ) ) {
		return;
	}

	( new EmberPrice\Ingestion\UploadStorage() )->purge_legacy_unencrypted();
	update_option( 'embp_private_uploads_migrated', true );
}
