<?php
/**
 * Main plugin class.
 *
 * @package StoreSheet
 */

defined( 'ABSPATH' ) || exit;

use Automattic\WooCommerce\Utilities\FeaturesUtil;
use StoreSheet\API\GoogleOAuthClient;
use StoreSheet\API\GoogleSheetsClient;
use StoreSheet\Hooks\CouponHooks;
use StoreSheet\Hooks\OrderHooks;
use StoreSheet\Hooks\ProductHooks;
use StoreSheet\Migration\Installer;
use StoreSheet\Notifications\DigestNotifier;
use StoreSheet\Notifications\FailureNotifier;
use StoreSheet\Queue\SyncQueue;
use StoreSheet\Rest\ImportController;
use StoreSheet\Rest\OAuthController;
use StoreSheet\Rest\OverviewController;
use StoreSheet\Rest\SettingsController;
use StoreSheet\Settings\Assets;
use StoreSheet\Settings\Menu;
use StoreSheet\Settings\PluginLinks;

/**
 * Main singleton. Boots all plugin components.
 */
final class StoreSheet {

	private static ?StoreSheet $instance = null;

	private ?GoogleOAuthClient $oauth_client = null;

	private function __construct() {}

	public static function get_instance(): self {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	public function init(): void {
		register_activation_hook( STORESHEET_FILE, array( $this, 'activate' ) );
		register_deactivation_hook( STORESHEET_FILE, array( $this, 'deactivate' ) );

		add_action( 'before_woocommerce_init', array( $this, 'declare_compatibility' ) );
		add_action( 'admin_notices', array( $this, 'dependency_notice' ) );
		add_action( 'woocommerce_loaded', array( $this, 'boot_components' ) );
	}

	public function boot_components(): void {
		add_action( 'rest_api_init', array( $this, 'register_rest_routes' ) );

		$queue = new SyncQueue();
		$queue->init();

		( new ProductHooks( $queue ) )->init();
		( new OrderHooks( $queue ) )->init();
		( new CouponHooks( $queue ) )->init();

		if ( is_admin() ) {
			( new Menu() )->init();
			( new Assets() )->init();
			( new PluginLinks() )->init();
		}

		( new FailureNotifier() )->init();
		( new DigestNotifier() )->init();

		do_action( 'storesheet_loaded' );
	}

	public function register_rest_routes(): void {
		( new OAuthController( $this->oauth_client() ) )->register_routes();
		( new SettingsController() )->register_routes();
		( new OverviewController() )->register_routes();
		( new ImportController() )->register_routes();
	}

	public function declare_compatibility(): void {
		if ( ! class_exists( FeaturesUtil::class ) ) {
			return;
		}

		foreach ( array( 'custom_order_tables', 'cart_checkout_blocks' ) as $feature ) {
			FeaturesUtil::declare_compatibility( $feature, STORESHEET_FILE, true );
		}
	}

	public function dependency_notice(): void {
		if ( class_exists( 'WooCommerce' ) ) {
			return;
		}

		printf(
			'<div class="notice notice-error"><p>%s</p></div>',
			esc_html__( 'StoreSheet requires WooCommerce to be installed and active.', 'storesheet' )
		);
	}

	/**
	 * Whether Pro features are unlocked.
	 *
	 * Freemius premium-version model: this build knows the license directly, so
	 * `can_use_premium_code()` (valid paid or trial license) is authoritative.
	 * Falls back to the `storesheet_is_pro` filter when the SDK is absent — e.g.
	 * before `composer freemius:download`, or for third-party overrides.
	 *
	 * @since 1.0.0
	 * @return bool
	 */
	public function is_pro(): bool {
		$fs = function_exists( 'storesheet_fs' ) ? storesheet_fs() : null;
		if ( $fs instanceof \Freemius ) {
			// Both conditions are required: the premium build must be ACTIVE
			// (its code is what delivers Pro features and injects the Pro UI)
			// AND the license must be valid. A valid license with the Pro
			// plugin missing loads none of the premium code, so treating it as
			// Pro would hide the upsell and leave the user with dead toggles.
			// is_license_active() reports that gap state so the UI can prompt an
			// install instead of an upgrade.
			return self::is_premium_active() && $fs->can_use_premium_code();
		}

		return (bool) apply_filters( 'storesheet_is_pro', false );
	}

	/**
	 * Whether the user holds a valid Pro license, regardless of whether the
	 * premium build is installed. Drives the "install StoreSheet Pro" prompt in
	 * the gap state where a license is active but the Pro plugin is absent.
	 *
	 * @since 1.0.0
	 * @return bool
	 */
	public function is_license_active(): bool {
		$fs = function_exists( 'storesheet_fs' ) ? storesheet_fs() : null;
		if ( $fs instanceof \Freemius ) {
			return $fs->can_use_premium_code();
		}

		return (bool) apply_filters( 'storesheet_is_pro', false );
	}

	/**
	 * Whether the StoreSheet Pro (premium) build is installed and active. The
	 * Pro plugin defines the global storesheet_pro() on load, so its presence
	 * is the reliable cross-plugin signal that the premium code is available in
	 * this request.
	 *
	 * @since 1.0.0
	 * @return bool
	 */
	public static function is_premium_active(): bool {
		return function_exists( 'storesheet_pro' );
	}

	/**
	 * Lazily-instantiated shared OAuth client.
	 *
	 * @since 1.0.0
	 * @return GoogleOAuthClient
	 */
	public function oauth_client(): GoogleOAuthClient {
		if ( null === $this->oauth_client ) {
			$this->oauth_client = new GoogleOAuthClient();
		}
		return $this->oauth_client;
	}

	/**
	 * Sheets API client bound to the shared OAuth client.
	 *
	 * @since 1.0.0
	 * @return GoogleSheetsClient
	 */
	public function sheets_client(): GoogleSheetsClient {
		return new GoogleSheetsClient( $this->oauth_client() );
	}

	/**
	 * @param string $message Log message.
	 * @param string $level   error|warning|info|debug.
	 */
	public function log( string $message, string $level = 'info' ): void {
		if ( ! function_exists( 'wc_get_logger' ) ) {
			return;
		}

		$settings = get_option( 'storesheet_settings', array() );
		if ( empty( $settings['enable_logging'] ) ) {
			return;
		}

		wc_get_logger()->log( $level, $message, array( 'source' => 'storesheet' ) );
	}

	public function activate(): void {
		( new Installer() )->run();
		SyncQueue::schedule();
		if ( ! empty( get_option( 'storesheet_settings', array() )['enable_daily_digest'] ) ) {
			SyncQueue::schedule_digest();
		}
		do_action( 'storesheet_activated' );
	}

	public function deactivate(): void {
		wp_clear_scheduled_hook( 'storesheet_scheduled_sync' );
		SyncQueue::unschedule_digest();
		do_action( 'storesheet_deactivated' );
	}
}
