/**
 * Plugin Name:  Peptio – Warehouse Printer Router
 * Description:  Routes the existing Peptiology A4 + QR dispatch sheet to the correct HQ or Europe printer using the fulfilment warehouse already saved on each WooCommerce order. Leaves Dispatch Darian and manual QR printing untouched as a fallback.
 * Version:      1.0.0
 * Author:       Peptio
 *
 * CODE SNIPPETS VERSION:
 * Paste into a PHP snippet WITHOUT adding <?php.
 * Set the snippet to run everywhere.
 *
 * REQUIRES:
 * - Peptio – Multi-Warehouse Core
 * - Peptio – Frontend Warehouse Stock Routing
 * - Existing LE Printer + QR plugin
 *
 * IMPORTANT:
 * - Does NOT change warehouse allocation.
 * - Does NOT change stock.
 * - Does NOT replace Dispatch Darian.
 * - Does NOT replace the QR Scan-to-Dispatch system.
 * - Reuses le_printer_build_body_html() from the existing printer plugin.
 * - Suppresses ONLY the old automatic processing printer send while
 *   multi-warehouse mode is enabled.
 * - Manual Dispatch Darian printing remains operational.
 */

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

/* ==========================================================================
   LOAD GUARD
   ========================================================================== */

if (defined('PEPTI_MW_PRINTER_ROUTER_LOADED')) {
    return;
}

define('PEPTI_MW_PRINTER_ROUTER_LOADED', true);

/* ==========================================================================
   VERSION / CONFIG
   ========================================================================== */

if (!defined('PEPTI_MWPR_VERSION')) {
    define('PEPTI_MWPR_VERSION', '1.0.0');
}

if (!defined('PEPTI_MWPR_DELAY_SECONDS')) {
    define('PEPTI_MWPR_DELAY_SECONDS', 20);
}

/*
 * Existing routing metadata.
 */
if (!defined('PEPTI_MWPR_META_WAREHOUSE')) {
    define(
        'PEPTI_MWPR_META_WAREHOUSE',
        '_pepti_fulfilment_warehouse'
    );
}

if (!defined('PEPTI_MWPR_META_WAREHOUSE_NAME')) {
    define(
        'PEPTI_MWPR_META_WAREHOUSE_NAME',
        '_pepti_fulfilment_warehouse_name'
    );
}

/*
 * Router-specific printer metadata.
 */
if (!defined('PEPTI_MWPR_META_PRINTED_AT')) {
    define(
        'PEPTI_MWPR_META_PRINTED_AT',
        '_pepti_mw_printer_sent_at'
    );
}

if (!defined('PEPTI_MWPR_META_PRINTED_WAREHOUSE')) {
    define(
        'PEPTI_MWPR_META_PRINTED_WAREHOUSE',
        '_pepti_mw_printer_warehouse'
    );
}

if (!defined('PEPTI_MWPR_META_PRINTED_EMAIL')) {
    define(
        'PEPTI_MWPR_META_PRINTED_EMAIL',
        '_pepti_mw_printer_email'
    );
}

if (!defined('PEPTI_MWPR_META_LAST_RESULT')) {
    define(
        'PEPTI_MWPR_META_LAST_RESULT',
        '_pepti_mw_printer_last_result'
    );
}

if (!defined('PEPTI_MWPR_META_LAST_ERROR')) {
    define(
        'PEPTI_MWPR_META_LAST_ERROR',
        '_pepti_mw_printer_last_error'
    );
}

if (!defined('PEPTI_MWPR_META_QUEUED_AT')) {
    define(
        'PEPTI_MWPR_META_QUEUED_AT',
        '_pepti_mw_printer_queued_at'
    );
}

/* ==========================================================================
   CORE AVAILABILITY
   ========================================================================== */

function pepti_mwpr_core_available() {
    return function_exists('pepti_mw_get_settings')
        && function_exists('pepti_mw_is_enabled');
}

function pepti_mwpr_is_enabled() {
    if (!pepti_mwpr_core_available()) {
        return false;
    }

    return (bool) pepti_mw_is_enabled();
}

/* ==========================================================================
   SETTINGS
   ========================================================================== */

function pepti_mwpr_get_settings() {
    if (!function_exists('pepti_mw_get_settings')) {
        return [];
    }

    $settings = pepti_mw_get_settings();

    return is_array($settings)
        ? $settings
        : [];
}

