<?php

namespace Pay4AllForMypos;

use Pay4AllForMypos\Backend\ConfigPage;
use Pay4AllForMypos\Backend\SchemaMigrator;
use Pay4AllForMypos\Blocks\BlocksRegistration;
use Pay4AllForMypos\Checkout\MyposGateway;
use Pay4AllForMypos\Checkout\ReturnHandler;
use Pay4AllForMypos\Checkout\WebhookHandler;
use Pay4AllForMypos\Integrations\Pay4AllForm;
use Pay4AllForMypos\Support\WooBridge;

/**
 * Class Bootstrap
 *
 * Wires the plugin's constants, PSR-4 autoloader, WooCommerce gateway and
 * WooCommerce-Blocks integration together. Modelled directly on the
 * Pay4All for Stripe bootstrap - same admin menu shape, same wizard
 * pattern, minus the vendored SDK (myPOS ships no PHP client library ;
 * we call the IPC endpoint with wp_remote_* directly from `Api/IpcClient`).
 *
 * @package Pay4AllForMypos
 */
class Bootstrap
{
    public function __construct()
    {
        include_once __DIR__ . '/constants.php';

        register_activation_hook(   PAY4ALL_FOR_MYPOS_PLUGIN_FILE, [ $this, 'on_activation' ] );
        register_deactivation_hook( PAY4ALL_FOR_MYPOS_PLUGIN_FILE, [ $this, 'on_deactivation' ] );

        add_action( 'admin_enqueue_scripts', [ $this, 'admin_styles' ] );
        add_action( 'plugins_loaded',        [ $this, 'on_plugins_loaded' ] );

        // WooCommerce gateway registration.
        add_filter( 'woocommerce_payment_gateways',            [ $this, 'add_mypos_gateway' ] );
        add_filter( 'woocommerce_available_payment_gateways',  [ $this, 'conditionally_show_payment_gateway' ], 10, 1 );

        // Block-based checkout (WooCommerce Blocks).
        add_action( 'woocommerce_blocks_loaded', [ $this, 'woocommerce_blocks_support' ] );

        // Text domain is loaded from on_plugins_loaded() below - WP's
        // auto-loading only kicks in for WP.org-hosted plugins.
    }

    /**
     * PSR-4 autoloader for the Pay4AllForMypos\ namespace, scoped to /src.
     */
    private function include_files_core()
    {
        spl_autoload_register( static function ( $class_name ) {
            if ( strpos( $class_name, 'Pay4AllForMypos\\' ) !== 0 ) {
                return;
            }
            $relative  = substr( $class_name, strlen( 'Pay4AllForMypos\\' ) );
            $relative  = str_replace( '\\', DIRECTORY_SEPARATOR, $relative );
            $file_path = __DIR__ . DIRECTORY_SEPARATOR . $relative . '.php';
            if ( file_exists( $file_path ) ) {
                require_once $file_path;
            }
        } );
    }

    public function on_activation()
    {
        flush_rewrite_rules();
    }

    public function on_deactivation()
    {
        // Clear scheduled hooks owned by the plugin.
        wp_clear_scheduled_hook( PAY4ALL_FOR_MYPOS_PREFIX . '_check_order_statuses' );
    }

    public function admin_styles()
    {
        if ( ! defined( 'PAY4ALL_FOR_MYPOS_WC_ACTIVE' ) || ! PAY4ALL_FOR_MYPOS_WC_ACTIVE ) {
            return;
        }

        $current_screen = get_current_screen();
        if ( ! $current_screen ) {
            return;
        }

        if (
            $current_screen->base === 'toplevel_page_pay4all-for-mypos-settings'
            || ( method_exists( WooBridge::class, 'get_wc_screen' ) && $current_screen->id === WooBridge::get_wc_screen() )
        ) {
            $css_rel = 'assets/css/admin-styles.css';
            $css_abs = PAY4ALL_FOR_MYPOS_PLUGIN_PATH . DIRECTORY_SEPARATOR . $css_rel;
            if ( file_exists( $css_abs ) ) {
                wp_enqueue_style(
                    'pay4all_for_mypos_admin_style',
                    PAY4ALL_FOR_MYPOS_PLUGIN_URL . $css_rel,
                    [],
                    PAY4ALL_FOR_MYPOS_PLUGIN_VERSION
                );
            }
        }
    }

