<?php
/**
 * Plugin Name: CommerceBird
 * Plugin URI:  https://commercebird.com
 * Author:      CommerceBird
 * Description: This plugin helps you get the most of CommerceBird AI App and use integrations like Zoho Inventory, Zoho CRM, Exact Online and more. Requires a subscription at CommerceBird.com.
 * Version: 3.0.3
 * Requires PHP: 8.2
 * Requires Plugins: woocommerce
 * Requires at least: 7.0
 * Tested up to: 7.0
 * Text Domain: commercebird
 * Domain Path: /languages
 *
 * License: GNU General Public License v3.0
 * License URI: http://www.gnu.org/licenses/gpl-3.0.html
 *
 * @category  Fulfillment
 * @package   CommerceBird
 * @author    Fawad Tiemoerie <info@commercebird.com>
 * @copyright Copyright (c) 2026, CommerceBird
 * @license   https://www.gnu.org/licenses/gpl-3.0.html GPL-3.0-or-later
 *
 * WC requires at least: 10.7.0
 * WC tested up to: 10.9.1
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

if ( ! defined( 'CMBIRD_VERSION' ) ) {
	define( 'CMBIRD_VERSION', '3.0.3' );
}
if ( ! defined( 'CMBIRD_ZI_CATEGORY_MAP_LEGACY_FALLBACK' ) ) {
	define( 'CMBIRD_ZI_CATEGORY_MAP_LEGACY_FALLBACK', true );
}
if ( ! defined( 'CMBIRD_PATH' ) ) {
	define( 'CMBIRD_PATH', plugin_dir_path( __FILE__ ) );
}
if ( ! defined( 'CMBIRD_URL' ) ) {
	define( 'CMBIRD_URL', plugin_dir_url( __FILE__ ) );
}
if ( ! defined( 'CMBIRD_MENU_SLUG' ) ) {
	define( 'CMBIRD_MENU_SLUG', 'commercebird-app' );
}

require_once CMBIRD_PATH . 'includes/woo-functions.php';
require_once CMBIRD_PATH . 'includes/sync/order-backend.php';

// Load the Jetpack autoloader instead of vendor/autoload.php.
require_once plugin_dir_path( __FILE__ ) . 'vendor/autoload_packages.php';

use Automattic\WooCommerce\Utilities\FeaturesUtil;
use WP\MCP\Core\McpAdapter;
use CommerceBird\Admin\Actions\Sync\ExactOnlineSync;
use CommerceBird\Admin\Actions\Ajax\ExactOnlineAjax;
use CommerceBird\Admin\Actions\Sync\ZohoCRMSync;
use CommerceBird\API\CMBird_APIs;
use CommerceBird\API\CreateOrderWebhook;
use CommerceBird\API\Exact;
use CommerceBird\API\ProductWebhook;
use CommerceBird\API\ShippingWebhook;
use CommerceBird\API\Zoho;
use CommerceBird\CMBIRD_MCP;
use CommerceBird\Plugin;

/*
|--------------------------------------------------------------------------
| Activation, deactivation and uninstall event.
|--------------------------------------------------------------------------
*/

register_activation_hook( __FILE__, array( Plugin::class, 'activate' ) );
register_deactivation_hook( __FILE__, array( Plugin::class, 'deactivate' ) );
register_uninstall_hook( __FILE__, array( Plugin::class, 'uninstall' ) );

/*
|--------------------------------------------------------------------------
| Load the plugin translations
|--------------------------------------------------------------------------
| Note: WordPress.org automatically loads translations for plugins since WP 4.6.
| Manual loading not required for plugins hosted on WordPress.org.
*/

/** Loading Purchase Order Class
 *
 * @since 1.0.0
 */
function cmbird_purchase_order_class() {
	if ( class_exists( 'WooCommerce' ) ) {
		new CMBIRD_Purchase_Order();
	}
}
add_action( 'woocommerce_init', 'cmbird_purchase_order_class' );
add_action( 'init', array( CMBIRD_PO_Admin_Manager::class, 'init' ), 11 );

/*
|--------------------------------------------------------------------------
| Start the plugin
|--------------------------------------------------------------------------
*/
Plugin::init();

/**
 * Declaring compatibility for WooCommerce HPOS
 */
add_action(
	'before_woocommerce_init',
	function () {
		if ( class_exists( FeaturesUtil::class ) ) {
			FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, true );
			FeaturesUtil::declare_compatibility( 'product_instance_caching', __FILE__, true );
		}
	}
);