function pepti_mwpr_get_printer_email($warehouse) {
    $warehouse = sanitize_key($warehouse);
    $settings  = pepti_mwpr_get_settings();

    if ($warehouse === 'hq') {
        $email = $settings['hq_printer_email'] ?? '';
    } elseif ($warehouse === 'eu') {
        $email = $settings['eu_printer_email'] ?? '';
    } else {
        return '';
    }

    $email = sanitize_email(
        trim((string) $email)
    );

    return is_email($email)
        ? $email
        : '';
}

/* ==========================================================================
   WAREHOUSE HELPERS
   ========================================================================== */

function pepti_mwpr_get_order_warehouse(WC_Order $order) {
    $warehouse = sanitize_key(
        (string) $order->get_meta(
            PEPTI_MWPR_META_WAREHOUSE,
            true
        )
    );

    if (
        in_array(
            $warehouse,
            ['hq', 'eu'],
            true
        )
    ) {
        return $warehouse;
    }

    return '';
}

function pepti_mwpr_get_warehouse_name($warehouse) {
    $warehouse = sanitize_key($warehouse);

    if (function_exists('pepti_mw_get_warehouses')) {
        $warehouses = pepti_mw_get_warehouses();

        if (
            is_array($warehouses)
            && !empty($warehouses[$warehouse]['name'])
        ) {
            return sanitize_text_field(
                $warehouses[$warehouse]['name']
            );
        }
    }

    return $warehouse === 'eu'
        ? 'Europe Warehouse'
        : 'HQ Warehouse';
}

/* ==========================================================================
   PRINT ELIGIBILITY
   ========================================================================== */

function pepti_mwpr_order_should_print(WC_Order $order) {

    /*
     * Router is completely dormant while multi-warehouse mode is OFF.
     *
     * This is important because it allows the legacy printer system to
     * behave exactly as it does now.
     */
    if (!pepti_mwpr_is_enabled()) {
        return new WP_Error(
            'multi_warehouse_off',
            'Multi-warehouse mode is disabled.'
        );
    }

    if (!$order->has_status('processing')) {
        return new WP_Error(
            'wrong_status',
            'Order is not processing.'
        );
    }

    if (
        $order->has_status(
            [
                'failed',
                'cancelled',
                'refunded',
                'trash',
            ]
        )
    ) {
        return new WP_Error(
            'invalid_status',
            'Order is not eligible for warehouse printing.'
        );
    }

    if (!$order->needs_shipping()) {
        return new WP_Error(
            'no_shipping',
            'Order does not require shipping.'
        );
    }

    /*
     * Preserve the same general behaviour as the legacy printer.
     *
     * Zero-value replacement orders can still be manually printed from
     * Dispatch Darian if required.
     */
    if ((float) $order->get_total() <= 0) {
        return new WP_Error(
            'zero_total',
            'Zero-value order skipped by automatic warehouse printing.'
        );
    }

    $warehouse =
        pepti_mwpr_get_order_warehouse($order);

    if ($warehouse === '') {
        return new WP_Error(
            'warehouse_unassigned',
            'Order has no valid fulfilment warehouse.'
        );
    }

    $printer_email =
        pepti_mwpr_get_printer_email($warehouse);

    if ($printer_email === '') {
        return new WP_Error(
            'printer_not_configured',
            sprintf(
                '%s printer email is not configured.',
                pepti_mwpr_get_warehouse_name(
                    $warehouse
                )
            )
        );
    }

    /*
     * Router-level duplicate protection.
     */
    $sent_at = (int) $order->get_meta(
        PEPTI_MWPR_META_PRINTED_AT,
        true
    );

    if ($sent_at > 0) {
        return new WP_Error(
            'already_printed',
            'Warehouse printer sheet has already been sent.'
        );
    }

    return true;
}

/* ==========================================================================
   PRINTER HTML
   ========================================================================== */

function pepti_mwpr_build_printer_html(
    WC_Order $order
) {
    /*
     * Reuse your existing printer sheet.
     *
     * This preserves:
     * - Existing A4 layout
     * - Existing logo
     * - Existing customs declaration
     * - Existing product formatting
     * - Existing secure QR
     * - Existing Scan-to-Dispatch URL
     */
    if (function_exists('le_printer_build_body_html')) {
        return le_printer_build_body_html(
            $order
        );
    }

    return '';
}

