<?php
/**
 * Main Plugin Class
 *
 * @package    WarrantyCart
 * @author     Al Amin Ahamed <me@alaminahamed.com>
 * @copyright  2025 Al Amin Ahamed
 * @license    GPL-2.0-or-later
 */

use Automattic\WooCommerce\Utilities\FeaturesUtil;

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

/**
 * Main plugin class for Warranty Cart
 */
class Warranty_Cart {

	/**
	 * Singleton instance
	 *
	 * @var self|null
	 */
	private static ?self $instance = null;

	/**
	 * Plugin version
	 *
	 * @var string
	 */
	public string $version = WARRANTY_CART_VERSION;

	/**
	 * Integration manager instance
	 *
	 * @var WarrantyCart\Integrations\IntegrationManager
	 */
	public WarrantyCart\Integrations\IntegrationManager $integrations;

	/**
	 * Reports instance
	 *
	 * @var WarrantyCart\Admin\Reports
	 */
	public WarrantyCart\Admin\Reports $reports;

	/**
	 * ProductImport instance
	 *
	 * @var WarrantyCart\Admin\Product\Import
	 */
	public WarrantyCart\Admin\Product\Import $product_import;

	/**
	 * Get singleton instance
	 *
	 * @return self
	 */
	public static function get_instance(): self {
		return self::$instance ??= new self();
	}

	/**
	 * Initialize the plugin
	 *
	 * @return void
	 */
	public function init(): void {
		\register_activation_hook( WARRANTY_CART_FILE, array( $this, 'activate' ) );
		\register_deactivation_hook( WARRANTY_CART_FILE, array( $this, 'deactivate' ) );

		\add_action( 'before_woocommerce_init', array( $this, 'declare_woocommerce_feature_compatibility' ) );
		\add_action( 'woocommerce_loaded', array( $this, 'init_components' ) );
		\add_action( 'init', array( $this, 'register_capabilities' ) );
		\add_action( 'admin_notices', array( $this, 'dependency_notice' ) );
	}

	/**
	 * Initialize plugin components
	 *
	 * @return void
	 */
	public function init_components(): void {
		if ( ! $this->check_dependencies() ) {
			return;
		}

		// Initialize settings components
		new WarrantyCart\Settings\PluginLinks();

		// Initialize notifications
		new WarrantyCart\Notifications\Manager();

		// Initialize REST API
		new WarrantyCart\REST\Manager();

		// Initialize frontend components
		new WarrantyCart\Frontend\Shortcode();
		new WarrantyCart\Frontend\Assets();
		new WarrantyCart\Frontend\CheckoutFields();

		// Initialize integration manager
		$this->integrations = new WarrantyCart\Integrations\IntegrationManager();

		// Initialize warranty handler
		new WarrantyCart\Core\WarrantyHandler();

		// Initialize warranty cron jobs
		new WarrantyCart\Core\WarrantyCron();

		// Initialize report instance (needed for abilities API)
		$this->reports = new WarrantyCart\Admin\Reports();

		// Initialize product import instance (needed for abilities API)
		$this->product_import = new WarrantyCart\Admin\Product\Import();

		// Initialize admin components
		if ( is_admin() ) {
			new WarrantyCart\Admin\Menu();
			new WarrantyCart\Admin\Product\Manager();
			new WarrantyCart\Admin\Assets();
		}

		// Register abilities for AI integration
		add_action( 'abilities_api_init', array( $this, 'register_abilities' ) );

		// Register emails with the WooCommerce block editor
		add_filter( 'woocommerce_transactional_emails_for_block_editor', array( $this, 'register_emails_for_block_editor' ) );
	}

	/**
	 * Check plugin dependencies
	 *
	 * @return bool
	 */
	private function check_dependencies(): bool {
		return $this->is_woocommerce_active();
	}