/*
--------------------------------------------------------------------------
| Install required dependencies
|--------------------------------------------------------------------------
*/
add_action(
	'plugins_loaded',
	static function () {
		// Initialize Quotes module.
		CMBIRD_Quotes::init();
		// Initialize MCP abilities.
		CMBIRD_MCP::init();
		// Only if plan is active via transient subscription_details.
		$subscription = get_transient( 'subscription_details' );
		// return if no subscription found.
		if ( empty( $subscription ) ) {
			return;
		} else {
			WP_Dependency_Installer::instance( __DIR__ )->run();
		}
	}
);

/**
 * Hooks for WC Action Scheduler to import or export products
 */
$cmbird_import_products  = new CMBIRD_Products_ZI();
$cmbird_import_pricelist = new CMBIRD_Pricelist_ZI();
$cmbird_product_class    = new CMBIRD_Products_ZI_Export();
$cmbird_common_class     = new CMBIRD_Common_Functions();
$cmbird_contact_class    = new CMBIRD_Contact_ZI();
$cmbird_category_class   = new CMBIRD_Categories_ZI();
$cmbird_import_pricelist->wc_b2b_groups();
add_action( 'import_group_items_cron', array( $cmbird_import_products, 'sync_groupitem_recursively' ), 10, 2 );
add_action( 'import_simple_items_cron', array( $cmbird_import_products, 'sync_items_batch' ), 10, 2 );
add_action( 'import_variable_product_cron', array( $cmbird_import_products, 'import_variable_product_variations' ), 10, 2 );
add_action( 'sync_zi_product_cron', array( $cmbird_product_class, 'cmbird_zi_products_prepare_sync' ), 10, 2 );
add_action( 'sync_zi_pricelist', array( $cmbird_import_pricelist, 'zi_get_pricelist' ), 10, 2 );
add_action( 'cmbird_pricelist_addify_page', array( $cmbird_import_pricelist, 'process_addify_page' ), 10, 3 );
add_action( 'cmbird_pricelist_wc_b2b_page', array( $cmbird_import_pricelist, 'process_wc_b2b_page' ), 10, 3 );
add_action( 'sync_zi_order', array( $cmbird_common_class, 'cmbird_orders_prepare_sync' ), 10, 2 );
add_action( 'sync_zi_import_contacts', array( $cmbird_contact_class, 'cmbird_get_zoho_contacts' ), 10, 2 );
// Cascade Zoho category mapping deletion when a WC product category is deleted.
add_action(
	'delete_term',
	static function ( $term_id, $tt_id, $taxonomy ) {
		if ( 'product_cat' !== $taxonomy ) {
			return;
		}
		( new \CommerceBird\Admin\Mappings\ZohoCategoryMap() )->forget_term( (int) $term_id );
	},
	10,
	3
);
// add action to set the zoho rate limit option exceeded to false.
add_action( 'cmbird_common', array( CMBIRD_Common_Functions::class, 'set_zoho_rate_limit_option' ) );
// Zoho CRM Hooks.
add_action( 'sync_zcrm_order', array( $cmbird_common_class, 'cmbird_orders_prepare_sync' ) );
add_action( 'sync_zcrm_contact', array( ZohoCRMSync::class, 'cmbird_zcrm_contact_sync' ) );
// Exact Online Hooks.
$exact_online_sync = new ExactOnlineSync();
add_action( 'cmbird_sync_eo', array( $exact_online_sync, 'sync' ), 10, 3 );
add_action( 'cmbird_exact_online_sync_orders', array( ExactOnlineSync::class, 'sync_orders_via_cron' ) );
add_action( 'cmbird_payment_status', array( ExactOnlineSync::class, 'cmbird_payment_status' ), 10, 1 );
add_action( 'cmbird_eo_get_payment_statuses', array( ExactOnlineSync::class, 'get_payment_status_via_cron' ) );
add_filter( 'cron_schedules', array( ExactOnlineAjax::instance(), 'register_product_cron_schedules' ) );
add_action( 'cmbird_eo_product_mapping_daily', array( ExactOnlineAjax::instance(), 'product_map_cron' ) );
add_action( 'cmbird_eo_product_daily_reset', array( ExactOnlineAjax::instance(), 'product_map_daily_reset' ) );
// Callback functions for scheduled action to process product or customer chunk.
add_action(
	'cmbird_process_product_chunk',
	function ( $args ) {
		if ( ! is_array( $args ) || empty( $args['transient_key'] ) ) {
			return;
		}
		$transient_key    = $args['transient_key'];
		$import_products  = $args['import_products'] ?? false;
		$chunked_products = get_transient( $transient_key );
		if ( $chunked_products ) {
			$sync = new ExactOnlineSync();
			$sync->sync( 'product', $chunked_products, (bool) $import_products );
			// Remove transient after processing.
			delete_transient( $transient_key );
		}
	},
	10,
	1
);
add_action(
	'cmbird_process_customer_chunk',
	function ( $args ) {
		if ( ! is_array( $args ) || empty( $args['transient_key'] ) ) {
			return;
		}
		$transient_key     = $args['transient_key'];
		$import_customers  = $args['import_customers'] ?? false;
		$chunked_customers = get_transient( $transient_key );
		if ( $chunked_customers ) {
			$sync = new ExactOnlineSync();
			$sync->sync( 'customer', $chunked_customers, (bool) $import_customers );
			// Remove transient after processing.
			delete_transient( $transient_key );
		}
	},
	10,
	1
);
// Zoho CRM Hooks.
add_action( 'init', array( ZohoCRMSync::class, 'refresh_token' ) );
// Zoho Inventory Cron Hook for importing items.
add_action( 'zi_execute_import_sync', array( Plugin::class, 'dispatch_import_simple_items' ) );