/* ==========================================================================
   SEND TO WAREHOUSE PRINTER
   ========================================================================== */

function pepti_mwpr_send_order(
    WC_Order $order
) {
    $eligibility =
        pepti_mwpr_order_should_print(
            $order
        );

    if (is_wp_error($eligibility)) {
        return $eligibility;
    }

    $order_id =
        $order->get_id();

    $warehouse =
        pepti_mwpr_get_order_warehouse(
            $order
        );

    $warehouse_name =
        pepti_mwpr_get_warehouse_name(
            $warehouse
        );

    $printer_email =
        pepti_mwpr_get_printer_email(
            $warehouse
        );

    $html =
        pepti_mwpr_build_printer_html(
            $order
        );

    if ($html === '') {
        $error = new WP_Error(
            'printer_builder_missing',
            'Existing LE printer HTML builder is unavailable.'
        );

        $order->update_meta_data(
            PEPTI_MWPR_META_LAST_RESULT,
            'fail'
        );

        $order->update_meta_data(
            PEPTI_MWPR_META_LAST_ERROR,
            $error->get_error_message()
        );

        $order->save();

        return $error;
    }

    $subject = sprintf(
        'NEW ORDER #%s – %s – %s',
        $order->get_order_number(),
        get_bloginfo('name'),
        $warehouse_name
    );

    /*
     * X-Peptio-Warehouse-Router is deliberately included.
     *
     * It identifies this as a genuine routed warehouse print and ensures
     * our legacy auto-send suppression does not interfere with it.
     */
    $headers = [
        'Content-Type: text/html; charset=UTF-8',
        'X-LE-Printer: NewOrderHTMLQR-PROXY',
        'X-Peptio-Warehouse-Router: ' . $warehouse,
        'X-Peptio-Warehouse-Order: ' . $order_id,
    ];

    $sent = (bool) wp_mail(
        $printer_email,
        $subject,
        $html,
        $headers
    );

    if (!$sent) {
        $order->update_meta_data(
            PEPTI_MWPR_META_LAST_RESULT,
            'fail'
        );

        $order->update_meta_data(
            PEPTI_MWPR_META_LAST_ERROR,
            sprintf(
                'wp_mail() failed for %s.',
                $printer_email
            )
        );

        $order->save();

        $order->add_order_note(
            sprintf(
                'Warehouse printer FAILED — %s (%s).',
                $warehouse_name,
                $printer_email
            )
        );

        return new WP_Error(
            'send_failed',
            'Warehouse printer email could not be sent.'
        );
    }

    $now = time();

    $order->update_meta_data(
        PEPTI_MWPR_META_PRINTED_AT,
        $now
    );

    $order->update_meta_data(
        PEPTI_MWPR_META_PRINTED_WAREHOUSE,
        $warehouse
    );

    $order->update_meta_data(
        PEPTI_MWPR_META_PRINTED_EMAIL,
        $printer_email
    );

    $order->update_meta_data(
        PEPTI_MWPR_META_LAST_RESULT,
        'ok'
    );

    $order->delete_meta_data(
        PEPTI_MWPR_META_LAST_ERROR
    );

    $order->save();

    $order->add_order_note(
        sprintf(
            'Warehouse printer sheet sent — %s (%s).',
            $warehouse_name,
            $printer_email
        )
    );

    /*
     * Fire an extension hook.
     *
     * Future Mi0ps modules can use this for:
     * - printer health
     * - dispatch telemetry
     * - alerts
     * - warehouse audit history
     */
    do_action(
        'pepti_mw_printer_sent',
        $order_id,
        $warehouse,
        $printer_email,
        $now
    );

    return true;
}

/* ==========================================================================
   AUTOMATIC PRINT QUEUE
   ========================================================================== */

/*
 * Wait until priority 150.
 *
 * Your warehouse allocation / payment callbacks therefore get plenty of
 * opportunity to save the final fulfilment warehouse before we schedule
 * the printer job.
 */