	/**
	 * Check if WooCommerce is active
	 *
	 * @return bool
	 */
	public function is_woocommerce_active(): bool {
		// Check if WooCommerce is active by looking for its main class
		return class_exists( 'WooCommerce' ) && defined( 'WC_VERSION' );
	}

	/**
	 * Show dependency notice
	 *
	 * @return void
	 */
	public function dependency_notice(): void {
		$missing = array();

		if ( ! $this->is_woocommerce_active() ) {
			$missing[] = 'WooCommerce';
		}

		if ( empty( $missing ) ) {
			return;
		}

		printf(
			'<div class="notice notice-error"><p>%s</p></div>',
			sprintf(
			/* translators: %s: List of missing plugin dependencies */
				esc_html__( 'Warranty Cart requires: %s', 'warranty-cart' ),
				esc_html( implode( ', ', $missing ) )
			)
		);
	}

	/**
	 * Declare WooCommerce HPOS compatibility
	 *
	 * @return void
	 */
	public function declare_woocommerce_feature_compatibility(): void {
		if ( ! class_exists( FeaturesUtil::class ) ) {
			return;
		}

		FeaturesUtil::declare_compatibility( 'cart_checkout_blocks', WARRANTY_CART_FILE, true );
		FeaturesUtil::declare_compatibility( 'custom_order_tables', WARRANTY_CART_FILE, true );
		FeaturesUtil::declare_compatibility( 'email_improvements', WARRANTY_CART_FILE, true );
		FeaturesUtil::declare_compatibility( 'block_email_editor', WARRANTY_CART_FILE, true );
		FeaturesUtil::declare_compatibility( 'blueprint', WARRANTY_CART_FILE, true );
		FeaturesUtil::declare_compatibility( 'fulfillments', WARRANTY_CART_FILE, true );
		FeaturesUtil::declare_compatibility( 'mcp_integration', WARRANTY_CART_FILE, true );
	}

	/**
	 * Plugin activation
	 *
	 * @return void
	 */
	public function activate(): void {
		// Create database tables
		WarrantyCart\Core\DatabaseInstaller::create_tables();

		// Set default options
		$this->set_default_options();

		// Register capabilities
		$this->register_capabilities();

		// Schedule cron jobs
		$this->schedule_cron_jobs();

		// Flush rewrite rules
		\flush_rewrite_rules();

		// Set activation flag
		\update_option( 'warranty_cart_activated', true );

		\do_action( 'warranty_cart_activated' );
	}

	/**
	 * Schedule cron jobs
	 *
	 * @return void
	 */
	private function schedule_cron_jobs(): void {
		if ( ! \wp_next_scheduled( 'warranty_cart_check_expirations' ) ) {
			\wp_schedule_event( time(), 'daily', 'warranty_cart_check_expirations' );
		}

		if ( ! \wp_next_scheduled( 'warranty_cart_send_reminders' ) ) {
			\wp_schedule_event( time(), 'daily', 'warranty_cart_send_reminders' );
		}
	}

	/**
	 * Plugin deactivation
	 *
	 * @return void
	 */
	public function deactivate(): void {
		// Clear cached data
		\delete_transient( 'warranty_cart_temp_data' );

		// Clear cron jobs
		$timestamp = \wp_next_scheduled( 'warranty_cart_check_expirations' );
		if ( $timestamp ) {
			\wp_unschedule_event( $timestamp, 'warranty_cart_check_expirations' );
		}

		$timestamp = \wp_next_scheduled( 'warranty_cart_send_reminders' );
		if ( $timestamp ) {
			\wp_unschedule_event( $timestamp, 'warranty_cart_send_reminders' );
		}

		// Flush rewrite rules
		\flush_rewrite_rules();

		\do_action( 'warranty_cart_deactivated' );
	}

