<?php

namespace DigitalApps\PaymentsForAdyen;

defined('ABSPATH') || exit;

use DigitalApps\PaymentsForAdyen\Admin\Admin;
use DigitalApps\PaymentsForAdyen\Logger;
use DigitalApps\PaymentsForAdyen\Api\Rest_Controller;
use DigitalApps\PaymentsForAdyen\Api\Webhook_Controller;

/**
 * Main plugin class for Digital Apps Payments for Adyen
 */
class Adyen_Plugin
{
	const DATABASE_VERSION = 2;
	const DATABASE_VERSION_OPTION = 'digitalapps_payments_for_adyen_database_version';
	/**
	 * Singleton instance
	 *
	 * @var Adyen_Plugin
	 */
	private static $instance;

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

	/**
	 * Constructor
	 */
	private function __construct()
	{
		$this->define_constants();
		$this->includes();
		$this->init_hooks();
		do_action('digitalapps_payments_for_adyen_loaded', $this);
	}

	/**
	 * Define plugin constants
	 */
	private function define_constants()
	{
		if (!defined('DIGITALAPPS_PAYMENTS_FOR_ADYEN_PLUGIN_FILE')) {
			define('DIGITALAPPS_PAYMENTS_FOR_ADYEN_PLUGIN_FILE', DIGITALAPPS_PAYMENTS_FOR_ADYEN_PATH . 'digital-apps-payments-for-adyen.php');
		}
	}

	/**
	 * Include required files
	 */
	private function includes()
	{
		require_once DIGITALAPPS_PAYMENTS_FOR_ADYEN_PATH . 'includes/class-settings-store.php';
		Settings_Store::register_hooks();
		Settings_Store::maybe_migrate();

		// Ensure logger is available early for debugging
		require_once DIGITALAPPS_PAYMENTS_FOR_ADYEN_PATH . 'includes/logger.php';

		// Load session manager for 3DS support
		require_once DIGITALAPPS_PAYMENTS_FOR_ADYEN_PATH . 'includes/class-adyen-session-manager.php';

		// Load Composer autoloader for Adyen PHP SDK
		$autoload_path = DIGITALAPPS_PAYMENTS_FOR_ADYEN_PATH . 'vendor/autoload.php';
		if (file_exists($autoload_path)) {
			require_once $autoload_path;
			$logger = new Logger();
		} else {
			$logger = new Logger();
			$logger->log('ERROR', ['message' => 'Composer autoloader not found', 'path' => $autoload_path]);
		}

		require_once DIGITALAPPS_PAYMENTS_FOR_ADYEN_PATH . 'includes/class-adyen-amount.php';
		require_once DIGITALAPPS_PAYMENTS_FOR_ADYEN_PATH . 'includes/class-adyen-endpoint-resolver.php';
		require_once DIGITALAPPS_PAYMENTS_FOR_ADYEN_PATH . 'includes/class-adyen-application-info.php';
		require_once DIGITALAPPS_PAYMENTS_FOR_ADYEN_PATH . 'includes/class-adyen-operation.php';
		require_once DIGITALAPPS_PAYMENTS_FOR_ADYEN_PATH . 'includes/class-adyen-result.php';
		require_once DIGITALAPPS_PAYMENTS_FOR_ADYEN_PATH . 'includes/class-adyen-action-page.php';
		require_once DIGITALAPPS_PAYMENTS_FOR_ADYEN_PATH . 'includes/class-adyen-webhook-inbox.php';
		require_once DIGITALAPPS_PAYMENTS_FOR_ADYEN_PATH . 'includes/class-adyen-client.php';
		require_once DIGITALAPPS_PAYMENTS_FOR_ADYEN_PATH . 'includes/class-adyen-payment-method-status.php';
		require_once DIGITALAPPS_PAYMENTS_FOR_ADYEN_PATH . 'includes/class-adyen-gateway-utils.php';
		require_once DIGITALAPPS_PAYMENTS_FOR_ADYEN_PATH . 'includes/class-adyen-card-gateway.php';
		// WooCommerce Blocks compatibility (if available)
		if (file_exists(DIGITALAPPS_PAYMENTS_FOR_ADYEN_PATH . 'includes/blocks/class-adyen-blocks-support.php')) {
			require_once DIGITALAPPS_PAYMENTS_FOR_ADYEN_PATH . 'includes/blocks/class-adyen-blocks-support.php';
		}
		// Note: class-adyen-card-blocks.php is deprecated
		// WooCommerce Blocks integration is now handled by the proper
		// AbstractPaymentMethodType class loaded via the blocks support
		require_once DIGITALAPPS_PAYMENTS_FOR_ADYEN_PATH . 'includes/class-adyen-admin-notices.php';
		require_once DIGITALAPPS_PAYMENTS_FOR_ADYEN_PATH . 'includes/api/class-rest-controller.php';
		require_once DIGITALAPPS_PAYMENTS_FOR_ADYEN_PATH . 'includes/api/class-adyen-details-controller.php';
		require_once DIGITALAPPS_PAYMENTS_FOR_ADYEN_PATH . 'includes/api/webhooks.php';
		require_once DIGITALAPPS_PAYMENTS_FOR_ADYEN_PATH . 'includes/class-admin.php';
		require_once DIGITALAPPS_PAYMENTS_FOR_ADYEN_PATH . 'includes/class-deactivation-feedback.php';
		self::maybe_upgrade_database();
	}

