<?php
/**
 * filtersFront.php
 *
 * @since      1.0.0
 * @author     alfiopiccione <alfio.piccione@gmail.com>
 * @license    http://opensource.org/licenses/gpl-2.0.php GPL v2
 *
 * Copyright (C) 2025 alfiopiccione <alfio.piccione@gmail.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

if (! defined('ABSPATH')) {
    exit; // Exit if accessed directly.
}

// if WooCommerce isn't active, do not add any filters
if (! \WcElectronInvoice\Functions\isWooCommerceActive()) {
    return;
}

$fields        = include \WcElectronInvoice\Plugin::getPluginDirPath('/inc/billingFields.php');
$endPointApi   = new \WcElectronInvoice\EndPoint\Endpoints();
$optionPage    = \WcElectronInvoice\Admin\Settings\OptionPage::init();
$invoiceFields = new \WcElectronInvoice\WooCommerce\Fields\InvoiceFields((array)$fields, $optionPage);

//
//  array(
//      'filter'        => ''
//      'callback'      => ''
//      'priority'      => ''
//      'accepted_args' => ''
//  )
//
$filtersFront = array(
    'front' => array(
        'action' => array(
            /**
             * Validation checkout for payment_method (ppec_paypal, ppcp-gateway)
             */
            array(
                'filter'        => 'woocommerce_after_checkout_validation',
                'callback'      => array($invoiceFields, 'validation'),
                'priority'      => 20,
                'accepted_args' => 2,
            ),
            array(
                'filter'        => 'woocommerce_order_details_after_customer_address',
                'callback'      => array($invoiceFields, 'renderTaxInformationAfterBillingAddress'),
                'priority'      => 30,
                'accepted_args' => 2,
            ),

            /**
             * WooCommerce
             *
             * - checkout process @since 1.0.0
             * - address process @since 1.0.0
             */
            array(
                'filter'   => array(
                    'woocommerce_before_checkout_process',
                    'woocommerce_checkout_process',
                    'woocommerce_after_save_address_validation',
                ),
                'callback' => array($invoiceFields, 'process'),
                'priority' => 20,
            ),

            /**
             * Add custom meta for check shipping to different address
             *
             * @since 1.0.0
             */
            array(
                'filter'        => 'woocommerce_checkout_order_processed',
                'callback'      => array($invoiceFields, 'haveShippingAddress'),
                'priority'      => 20,
                'accepted_args' => 3,
            ),

            /**
             * - WC auto completed and processing order - Set the invoice number if necessary
             *
             * @since 1.0.0
             */
            array(
                'filter'   => array(
                    'woocommerce_payment_complete',
                    'woocommerce_pre_payment_complete',
                    'woocommerce_order_status_completed',
                    'woocommerce_order_status_processing',
                ),
                'callback' => 'WcElectronInvoice\\Functions\\setInvoiceNumberOnOrderAutoCompleted',
                'priority' => 10,
            ),

            array(
                'filter'   => array(
                    'woocommerce_payment_complete',
                    'woocommerce_pre_payment_complete',
                    'woocommerce_order_status_completed',
                ),
                'callback' => 'WcElectronInvoice\\Xml\\CreateXml::createXMLOnOrderCompleted',
                'priority' => 10,
            ),

            /**
             * Action front WC orders
             * - REST route for invoice/receipt PDF
             * - Create invoice/receipt PDF
             */
            array(
                'filter'   => 'rest_api_init',
                'callback' => function () {
                    register_rest_route('pop-wp/v1', '/invoice/(?P<order_id>\d+)', [
                        'methods'             => 'GET',
                        'callback'            => function ($request) {
                            $orderID            = (int)$request['order_id'];
                            $params             = $request->get_params();
                            $provider           = isset($params['provider']) ? sanitize_key((string)$params['provider']) : '';
                            $action             = $params['action'];
                            $nonce              = $params['nonce'];
                            $orderQuery         = \WcElectronInvoice\Providers\OrderQuery::instance();

                            if ('' === $provider) {
                                $providerCandidates = ['woocommerce', 'pmpro', 'cozmoslabspms'];
                                $activeProviders    = [];

                                foreach ($providerCandidates as $providerCandidate) {
                                    if (is_object($orderQuery->get_provider($providerCandidate))) {
                                        $activeProviders[] = $providerCandidate;
                                    }
                                }

                                if (1 === count($activeProviders)) {
                                    $provider = $activeProviders[0];
                                } elseif (count($activeProviders) > 1) {
                                    return new WP_Error(
                                        'missing_provider',
                                        __('Provider parameter is required when multiple providers are active.', WC_EL_INV_TEXTDOMAIN),
                                        ['status' => 400, 'providers' => $activeProviders]
                                    );
                                } else {
                                    return new WP_Error(
                                        'missing_provider',
                                        __('Provider parameter is required.', WC_EL_INV_TEXTDOMAIN),
                                        ['status' => 400]
                                    );
                                }
                            }

                            try {
                                $order = $orderQuery->getProviderOrder($orderID, $provider);
                            } catch (\Throwable $e) {
                                return new WP_Error('invalid_provider', __('Invalid provider parameter.', WC_EL_INV_TEXTDOMAIN), ['status' => 400]);
                            }

                            if (! is_object($order)) {
                                return new WP_Error('order_not_found', __('Order not found for provider.', WC_EL_INV_TEXTDOMAIN), ['status' => 404]);
                            }

                            $choiceTypeModifier = $order->get_meta('_billing_choice_type');

                            $type = 'invoice';
                            if (is_subclass_of($order,
                                    '\WcElectronInvoice\Providers\Order') && 'receipt' === $choiceTypeModifier) {
                                $type = 'receipt';
                            }

                            $key      = WcElectronInvoice\Admin\Settings\OptionPage::getK();
                            $url      = esc_url_raw(add_query_arg([
                                'shop_order'  => $orderID,
                                'provider'    => $provider,
                                'key'         => $key,
                                'format'      => 'pdf',
                                'choice_type' => $type,
                                'action'      => $action,
                                'nonce'       => $nonce,
                                'route'       => $request->get_route(),
                                'v'           => time(),
                            ], site_url('/')));
                            $response = wp_remote_get($url,
                                \WcElectronInvoice\Functions\getSessionCookieArgs('application/pdf', 'front'));

                            if (is_wp_error($response)) {
                                return new WP_Error('pdf_error', 'PDF recovery error', ['status' => 500]);
                            }

                            $pdfOutput = wp_remote_retrieve_body($response);
                            $headers   = wp_remote_retrieve_headers($response);
                            $filename  = 'invoice.pdf';

                            if (isset($headers['content-disposition']) &&
                                preg_match('/filename="?([^"]+)"?/i', $headers['content-disposition'], $matches)
                            ) {
                                $filename = $matches[1];
                            }
                            if (ob_get_length()) {
                                ob_end_clean();
                            }

                            header('Content-Type: application/pdf');
                            header('Content-Disposition: attachment; filename="' . $filename . '"');
                            header('Content-Length: ' . strlen($pdfOutput));
                            header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
                            header('Pragma: no-cache');

                            echo $pdfOutput;
                            exit;
                        },
                        'permission_callback' => function ($request) {
                            $params = $request->get_params();
                            $action = $params['action'];

                            return ('invoice_pdf' === $action || 'receipt_pdf' === $action);
                        },
                    ]);
                },
                'priority' => 10,
            ),
            array(
                'filter'   => 'wp',
                'callback' => function () {
                    $orderID    = \WcElectronInvoice\Functions\filterInput($_GET, 'shop_order', FILTER_VALIDATE_INT);
                    $provider   = \WcElectronInvoice\Functions\filterInput($_GET, 'provider', FILTER_UNSAFE_RAW);
                    $key        = \WcElectronInvoice\Functions\filterInput($_GET, 'key', FILTER_UNSAFE_RAW);
                    $format     = \WcElectronInvoice\Functions\filterInput($_GET, 'format', FILTER_UNSAFE_RAW);
                    $choiceType = \WcElectronInvoice\Functions\filterInput($_GET, 'choice_type', FILTER_UNSAFE_RAW);
                    $action     = \WcElectronInvoice\Functions\filterInput($_GET, 'action', FILTER_UNSAFE_RAW);
                    $nonce      = \WcElectronInvoice\Functions\filterInput($_GET, 'nonce', FILTER_UNSAFE_RAW);
                    $route      = \WcElectronInvoice\Functions\filterInput($_GET, 'route', FILTER_UNSAFE_RAW);

                    if (wp_verify_nonce($nonce, 'wc_el_inv_pop_invoice') &&
                        $route === "/pop-wp/v1/invoice/{$orderID}" &&
                        $orderID && $provider && $key && $format && $choiceType &&
                        ('invoice_pdf' === $action || 'receipt_pdf' === $action)
                    ) {
                        // Filter XML data and create PDF
                        add_filter('wc_el_inv-xml_data_filter', 'WcElectronInvoice\\Pdf\\CreatePdf::create');
                        $xml = new \WcElectronInvoice\Xml\BuildXml();
                        $xml->send();
                        exit();
                    }
                },
                'priority' => 10,
            ),

            /**
             * SDI via POP
             * Cron Jobs on order auto completed
             */
            array(
                'filter'        => array(
                    'woocommerce_payment_complete',
                    'woocommerce_payment_complete_order_status_completed',
                    'woocommerce_payment_complete_order_status_processing',
                    'woocommerce_order_status_completed',
                    'woocommerce_order_status_processing',
                ),
                'callback'      => function ($orderID) {
                    if (! \WcElectronInvoice\Integrations::isInvoiceChannelActive(\WcElectronInvoice\Integrations::CHANNEL_SDIPOP)) {
                        return;
                    }

                    \WcElectronInvoice\InvoiceApi::autoCompleted($orderID);
                },
                'priority'      => 10,
                'accepted_args' => 1,
            ),

            /**
             * PEPPOL via POP
             * Cron Jobs on order auto completed
             */
            array(
                'filter'        => array(
                    'woocommerce_payment_complete',
                    'woocommerce_payment_complete_order_status_completed',
                    'woocommerce_payment_complete_order_status_processing',
                    'woocommerce_order_status_completed',
                    'woocommerce_order_status_processing',
                ),
                'callback'      => function ($orderID) {
                    if (! \WcElectronInvoice\Integrations::isInvoiceChannelActive(\WcElectronInvoice\Integrations::CHANNEL_PEPPOL)) {
                        return;
                    }

                    \WcElectronInvoice\PeppolApi::autoCompleted($orderID);
                },
                'priority'      => 10,
                'accepted_args' => 1,
            ),

            /**
             * Zoho via POP
             * Cron Jobs on order auto completed
             */
            array(
                'filter'        => array(
                    'woocommerce_payment_complete',
                    'woocommerce_payment_complete_order_status_completed',
                    'woocommerce_payment_complete_order_status_processing',
                    'woocommerce_order_status_completed',
                    'woocommerce_order_status_processing',
                ),
                'callback'      => function ($orderID) {
                    if (! \WcElectronInvoice\Integrations::isInvoiceChannelActive(\WcElectronInvoice\Integrations::CHANNEL_ZOHO)) {
                        return;
                    }

                    \WcElectronInvoice\ZohoApi::autoCompleted($orderID);
                },
                'priority'      => 10,
                'accepted_args' => 1,
            ),

            /**
             * POP to Webhook
             * Cron Jobs on order auto completed
             */
            array(
                'filter'   => array(
                    'woocommerce_payment_complete',
                    'woocommerce_payment_complete_order_status_completed',
                    'woocommerce_payment_complete_order_status_processing',
                    'woocommerce_order_status_completed',
                    'woocommerce_order_status_processing',
                ),
                'callback' => function ($orderID) {
                    \WcElectronInvoice\Functions\webHookScheduledCron($orderID);
                },
                'priority' => 10,
            ),

        ),
        'filter' => array(
            /**
             * Filter Order Json Data
             */
            array(
                'filter'   => array(
                    'wc_el_inv-orders_json_data',
                    'wc_el_inv-orders_refund_json_data',
                ),
                'callback' => 'WcElectronInvoice\\Xml\\CreateXml::filterData',
                'priority' => 10,
            ),

            /**
             * WooCommerce
             *
             * - my account formatted address      @since 1.0.0
             * - billing fields                     @since 1.0.0
             * - formatted address replacements    @since 1.0.0
             * - my account order action           @since 1.0.0
             */
            array(
                'filter'        => 'woocommerce_billing_fields',
                'callback'      => array($invoiceFields, 'billingAddressFields'),
                'priority'      => PHP_INT_MAX,
                'accepted_args' => 3,
            ),
            array(
                'filter'        => 'woocommerce_order_formatted_billing_address',
                'callback'      => array($invoiceFields, 'orderFormattedBillingAddress'),
                'priority'      => 20,
                'accepted_args' => 2,
            ),
            array(
                'filter'        => 'woocommerce_my_account_my_address_formatted_address',
                'callback'      => array($invoiceFields, 'myAccountFormattedAddress'),
                'priority'      => 20,
                'accepted_args' => 3,
            ),
            array(
                'filter'        => 'woocommerce_filter_fields_for_order_confirmation',
                'callback'      => array($invoiceFields, 'filterOrderConfirmationFields'),
                'priority'      => 20,
                'accepted_args' => 5,
            ),
            array(
                'filter'        => 'render_block',
                'callback'      => array($invoiceFields, 'appendTaxInformationToOrderConfirmationBillingBlock'),
                'priority'      => 20,
                'accepted_args' => 2,
            ),
            array(
                'filter'        => 'woocommerce_my_account_my_orders_actions',
                'callback'      => array($invoiceFields, 'actionsFront'),
                'priority'      => 20,
                'accepted_args' => 2,
            ),
        ),
    ),
);

add_filter('wc_el_inv-filters_front', function ($filters) use ($filtersFront) {
    $filters['front']['action'] = array_merge($filters['front']['action'], $filtersFront['front']['action']);
    $filters['front']['filter'] = array_merge($filters['front']['filter'], $filtersFront['front']['filter']);

    return $filters;
}, 10, 1);