	/**
	 * Register plugin capabilities
	 *
	 * @return void
	 */
	public function register_capabilities(): void {
		$roles = wp_roles();

		// Define capabilities
		$capabilities = array(
			'manage_warranty_cart'     => __( 'Manage Warranty Cart', 'warranty-cart' ),
			'view_warranty_reports'    => __( 'View Warranty Reports', 'warranty-cart' ),
			'import_warranty_products' => __( 'Import Warranty Products', 'warranty-cart' ),
			'manage_warranty_payments' => __( 'Manage Warranty Payments', 'warranty-cart' ),
		);

		// Add capabilities to administrator role
		$admin_role = $roles->get_role( 'administrator' );
		if ( $admin_role instanceof WP_Role ) {
			foreach ( $capabilities as $cap => $label ) {
				$admin_role->add_cap( $cap );
			}
		}
	}

	/**
	 * Register emails for WooCommerce block editor
	 *
	 * @param array<string> $emails Array of email IDs.
	 *
	 * @return array<string> Modified array of email IDs.
	 */
	public function register_emails_for_block_editor( array $emails ): array {
		$emails[] = 'warranty_order_completed';
		$emails[] = 'warranty_expired';
		$emails[] = 'warranty_reminder';

		return $emails;
	}

	/**
	 * Register abilities for AI integration
	 *
	 * @return void
	 */
	public function register_abilities(): void {
		if ( ! function_exists( 'wp_register_ability' ) ) {
			return;
		}

		// Register ability to generate sales reports
		wp_register_ability(
			'warranty-cart/generate-sales-report',
			array(
				'label'               => __( 'Generate Warranty Sales Report', 'warranty-cart' ),
				'description'         => __( 'Generates a sales report for warranty products.', 'warranty-cart' ),
				'execute_callback'    => array( $this, 'generate_sales_report_ability' ),
				'input_schema'        => array(
					'type'                  => 'object',
					'properties'            => array(
						'period' => array(
							'type'        => 'string',
							'description' => __( 'Report period (e.g., "last_30_days", "this_month")', 'warranty-cart' ),
							'enum'        => array( 'last_7_days', 'last_30_days', 'this_month', 'last_month', 'this_year' ),
							'default'     => 'last_30_days',
						),
					),
					'additional_properties' => false,
				),
				'output_schema'       => array(
					'type'       => 'object',
					'properties' => array(
						'total_sales'   => array(
							'type'        => 'number',
							'description' => __( 'Total sales amount', 'warranty-cart' ),
						),
						'total_orders'  => array(
							'type'        => 'integer',
							'description' => __( 'Total number of orders', 'warranty-cart' ),
						),
						'average_order' => array(
							'type'        => 'number',
							'description' => __( 'Average order value', 'warranty-cart' ),
						),
						'period'        => array(
							'type'        => 'string',
							'description' => __( 'Report period', 'warranty-cart' ),
						),
						'top_products'  => array(
							'type'        => 'array',
							'description' => __( 'Top selling products', 'warranty-cart' ),
							'items'       => array(
								'type'       => 'object',
								'properties' => array(
									'name'    => array( 'type' => 'string' ),
									'sales'   => array( 'type' => 'integer' ),
									'revenue' => array( 'type' => 'number' ),
								),
							),
						),
						'monthly_data'  => array(
							'type'        => 'array',
							'description' => __( 'Monthly sales data', 'warranty-cart' ),
							'items'       => array(
								'type'       => 'object',
								'properties' => array(
									'month'  => array( 'type' => 'string' ),
									'sales'  => array( 'type' => 'number' ),
									'orders' => array( 'type' => 'integer' ),
								),
							),
						),
					),
					'required'   => array( 'total_sales', 'total_orders', 'average_order', 'period' ),
				),
				'permission_callback' => array( $this, 'view_warranty_reports' ),
			)
		);

		// Register ability to import warranty products
		wp_register_ability(
			'warranty-cart/import-products',
			array(
				'label'               => __( 'Import Warranty Products', 'warranty-cart' ),
				'description'         => __( 'Imports warranty products from a CSV file.', 'warranty-cart' ),
				'execute_callback'    => array( $this, 'import_products_ability' ),
				'input_schema'        => array(
					'type'                  => 'object',
					'properties'            => array(
						'csv_content' => array(
							'type'        => 'string',
							'description' => __( 'CSV content with product data', 'warranty-cart' ),
							'required'    => true,
						),
						'category'    => array(
							'type'        => 'string',
							'description' => __( 'Product category for imported items', 'warranty-cart' ),
							'default'     => 'warranties',
						),
					),
					'additional_properties' => false,
				),
				'output_schema'       => array(
					'type'       => 'object',
					'properties' => array(
						'imported_count' => array(
							'type'        => 'integer',
							'description' => __( 'Number of products imported', 'warranty-cart' ),
						),
						'errors'         => array(
							'type'        => 'array',
							'description' => __( 'Import errors', 'warranty-cart' ),
						),
					),
					'required'   => array( 'imported_count' ),
				),
				'permission_callback' => array( $this, 'import_warranty_products' ),
			)
		);
	}