	/**
	 * Initialize hooks
	 */
	private function init_hooks()
	{
		add_filter('woocommerce_payment_gateways', [$this, 'register_gateway']);

		// Register custom cron schedules
		add_filter('cron_schedules', [__CLASS__, 'add_cron_schedules']);

		// Register REST API routes
		add_action('rest_api_init', function () {
			$controller = new Rest_Controller();
			$controller->register_routes();
			$detailsController = new \DigitalApps\PaymentsForAdyen\Api\Adyen_Details_Controller();
			$detailsController->register_routes();
		});

		// Register Webhook routes
		add_action('rest_api_init', function () {
			$controller = new Webhook_Controller();
			$controller->register_routes();
		});

		// Register 3DS session cleanup cron job
		add_action('digitalapps_payments_for_adyen_cleanup_3ds_sessions', [$this, 'cleanup_3ds_sessions']);
		add_action(Adyen_Webhook_Inbox::PROCESS_HOOK, [$this, 'process_webhook_inbox'], 10, 1);
		add_action('woocommerce_refund_created', [$this, 'link_refund_operation'], 10, 2);
		if (!wp_next_scheduled('digitalapps_payments_for_adyen_cleanup_3ds_sessions')) {
			wp_schedule_event(time(), 'fifteen_minutes', 'digitalapps_payments_for_adyen_cleanup_3ds_sessions');
		}

		// Initialize Admin
		new Admin();
		(new \DigitalApps\PaymentsForAdyen\Admin\Deactivation_Feedback())->register_hooks();
		(new Adyen_Action_Page())->register_hooks();

	}

	/**
	 * Register WooCommerce payment gateway
	 *
	 * @param array $gateways
	 * @return array
	 */
	public function register_gateway($gateways)
	{
		$gateways[] = 'DigitalApps\\PaymentsForAdyen\\Gateways\\Adyen_Card_Gateway';

		return apply_filters('digitalapps_payments_for_adyen_gateway_definitions', $gateways);
	}

	/**
	 * Plugin activation
	 */
	public static function activate()
	{
		require_once DIGITALAPPS_PAYMENTS_FOR_ADYEN_PATH . 'includes/class-settings-store.php';
		Settings_Store::register_hooks();
		Settings_Store::maybe_migrate();

		// Register custom cron schedule
		add_filter('cron_schedules', [__CLASS__, 'add_cron_schedules']);

		// Schedule 3DS session cleanup
		if (!wp_next_scheduled('digitalapps_payments_for_adyen_cleanup_3ds_sessions')) {
			wp_schedule_event(time(), 'fifteen_minutes', 'digitalapps_payments_for_adyen_cleanup_3ds_sessions');
		}

		// Create 3DS sessions database table
		self::create_3ds_sessions_table();
		require_once DIGITALAPPS_PAYMENTS_FOR_ADYEN_PATH . 'includes/class-adyen-webhook-inbox.php';
		Adyen_Webhook_Inbox::create_table();
		update_option(self::DATABASE_VERSION_OPTION, self::DATABASE_VERSION, false);
	}