add_action(
    'woocommerce_order_status_changed',
    function(
        $order_id,
        $old_status,
        $new_status
    ) {
        if ($new_status !== 'processing') {
            return;
        }

        if (!pepti_mwpr_is_enabled()) {
            return;
        }

        $order = wc_get_order(
            $order_id
        );

        if (!$order instanceof WC_Order) {
            return;
        }

        /*
         * Don't schedule twice.
         */
        $already_sent = (int) $order->get_meta(
            PEPTI_MWPR_META_PRINTED_AT,
            true
        );

        if ($already_sent > 0) {
            return;
        }

        $args = [
            (int) $order_id,
        ];

        if (
            !wp_next_scheduled(
                'pepti_mwpr_delayed_print',
                $args
            )
        ) {
            wp_schedule_single_event(
                time()
                + max(
                    5,
                    (int) PEPTI_MWPR_DELAY_SECONDS
                ),
                'pepti_mwpr_delayed_print',
                $args
            );

            $order->update_meta_data(
                PEPTI_MWPR_META_QUEUED_AT,
                time()
            );

            $order->save();
        }
    },
    150,
    3
);

/* ==========================================================================
   EXECUTE DELAYED PRINT
   ========================================================================== */

add_action(
    'pepti_mwpr_delayed_print',
    function($order_id) {

        if (!pepti_mwpr_is_enabled()) {
            return;
        }

        /*
         * Reload the order fresh.
         *
         * This is deliberate because payment callbacks and warehouse
         * allocation may have modified it after checkout.
         */
        $order = wc_get_order(
            absint($order_id)
        );

        if (!$order instanceof WC_Order) {
            return;
        }

        $result =
            pepti_mwpr_send_order(
                $order
            );

        if (
            is_wp_error($result)
            && !in_array(
                $result->get_error_code(),
                [
                    'already_printed',
                    'multi_warehouse_off',
                    'wrong_status',
                    'no_shipping',
                    'zero_total',
                ],
                true
            )
        ) {
            $order->add_order_note(
                'Warehouse printer router: '
                . $result->get_error_message()
            );
        }
    },
    10,
    1
);

/* ==========================================================================
   LEGACY AUTOMATIC PRINTER SUPPRESSION
   ========================================================================== */

/**
 * This is the critical compatibility layer.
 *
 * Your existing LE Printer + QR plugin currently schedules:
 *
 *     le_printer_delayed_processing_send
 *
 * about 15 seconds after an order becomes processing.
 *
 * We DO NOT disable the existing plugin.
 * We DO NOT change LE_PRINTER_EMAIL.
 * We DO NOT interfere with Dispatch Darian.
 * We DO NOT interfere with manual printer sends.
 *
 * We only intercept wp_mail while the legacy AUTOMATIC cron/action itself
 * is executing and multi-warehouse mode is enabled.
 *
 * Returning TRUE tells the old plugin the mail operation succeeded, so it
 * does not create a false printer failure.
 */
add_filter(
    'pre_wp_mail',
    function($return, $atts) {

        if (!pepti_mwpr_is_enabled()) {
            return $return;
        }

        /*
         * Only intercept the legacy automatic job.
         *
         * A manual Dispatch Darian print does NOT run inside this action and
         * therefore passes straight through.
         */
        if (
            !doing_action(
                'le_printer_delayed_processing_send'
            )
        ) {
            return $return;
        }

        $headers =
            $atts['headers'] ?? [];

        if (is_string($headers)) {
            $headers = preg_split(
                '/\r\n|\r|\n/',
                $headers
            );
        }

        if (!is_array($headers)) {
            $headers = [];
        }

        $is_legacy_printer_mail = false;
        $is_warehouse_router_mail = false;

        foreach ($headers as $header) {
            $header =
                strtolower(
                    trim(
                        (string) $header
                    )
                );

            if (
                strpos(
                    $header,
                    'x-le-printer:'
                ) === 0
            ) {
                $is_legacy_printer_mail = true;
            }

            if (
                strpos(
                    $header,
                    'x-peptio-warehouse-router:'
                ) === 0
            ) {
                $is_warehouse_router_mail = true;
            }
        }

        /*
         * Never suppress a genuine warehouse-router print.
         */
        if ($is_warehouse_router_mail) {
            return $return;
        }

        /*
         * Suppress only the legacy automatic Brother printer message.
         */
        if ($is_legacy_printer_mail) {
            return true;
        }

        return $return;
    },
    5,
    2
);