	/**
	 * Generate sales report ability callback
	 *
	 * @param array{period?: string} $args Input arguments.
	 * @return array{total_sales: float|int, total_orders: int, average_order: float|int, period: string, top_products: array<array{name: string, sales: int, revenue: float|int}>, monthly_data: array<array{month: string, sales: float|int, orders: int}>} Report data.
	 */
	public function generate_sales_report_ability( array $args ): array {
		$period = $args['period'] ?? 'last_30_days';

		// Map period to days
		$period_map = array(
			'last_7_days'  => 7,
			'last_30_days' => 30,
			'this_month'   => 30, // Approximate
			'last_month'   => 30, // Approximate
			'this_year'    => 365,
		);

		$days = $period_map[ $period ] ?? 30;

		// Use comprehensive reports for detailed data
		$data = $this->reports->get_comprehensive_reports( $days );

		$report_data = array(
			'total_sales'   => $data['total_sales'],
			'total_orders'  => $data['total_orders'],
			'average_order' => $data['average_order_value'],
			'period'        => $period,
			'top_products'  => $data['top_products'],
			'monthly_data'  => $data['monthly_data'],
		);

		/**
		 * Filter the sales report data.
		 *
		 * @param array $report_data The report data array.
		 * @param string $period The report period.
		 * @param int $days Number of days for the report.
		 */
		return apply_filters( 'warranty_cart_sales_report_data', $report_data, $period, $days );
	}

	/**
	 * Import products ability callback
	 *
	 * @param array{csv_content?: string, category?: string} $args Input arguments.
	 * @return array{imported_count: int, errors: array<string>} Import result.
	 */
	public function import_products_ability( array $args ): array {
		$csv_content = $args['csv_content'] ?? '';
		$category    = $args['category'] ?? 'warranties';

		if ( empty( $csv_content ) ) {
			return array(
				'imported_count' => 0,
				'errors'         => array( __( 'CSV content is required', 'warranty-cart' ) ),
			);
		}

		// Save CSV content to temp file
		$temp_file = wp_tempnam();
		global $wp_filesystem;
		if ( ! function_exists( 'WP_Filesystem' ) ) {
			require_once ABSPATH . 'wp-admin/includes/file.php';
		}
		WP_Filesystem();
		$wp_filesystem->put_contents( $temp_file, $csv_content );

		// Use existing ProductImport instance
		$imported = $this->product_import->process_csv_import( $temp_file, $category );

		// Clean up temp file
		wp_delete_file( $temp_file );

		$import_result = array(
			'imported_count' => $imported,
			'errors'         => array(), // Could be enhanced to collect actual errors
		);

		/**
		 * Filter the product import result data.
		 *
		 * @param array $import_result The import result array.
		 * @param string $csv_content The CSV content that was imported.
		 * @param string $category The category for imported products.
		 */
		return apply_filters( 'warranty_cart_import_products_result', $import_result, $csv_content, $category );
	}

	/**
	 * Check permission for viewing warranty reports
	 *
	 * @return bool Whether the user has permission.
	 */
	public function view_warranty_reports(): bool {
		return true;
	}