	/**
	 * Create the database table for 3DS sessions
	 */
	private static function create_3ds_sessions_table()
	{
		global $wpdb;
		$table_name = $wpdb->prefix . 'digitalapps_payments_for_adyen_3ds_sessions';
		$charset_collate = $wpdb->get_charset_collate();

		$sql = "CREATE TABLE IF NOT EXISTS $table_name (
			id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
			session_key varchar(100) NOT NULL,
			order_id bigint(20) unsigned NOT NULL,
			user_id bigint(20) unsigned NOT NULL,
			payment_data text NOT NULL,
			action_data text NOT NULL,
			status varchar(20) NOT NULL DEFAULT 'pending',
			created_at datetime NOT NULL,
			expires_at datetime NOT NULL,
			PRIMARY KEY  (id),
			UNIQUE KEY session_key (session_key),
			KEY order_id (order_id),
			KEY expires_at (expires_at),
			KEY status (status)
		) $charset_collate;";

		require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
		dbDelta($sql);

	}

	/** Apply additive schema changes once per plugin database version. */
	private static function maybe_upgrade_database()
	{
		if ((int) get_option(self::DATABASE_VERSION_OPTION, 0) >= self::DATABASE_VERSION) {
			return;
		}
		self::create_3ds_sessions_table();
		Adyen_Webhook_Inbox::create_table();
		update_option(self::DATABASE_VERSION_OPTION, self::DATABASE_VERSION, false);
	}

	/**
	 * Plugin deactivation
	 */
	public static function deactivate()
	{
		// Clear scheduled cron jobs
		$timestamp = wp_next_scheduled('digitalapps_payments_for_adyen_cleanup_3ds_sessions');
		if ($timestamp) {
			wp_unschedule_event($timestamp, 'digitalapps_payments_for_adyen_cleanup_3ds_sessions');
		}
	}

	/**
	 * Add custom cron schedules
	 *
	 * @param array $schedules Existing schedules
	 * @return array Modified schedules
	 */
	public static function add_cron_schedules($schedules)
	{
		if (!isset($schedules['fifteen_minutes'])) {
			$schedules['fifteen_minutes'] = [
				'interval' => 900, // 15 minutes in seconds
				'display' => __('Every 15 Minutes', 'digital-apps-payments-for-adyen')
			];
		}
		return $schedules;
	}

	/**
	 * Clean up expired 3DS sessions
	 * Called by WordPress cron
	 */
	public function cleanup_3ds_sessions()
	{
		$session_manager = new Adyen_Session_Manager();
		$session_manager->cleanup_expired_sessions();
	}

	/** Process one durable webhook inbox row. */
	public function process_webhook_inbox($row_id)
	{
		(new Adyen_Webhook_Inbox())->process((int) $row_id);
	}

	/** Link WooCommerce's newly created refund record to the accepted Adyen operation. */
	public function link_refund_operation($refund_id, $args)
	{
		$order_id = is_array($args) ? (int) ($args['order_id'] ?? 0) : 0;
		$order = $order_id ? wc_get_order($order_id) : false;
		if (!$order || 'digitalapps_payments_for_adyen_card' !== $order->get_payment_method()) {
			return;
		}
		$operations = $order->get_meta(Adyen_Operation::META_KEY, true);
		if (!is_array($operations)) {
			return;
		}
		$amount_value = Adyen_Amount::to_minor_units($args['amount'] ?? 0, $order->get_currency());
		foreach (array_reverse($operations, true) as $operation_id => $operation) {
			if (
				is_array($operation)
				&& 'refund' === ($operation['type'] ?? '')
				&& 'initiated' === ($operation['status'] ?? '')
				&& empty($operation['wooRefundId'])
				&& $amount_value === (int) ($operation['amountValue'] ?? -1)
			) {
				Adyen_Operation::mark($order, $operation_id, 'initiated', ['wooRefundId' => (int) $refund_id]);
				$pre_refund_status = sanitize_key((string) ($operation['preRefundStatus'] ?? 'processing'));
				if ($order->has_status('refunded') && in_array($pre_refund_status, ['processing', 'completed', 'on-hold'], true)) {
					$order->update_status($pre_refund_status, __('Adyen accepted the refund request. Final refund status is pending webhook confirmation.', 'digital-apps-payments-for-adyen'));
				}
				break;
			}
		}
	}

	/**
	 * Plugin uninstall
	 */
	public static function uninstall()
	{
		// Remove options, tables if needed
	}
}