/* ==========================================================================
   CLEANUP WHEN ORDER LEAVES PROCESSING BEFORE PRINT
   ========================================================================== */

add_action(
    'woocommerce_order_status_changed',
    function(
        $order_id,
        $old_status,
        $new_status
    ) {
        if ($new_status === 'processing') {
            return;
        }

        $timestamp = wp_next_scheduled(
            'pepti_mwpr_delayed_print',
            [
                (int) $order_id,
            ]
        );

        if ($timestamp) {
            wp_unschedule_event(
                $timestamp,
                'pepti_mwpr_delayed_print',
                [
                    (int) $order_id,
                ]
            );
        }
    },
    200,
    3
);

/* ==========================================================================
   ADMIN / DEBUG HELPERS
   ========================================================================== */

/**
 * Useful from other Mi0ps extensions:
 *
 * pepti_mwpr_get_order_print_status($order_id)
 */
function pepti_mwpr_get_order_print_status(
    $order_or_id
) {
    $order =
        $order_or_id instanceof WC_Order
            ? $order_or_id
            : wc_get_order(
                absint($order_or_id)
            );

    if (!$order instanceof WC_Order) {
        return [
            'status'    => 'invalid',
            'warehouse' => '',
            'email'     => '',
            'sent_at'   => 0,
            'error'     => '',
        ];
    }

    $sent_at = (int) $order->get_meta(
        PEPTI_MWPR_META_PRINTED_AT,
        true
    );

    $result = sanitize_key(
        (string) $order->get_meta(
            PEPTI_MWPR_META_LAST_RESULT,
            true
        )
    );

    $status = 'not_sent';

    if ($sent_at > 0) {
        $status = 'sent';
    } elseif ($result === 'fail') {
        $status = 'failed';
    }

    return [
        'status' => $status,

        'warehouse' => sanitize_key(
            (string) $order->get_meta(
                PEPTI_MWPR_META_PRINTED_WAREHOUSE,
                true
            )
        ),

        'email' => sanitize_email(
            (string) $order->get_meta(
                PEPTI_MWPR_META_PRINTED_EMAIL,
                true
            )
        ),

        'sent_at' => $sent_at,

        'error' => sanitize_text_field(
            (string) $order->get_meta(
                PEPTI_MWPR_META_LAST_ERROR,
                true
            )
        ),
    ];
}

/* ==========================================================================
   SETTINGS STATUS PANEL
   ========================================================================== */

/*
 * No separate interface.
 *
 * We simply add a small diagnostic block underneath your existing
 * Warehouse Operations → Settings screen.
 */
add_action(
    'pepti_mw_workspace_tab_settings',
    function($context) {

        if (!current_user_can('manage_woocommerce')) {
            return;
        }

        $settings =
            pepti_mwpr_get_settings();

        $hq_email =
            pepti_mwpr_get_printer_email(
                'hq'
            );

        $eu_email =
            pepti_mwpr_get_printer_email(
                'eu'
            );

        $enabled =
            pepti_mwpr_is_enabled();

        ?>
        <div
            class="pepti-mw-notice"
            style="margin-top:16px;"
        >
            <strong>
                🖨️ Warehouse Printer Router
            </strong>

            <div style="margin-top:10px;">
                Router:
                <strong>
                    <?php
                    echo $enabled
                        ? 'Active'
                        : 'Standby';
                    ?>
                </strong>
            </div>

            <div style="margin-top:6px;">
                HQ printer:
                <strong>
                    <?php
                    echo $hq_email !== ''
                        ? esc_html($hq_email)
                        : 'Not configured';
                    ?>
                </strong>
            </div>

            <div style="margin-top:6px;">
                Europe printer:
                <strong>
                    <?php
                    echo $eu_email !== ''
                        ? esc_html($eu_email)
                        : 'Not configured';
                    ?>
                </strong>
            </div>

            <div
                class="pepti-subtle"
                style="margin-top:10px;"
            >
                When multi-warehouse mode is enabled,
                automatic order sheets are routed according
                to the fulfilment warehouse stored on the
                WooCommerce order.

                Manual Dispatch Darian printing and the existing
                Scan-to-Dispatch QR system remain available
                as the emergency fallback.
            </div>
        </div>
        <?php
    },
    40,
    1
);