	/**
	 * Check permission for importing warranty products
	 *
	 * @return bool Whether the user has permission.
	 */
	public function import_warranty_products(): bool {
		return true;
	}

	/**
	 * Set default plugin options
	 *
	 * @return void
	 */
	private function set_default_options(): void {
		if ( ! get_option( 'warranty_cart_settings' ) ) {
			$default_settings = array(
				'enable_shortcode'   => true,
				'enable_admin_tools' => true,
			);
			update_option( 'warranty_cart_settings', $default_settings );
		}
	}

	/**
	 * Get plugin settings
	 *
	 * @return array<string, mixed>
	 */
	public function get_settings(): array {
		$settings = get_option( 'warranty_cart_settings', array() );

		/**
		 * Filter the plugin settings.
		 *
		 * @param array $settings The plugin settings array.
		 */
		return apply_filters( 'warranty_cart_settings', $settings );
	}

	/**
	 * Get specific setting
	 *
	 * @param string $key           Setting key.
	 * @param mixed  $default_value Default value.
	 *
	 * @return mixed
	 */
	public function get_setting( string $key, $default_value = '' ) {
		$settings = $this->get_settings();
		$value    = $settings[ $key ] ?? $default_value;

		/**
		 * Filter the specific plugin setting value.
		 *
		 * @param mixed  $value The setting value.
		 * @param string $key   The setting key.
		 * @param mixed  $default_value The default value.
		 */
		return apply_filters( 'warranty_cart_setting', $value, $key, $default_value );
	}

	/**
	 * Log a message with the specified type
	 *
	 * @param string               $message The message to be logged.
	 * @param string               $type    The type of the log entry. Defaults to 'error'.
	 * @param array<string, mixed> $context The context of the message.
	 *
	 * @return void
	 */
	public function log( string $message, string $type = 'error', array $context = array() ): void {
		if ( ! function_exists( 'wc_get_logger' ) || empty( $message ) ) {
			return;
		}

		$logger = wc_get_logger();
		if ( ! $logger instanceof WC_Logger ) {
			return;
		}

		$context['source'] = 'Warranty_Cart';

		$logger->log( $type, $message, $context );
	}

	/**
	 * Initialize WordPress Filesystem
	 *
	 * @return WP_Filesystem_Base True if initialized successfully.
	 */
	public function wp_filesystem(): WP_Filesystem_Base {
		global $wp_filesystem;

		if ( ! function_exists( 'WP_Filesystem' ) ) {
			require_once ABSPATH . 'wp-admin/includes/file.php';
		}

		WP_Filesystem();

		return $wp_filesystem;
	}

	/**
	 * Read file contents using WP_Filesystem
	 *
	 * @param string $file_path Path to the file to read.
	 *
	 * @return string|false File contents or false on failure.
	 */
	public function read_file( string $file_path ) {
		return $this->wp_filesystem()->get_contents( $file_path );
	}

	/**
	 * Write contents to file using WP_Filesystem
	 *
	 * @param string $file_path Path to the file to write.
	 * @param string $contents  Contents to write.
	 *
	 * @return bool True on success, false on failure.
	 */
	public function write_file( string $file_path, string $contents ): bool {
		return $this->wp_filesystem()->put_contents( $file_path, $contents );
	}

	/**
	 * Check if file exists using WP_Filesystem
	 *
	 * @param string $file_path Path to the file to check.
	 *
	 * @return bool True if file exists, false otherwise.
	 */
	public function file_exists( string $file_path ): bool {
		return $this->wp_filesystem()->exists( $file_path );
	}

	/**
	 * Delete file using WP_Filesystem
	 *
	 * @param string $file_path Path to the file to delete.
	 *
	 * @return bool True on success, false on failure.
	 */
	public function delete_file( string $file_path ): bool {
		return $this->wp_filesystem()->delete( $file_path );
	}
}