    public function on_plugins_loaded()
    {
        // Load the .mo files bundled under /languages/ so the plugin's
        // shipped FR / DE / IT translations are available immediately
        // after install (before translate.wordpress.org community
        // contributions catch up). WordPress core auto-loads from
        // /wp-content/languages/plugins/ once translate.wordpress.org
        // publishes, but that only kicks in for locales that have been
        // manually translated by a community contributor — hence the
        // explicit call here as a safety net for our first-party langs.
        // phpcs:ignore PluginCheck.CodeAnalysis.DiscouragedFunctions.load_plugin_textdomainFound -- intentional : ships our own FR/DE/IT .mo files as a safety net until translate.wordpress.org catches up.
        load_plugin_textdomain(
            'pay4all-for-mypos',
            false,
            dirname( plugin_basename( PAY4ALL_FOR_MYPOS_PLUGIN_FILE ) ) . '/languages'
        );

        defined( 'PAY4ALL_FOR_MYPOS_WC_ACTIVE' ) || define( 'PAY4ALL_FOR_MYPOS_WC_ACTIVE', class_exists( 'woocommerce' ) );

        $has_wc     = PAY4ALL_FOR_MYPOS_WC_ACTIVE;
        $has_p4form = class_exists( '\\Pay4All\\Form\\Plugin' )
            || defined( 'P4ALL_FORM_VERSION' )
            || post_type_exists( 'p4all_form' );

        // Informational notice when neither host plugin is present, but the
        // wizard + settings stay reachable so the merchant can prepare
        // credentials in advance. Scoped to plugins.php only per WP.org
        // Guideline 11 §18 (no admin-wide banners).
        if ( ! $has_wc && ! $has_p4form ) {
            add_action( 'admin_notices', static function () : void {
                $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
                if ( ! $screen || $screen->id !== 'plugins' ) { return; }
                $install_url = admin_url( 'plugin-install.php?s=Pay4All&tab=search&type=term' );
                $link        = '<a href="' . esc_url( $install_url ) . '">Pay4All Shop</a>';
                $message     = sprintf(
                    /* translators: %s: link to install Pay4All Shop */
                    esc_html__( 'Pay4All for myPOS requires %s or WooCommerce to be installed.', 'pay4all-for-mypos' ),
                    $link
                );
                echo '<div class="notice notice-error"><p>' . wp_kses(
                    $message,
                    [ 'a' => [ 'href' => [] ] ]
                ) . '</p></div>';
            } );
        }

        // Register the autoloader.
        $this->include_files_core();

        // The Pay4All for myPOS Settings admin page must always be reachable,
        // even on sites without WooCommerce.
        if ( is_admin() && ! is_network_admin() ) {
            add_action( 'admin_menu', [ $this, 'add_admin_menu' ], 99 );
            \Pay4AllForMypos\Backend\WizardPage::register();
            \Pay4AllForMypos\Backend\WcSettings::register();
        }

        // The Return + Webhook handlers and the Pay4All Form integration
        // are usable WITHOUT WooCommerce (Pay4All Shop route).
        ReturnHandler::register();
        WebhookHandler::register();
        Pay4AllForm::register();

        // ConfigPage instance registers all `admin_post_pay4all_for_mypos_*`
        // handlers (save_pack, toggle_mode, save_methods, save_statuses,
        // test_connection, delete_credential). Registered regardless of WC
        // presence so the wizard works on Pay4All Shop-only installs.
        if ( is_admin() && ! is_network_admin() ) {
            ConfigPage::get_instance();
        }

        if ( ! PAY4ALL_FOR_MYPOS_WC_ACTIVE ) {
            return;
        }

        SchemaMigrator::init();
        SchemaMigrator::update_db();

        // Override WC's default post-payment status transition so paid
        // orders land on the merchant-chosen status (virtual → «completed»
        // by default, physical → «processing»). Fires for BOTH the
        // ReturnHandler (user-facing return URL) and the WebhookHandler
        // (server-to-server IPCPurchaseNotify) code paths.
        add_filter(
            'woocommerce_payment_complete_order_status',
            static function ( $status, $order_id, $order = null ) {
                if ( ! $order instanceof \WC_Order ) {
                    $order = wc_get_order( $order_id );
                }
                if ( ! $order instanceof \WC_Order ) { return $status; }
                if ( $order->get_payment_method() !== \Pay4AllForMypos\Checkout\MyposGateway::SLUG ) { return $status; }
                return ConfigPage::paid_status_for_wc_order( $order );
            },
            10,
            3
        );

        add_filter( 'plugin_action_links_' . plugin_basename( PAY4ALL_FOR_MYPOS_PLUGIN_FILE ), [ $this, 'action_links' ] );
    }