// add classes to REST API.
add_action(
	'rest_api_init',
	function () {
		new Zoho();
		new Exact();
		new ProductWebhook();
		new ShippingWebhook();
		new CreateOrderWebhook();
		new CMBird_APIs();
		$po_controller = new CMBIRD_REST_Shop_Purchase_Controller();
		$po_controller->register_routes();
	}
);

add_action(
	'save_post',
	function ( $post_id, $post ) {
		if ( 'wcb2b_group' === $post->post_type ) {
			delete_option( 'cmbird_wcb2b_groups' );
		}
	},
	10,
	2
);

/**
 * Perform actions when the plugin is updated
 *
 * @param string $upgrader_object
 * @param array $options
 * @return void
 */
add_action( 'upgrader_process_complete', 'cmbird_update_plugin_tasks', 10, 2 );

/**
 * Perform tasks when the plugin is updated.
 *
 * @param \WP_Upgrader $upgrader_object - Upgrader object.
 * @param array        $options - Options array.
 *
 * @see https://developer.wordpress.org/reference/hooks/upgrader_process_complete/
 */
function cmbird_update_plugin_tasks( $upgrader_object, $options ) {
	$this_plugin = plugin_basename( __FILE__ );

	if ( ! is_array( $options ) ) {
		return;
	}

	if ( ! isset( $options['action'], $options['type'], $options['plugins'] ) || ! is_array( $options['plugins'] ) ) {
		return;
	}

	if ( 'update' === $options['action'] && 'plugin' === $options['type'] ) {
		foreach ( $options['plugins'] as $plugin ) {
			if ( $plugin === $this_plugin ) {
				// Ensure category mapping table exists before any table-backed migrations run.
				Plugin::ensure_zi_category_map_table();

				// Perform tasks when the plugin is updated.
				// Updating meta key from '_cost_price' to '_cogs_total_value'.
				global $wpdb;
				$wpdb->query(
					$wpdb->prepare(
						"UPDATE {$wpdb->postmeta} SET meta_key = %s WHERE meta_key = %s",
						'_cogs_total_value',
						'_cost_price'
					)
				);
				// Enable MCP WooCommerce integration. Remove this when enabled in Woo core.
				update_option( 'woocommerce_feature_mcp_integration_enabled', 'yes' );
				update_option( 'woocommerce_feature_cost_of_goods_sold_enabled', 'yes' );
				update_option( 'woocommerce_feature_fulfillments_enabled', 'no' );
				// One-time cleanup for old per-minute Zoho API rate limit counters.
				$wpdb->query(
					$wpdb->prepare(
						"DELETE FROM {$wpdb->options} WHERE option_name LIKE %s",
						$wpdb->esc_like( 'cmbird_zoho_api_calls_' ) . '%'
					)
				);
				break;
			}
		}
	}

	// One-shot migration of legacy category mapping options into the new table.
	if ( ! get_option( 'cmbird_zi_category_map_migrated' ) ) {
		$report = \CommerceBird\Admin\Mappings\ZohoCategoryMap::migrate_legacy_options();

		if ( ! empty( $report['skipped'] ) ) {
			set_transient( 'cmbird_zi_category_map_migration_report', $report['skipped'], DAY_IN_SECONDS );
		}

		update_option( 'cmbird_zi_category_map_migrated', '1', false );
	}
}

/**
 * Instantiate the MCP adapter. Remove this when its included in Woo core.
 */
// 1. Check if MCP Adapter is available
if ( ! class_exists( McpAdapter::class ) ) {
	// Handle missing dependency (show admin notice, etc.).
	return;
}
// 2. Initialize the adapter
McpAdapter::instance();
