<?php
/**
 * The core plugin class.
 */

namespace RawTypeOE\Free;

use RawTypeOE\Free\Admin\Admin;
use RawTypeOE\Free\Admin\Rest_API;

// Prevent direct access.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Main plugin class that orchestrates all hooks and functionality.
 */
class Plugin {

	/** @var Admin */
	protected $admin;

	/** @var Rest_API */
	protected $rest_api;

	/** @var Column_Registry */
	protected $column_registry;

	/** @var Export_Engine */
	protected $export_engine;

	/** @var Custom_Field_Scanner */
	protected $custom_field_scanner;

	public function __construct() {
		$this->load_dependencies();
	}

	/** @var File_Manager */
	protected $file_manager;

	/** Load required dependencies. */
	private function load_dependencies() {
		require_once RAWTYPE_OE_PLUGIN_DIR . 'includes/trait-data-source.php';
		require_once RAWTYPE_OE_PLUGIN_DIR . 'includes/class-column-registry.php';
		require_once RAWTYPE_OE_PLUGIN_DIR . 'includes/class-query-builder.php';
		require_once RAWTYPE_OE_PLUGIN_DIR . 'includes/class-cross-entity-query.php';
		require_once RAWTYPE_OE_PLUGIN_DIR . 'includes/class-custom-field-scanner.php';
		require_once RAWTYPE_OE_PLUGIN_DIR . 'includes/class-data-source-orders.php';
		require_once RAWTYPE_OE_PLUGIN_DIR . 'includes/class-data-source-products.php';
		require_once RAWTYPE_OE_PLUGIN_DIR . 'includes/class-data-source-customers.php';
		require_once RAWTYPE_OE_PLUGIN_DIR . 'includes/class-file-manager.php';
		require_once RAWTYPE_OE_PLUGIN_DIR . 'includes/class-csv-exporter.php';
		require_once RAWTYPE_OE_PLUGIN_DIR . 'includes/class-xlsx-multisheet-exporter.php';
		require_once RAWTYPE_OE_PLUGIN_DIR . 'includes/class-export-engine.php';
		require_once RAWTYPE_OE_PLUGIN_DIR . 'includes/class-template-library.php';
		require_once RAWTYPE_OE_PLUGIN_DIR . 'includes/class-export-profile.php';
		require_once RAWTYPE_OE_PLUGIN_DIR . 'admin/class-admin.php';
		require_once RAWTYPE_OE_PLUGIN_DIR . 'admin/class-rest-api.php';
	}

	/** Register all hooks and run the plugin. */
	public function run() {
		add_action( 'init', array( $this, 'register_post_types' ) );

		$this->column_registry      = new Column_Registry();
		$this->custom_field_scanner = new Custom_Field_Scanner();
		$this->file_manager         = new File_Manager();
		$this->file_manager->register_hooks();

		$this->register_cache_invalidation_hooks();

		add_filter( 'rawtype_oe_columns_orders', array( $this, 'extend_columns_with_custom_fields' ), 10, 2 );
		add_filter( 'rawtype_oe_columns_products', array( $this, 'extend_columns_with_custom_fields' ), 10, 2 );
		add_filter( 'rawtype_oe_columns_customers', array( $this, 'extend_columns_with_custom_fields' ), 10, 2 );

			$this->export_engine = new Export_Engine( $this->column_registry, $this->file_manager );

			$export_profile = new Export_Profile();
			$export_profile->register_hooks();

			// Defer scheduling to init — Action Scheduler and WP Cron require init or later.
			add_action( 'init', array( $this, 'schedule_cleanup_tasks' ) );

		$this->rest_api = new Rest_API(
			$this->column_registry,
			$this->export_engine,
			$this->custom_field_scanner
		);
		$this->rest_api->register_hooks();

		if ( is_admin() ) {
			$this->admin = new Admin();
			$this->admin->register_hooks();
		}

		/**
		 * Fires after the plugin is fully loaded.
		 *
		 * @param Plugin $plugin The main plugin instance.
		 */
		do_action( 'rawtype_oe_loaded', $this );
	}

	/**
	 * Schedule cleanup cron/action tasks.
	 * Hooked to init because Action Scheduler and WP Cron are not ready during plugins_loaded.
	 */
	public function schedule_cleanup_tasks() {
		$this->file_manager->schedule_cleanup();
	}

	/**
	 * Wire transient invalidation so cached entity counts and taxonomy
	 * listings stay in sync with store changes. The plugin caches aggressively
	 * to keep big-store admin views responsive; invalidation runs on the
	 * relevant Woo/WP hooks.
	 *
	 * @return void
	 */
	private function register_cache_invalidation_hooks() {
		// Entity-count cache busting.
		$count_busters = array(
			'woocommerce_new_order',
			'woocommerce_update_order',
			'woocommerce_delete_order',
			'woocommerce_trash_order',
			'save_post_product',
			'delete_post',
			'user_register',
			'delete_user',
		);

		foreach ( $count_busters as $hook ) {
			add_action( $hook, array( 'RawTypeOE\\Free\\Query_Builder', 'flush_entity_counts_cache' ), 99 );
		}

		// Taxonomy listing cache busting (categories tree + tag list).
		$taxonomy_busters = array(
			'created_product_cat',
			'edited_product_cat',
			'delete_product_cat',
			'created_product_tag',
			'edited_product_tag',
			'delete_product_tag',
		);

		foreach ( $taxonomy_busters as $hook ) {
			add_action( $hook, array( 'RawTypeOE\\Free\\Query_Builder', 'flush_taxonomy_cache' ), 99 );
		}
	}

	/** Register internal custom post types. */
	public function register_post_types() {
		register_post_type(
			'rawtype_oe_profile',
			array(
				'labels'       => array(
					'name'          => __( 'Export Profiles', 'rawtype-order-exporter-woocommerce' ),
					'singular_name' => __( 'Export Profile', 'rawtype-order-exporter-woocommerce' ),
				),
				'public'       => false,
				'show_ui'      => false,
				'show_in_menu' => false,
				'supports'     => array( 'title', 'editor', 'custom-fields' ),
			)
		);
	}

	public static function is_pro() {
		return (bool) apply_filters( 'rawtype_oe_is_pro', false );
	}

	public function get_column_registry() {
		return $this->column_registry;
	}

	public function get_export_engine() {
		return $this->export_engine;
	}

	public function get_file_manager() {
		return $this->file_manager;
	}

	/**
	 * Append discovered custom fields to entity columns.
	 *
	 * @param array  $columns Existing columns.
	 * @param string $entity  Entity slug.
	 * @return array
	 */
	public function extend_columns_with_custom_fields( $columns, $entity ) {
		if ( ! is_array( $columns ) ) {
			$columns = array();
		}

		if ( ! $this->custom_field_scanner instanceof Custom_Field_Scanner ) {
			return $columns;
		}

		$custom_columns = $this->custom_field_scanner->get_columns_for_entity( $entity );
		if ( empty( $custom_columns ) ) {
			return $columns;
		}

		return array_merge( $columns, $custom_columns );
	}
}