    /**
     * Top-level "Pay4All myPOS" admin menu. Same shape as Pay4All for Stripe:
     *   - The Wizard IS the settings page (guided setup + day-to-day État tab)
     *   - A "Help" submenu with screenshot-based guides (Pack test, Pack prod,
     *     payment methods)
     */
    public function add_admin_menu()
    {
        $cap     = ( defined( 'PAY4ALL_FOR_MYPOS_WC_ACTIVE' ) && PAY4ALL_FOR_MYPOS_WC_ACTIVE ) ? 'manage_woocommerce' : 'manage_options';
        $top_lbl = __( 'Pay4All myPOS', 'pay4all-for-mypos' );

        add_menu_page(
            $top_lbl,
            $top_lbl,
            $cap,
            \Pay4AllForMypos\Backend\WizardPage::SLUG,
            [ '\\Pay4AllForMypos\\Backend\\WizardPage', 'render' ],
            'dashicons-money-alt',
            80.8
        );

        add_submenu_page(
            \Pay4AllForMypos\Backend\WizardPage::SLUG,
            __( 'Settings', 'pay4all-for-mypos' ),
            __( 'Settings', 'pay4all-for-mypos' ),
            $cap,
            \Pay4AllForMypos\Backend\WizardPage::SLUG,
            [ '\\Pay4AllForMypos\\Backend\\WizardPage', 'render' ]
        );

        add_submenu_page(
            \Pay4AllForMypos\Backend\WizardPage::SLUG,
            __( 'myPOS help', 'pay4all-for-mypos' ),
            __( 'myPOS help', 'pay4all-for-mypos' ),
            $cap,
            \Pay4AllForMypos\Backend\KeysGuidePage::SLUG,
            [ '\\Pay4AllForMypos\\Backend\\KeysGuidePage', 'render' ]
        );

        add_submenu_page(
            \Pay4AllForMypos\Backend\WizardPage::SLUG,
            __( 'Add-ons', 'pay4all-for-mypos' ),
            __( 'Add-ons', 'pay4all-for-mypos' ),
            $cap,
            \Pay4AllForMypos\Backend\AddOnsPage::SLUG,
            [ '\\Pay4AllForMypos\\Backend\\AddOnsPage', 'render' ]
        );
    }

    /**
     * @param array $methods
     * @return array
     */
    public function add_mypos_gateway( $methods )
    {
        $methods[] = MyposGateway::class;
        return $methods;
    }

    /**
     * Filter callback - passes through untouched. Availability is decided
     * by MyposGateway::is_available() based on whether a Configuration
     * Pack is set for the active mode.
     *
     * @param array $available_gateways
     * @return array
     */
    public function conditionally_show_payment_gateway( $available_gateways )
    {
        return $available_gateways;
    }

    public function woocommerce_blocks_support()
    {
        if ( class_exists( '\\Automattic\\WooCommerce\\Blocks\\Payments\\Integrations\\AbstractPaymentMethodType' ) ) {
            BlocksRegistration::register();
        }
    }

    /**
     * "Settings" link next to Activate/Deactivate on the plugins list.
     *
     * @param array $links
     * @return array
     */
    public function action_links( $links )
    {
        $plugin_links = [
            '<a href="' . esc_url( admin_url( 'admin.php?page=' . \Pay4AllForMypos\Backend\WizardPage::SLUG ) ) . '">'
                . esc_html__( 'Settings', 'pay4all-for-mypos' )
                . '</a>',
        ];
        return array_merge( $plugin_links, $links );
    }
}
