<?php
/**
 * CreatePdf.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 POP
 *
 * 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.
 */

namespace WcElectronInvoice\Pdf;

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

use WcElectronInvoice\Admin\Settings\OptionPage;
use WcElectronInvoice\Integrations;
use WcElectronInvoice\Plugin;
use WcElectronInvoice\Providers\OrderQuery;
use WcElectronInvoice\WooCommerce\Fields\GeneralFields;
use WcElectronInvoice\Xml\CreateXml;
use function WcElectronInvoice\Functions\disableInvoiceOnOrderTotalZero;
use function WcElectronInvoice\Functions\getZugferdCompletedOrderAttachments;
use function WcElectronInvoice\Functions\getPostType;

/**
 * Class CreatePdf
 *
 * @since  1.0.0
 * @author alfiopiccione <alfio.piccione@gmail.com>
 */
final class CreatePdf
{
    /**
     * List type
     *
     * @since 1.0.0
     */
    const LIST_TYPE = 'shop_order';

    /**
     * CreatePdf constructor.
     *
     * @since  1.0.0
     */
    public function __construct()
    {
        /* ... */
    }

    /**
     * Progressive file number
     *
     * @param $ordersData
     *
     * @return string
     * @since 1.0.0
     *
     */
    public static function progressiveFileNumber($ordersData)
    {
        // Controlla che $ordersData sia un oggetto con proprietà 'id'
        if (! is_object($ordersData) || ! property_exists($ordersData, 'id')) {
            return '';
        }

        $documentType = $ordersData->document_type ?? $ordersData->order_type ?? 'shop_order';
        $parentId     = $ordersData->parent_id ?? 0;
        $order        = \WcElectronInvoice\Functions\resolveProviderDocument(
            $ordersData->id,
            $ordersData->provider,
            (string)$documentType,
            $parentId
        );
        if (! $order) {
            return '';
        }

        $offset = 1000000; // offset

        $number = $order->get_order_number_invoice();
        if ($order instanceof \WcElectronInvoice\Providers\OrderRefund) {
            $number = $order->get_meta("refund_number_invoice-{$order->get_id()}");
        }

        $number = (int)$number;

        if ($number >= 1) {
            $dateCompleted = $order->get_date_completed();
            if(is_object($dateCompleted)) {
                $number = $number + (int)$dateCompleted->format('i');
            }
            $number = base_convert($number, 10, 36);
        } else {
            $dateCompleted = $order->get_date_completed();
            if(is_object($dateCompleted)) {
                $number = $number + $order->get_id() + (int)$dateCompleted->format('i');
            }
            $number = base_convert($number, 10, 36);
        }

        $number = substr($number, -5);
        $number = str_pad($number, 5, '0', STR_PAD_LEFT);

        $number = apply_filters('wc_el_inv-invoice_progressive_file_number', $number, $order->get_id(), 'pdf');

        return strtoupper($number);
    }

    /**
     * Remove Sent Invoice attachment file
     *
     * @return bool
     * @since 1.0.0
     *
     */
    public function removeSentInvoice($return, $emilID, $emailObj)
    {
        if (is_subclass_of($emailObj, 'WC_Email') && 'customer_completed_order' === $emilID) {
            // Get xml file
            $tempPDF = glob(
                Plugin::getPluginDirPath('/') . '/tempPdf/*'
            );

            if (! empty($tempPDF) && count($tempPDF) > 1) {
                foreach ($tempPDF as $file) {
                    if (file_exists($file) && is_file($file)) {
                        $info = pathinfo($file);
                        if ('index' === $info['filename'] && 'php' === $info['extension']) {
                            continue;
                        }
                        if ('invoice' !== $info['filename']) {
                            unlink($file);
                        }
                    }
                }

                return true;
            }
        }

        return false;
    }

    /**
     * Attachments Pdf To Email (WooCommerce provider)
     *
     * @param $attachments
     * @param $emailID
     * @param $order
     *
     * @return array|false|string
     * @since 1.0.0
     *
     */
    public function attachmentsPdfToEmail($attachments, $emailID, $order)
    {
        $provider = 'woocommerce';

        // Order null and not support email id, return!
        $wcOrderClass = \WcElectronInvoice\Functions\wcOrderClassName($order, '\WC_Order');
        if (! $order instanceof $wcOrderClass && ! in_array($emailID, array(
                'send_order_details',
                'customer_invoice',
                'customer_completed_order',
                'custom_email_completed_order_pdf_invoice',
                'custom_email_completed_order_pdf_receipt',
            ))) {
            error_log("[WcElectronInvoice] attachmentsPdfToEmail error: order = null, emailID = {$emailID}");

            return $attachments;
        }

        // Send attachments via email ?
        $active          = OptionPage::init()->getOptions('invoice_via_email');
        $forceAttachment = in_array($emailID, array(
            'custom_email_completed_order_pdf_invoice',
            'custom_email_completed_order_pdf_receipt',
        ), true);

        // Not send/create attachments for the bulk action
        $actionBulkCheck = \WcElectronInvoice\Functions\filterInput($_REQUEST, 'action', FILTER_UNSAFE_RAW);
        if ('mark_completed' === $actionBulkCheck) {
            return $attachments;
        }

        if ('on' !== $active && ! $forceAttachment) {
            return $attachments;
        }

        $order = OrderQuery::instance()->getProviderOrder($order->get_id(), $provider);
        // check if all variables properly set
        if (! is_object($order) || ! isset($emailID)) {
            return $attachments;
        }

        // Skip User emails
        if ($order instanceof \WP_User) {
            return $attachments;
        }

        if (! is_subclass_of($order, '\WcElectronInvoice\Providers\Order')) {
            return $attachments;
        }

        // Disable invoice order PDF email whit total zero
        if (disableInvoiceOnOrderTotalZero($order)) {
            return $attachments;
        }

        $orderID = $order->get_id();

        if (! $orderID) {
            return $attachments;
        }

        // Skip if order not completed
        if (! $order->has_status('completed')) {
            return $attachments;
        }

        // do not process low stock notifications, user emails etc!
        if (in_array($emailID, array(
                'no_stock',
                'low_stock',
                'backorder',
                'customer_new_account',
                'customer_reset_password',
            )) || getPostType($orderID) !== self::LIST_TYPE) {
            return $attachments;
        }

        // Default email ID
        $allowedEmailID = array(
            'send_order_details',
            'customer_invoice',
            'customer_completed_order',
            'custom_email_completed_order_pdf_invoice',
            'custom_email_completed_order_pdf_receipt',
        );

        /**
         * Filter wc email id for allowed attachment
         */
        $allowedEmailID = apply_filters('wc_el_inv-allowed_email_id_for_attachment', $allowedEmailID, $orderID);

        if (in_array($emailID, $allowedEmailID, true)) {
            if (Integrations::isGermanyZugferdContext()) {
                return getZugferdCompletedOrderAttachments($order);
            }

            try {

                // Pdf type conditions
                switch ($emailID) {
                    default :
                    case 'custom_email_completed_order_pdf_invoice':
                        $type = 'invoice';
                        break;
                    case 'custom_email_completed_order_pdf_receipt':
                        $type = 'receipt';
                        break;
                }

                // Invoice or Receipt
                $choiceTypeModifier = $order->get_meta('_billing_choice_type');
                if (is_subclass_of($order, '\WcElectronInvoice\Providers\Order') && 'receipt' === $choiceTypeModifier) {
                    $type = 'receipt';
                }

                if (false === apply_filters('wc_el_inv-use_external_attachments', false)) {
                    $key       = OptionPage::getK();
                    $nonce     = wp_create_nonce('wc_el_inv_pop_invoice');
                    $url       = esc_url_raw(add_query_arg([
                        self::LIST_TYPE => $orderID,
                        'provider'      => $provider,
                        'key'           => $key,
                        'format'        => 'pdf',
                        'nonce'         => $nonce,
                        'choice_type'   => $type,
                        'v'             => time(),
                    ], site_url('/' . \WcElectronInvoice\EndPoint\Endpoints::ENDPOINT)));
                    $response  = wp_remote_get($url, \WcElectronInvoice\Functions\getSessionCookieArgs());
                    $pdfOutput = wp_remote_retrieve_body($response);
                } else {
                    // Filter for external attachments
                    $pdfOutput = apply_filters('wc_el_inv-attachments_invoice_pdf_output', null, $order->get_id());
                }

                $data           = new \stdClass();
                $data->id       = $orderID;
                $data->provider = $provider;

                // File name
                $vatNumber = preg_replace('/^' . preg_quote(GeneralFields::getGeneralInvoiceOptionCountryState(),
                        '/') . '/',
                    '', GeneralFields::getGeneralInvoiceOptionVatNumber()
                );
                $fileName  = GeneralFields::getGeneralInvoiceOptionCountryState() . $vatNumber . '_' . self::progressiveFileNumber($data) . '.pdf';

                if (! $pdfOutput) {
                    $message   = __('Error in generating the PDF, download it from your reserved area, or ask the seller for it',
                        WC_EL_INV_TEXTDOMAIN);
                    $pdfOutput = "<!DOCTYPE html><html><head><meta http-equiv='Content-Type' content='text/html; charset=utf-8'/><title>{$fileName}</title></head><body><h1>{$message}</h1></body></html>";
                }

                return $this->buildAttachment($order, $fileName, $pdfOutput);
            } catch (\Exception $e) {
                return '';
            }
        }

        return $attachments;
    }

    /**
     * Build Attachment
     *
     * @param $order
     * @param $fileName
     * @param $attachments
     *
     * @return array
     * @since  1.0.0
     *
     */
    public function buildAttachment($order, $fileName, $attachments)
    {
        if (! is_subclass_of($order, '\WcElectronInvoice\Providers\Order')) {
            return $attachments;
        }

        // Get pdf data & store in temp file
        if (strpos($attachments, '%PDF-') === 0) {
            // is PDF or String
            $pdf = $attachments;
        } else {
            return $attachments;
        }

        $pdfDir = Plugin::getPluginDirPath('/tempPdf');
        if (! is_dir($pdfDir)) {
            wp_mkdir_p(trailingslashit($pdfDir));
            if (! is_writable($pdfDir)) {
                @chmod($pdfDir, 0755);
                if (! is_writable($pdfDir)) {
                    wp_die(esc_html__('The directory is not writable even after attempting to change permissions. Please check server settings.',
                            WC_EL_INV_TEXTDOMAIN) . ' DIR: ' . $pdfDir);
                }
            }
        }

        $pdfPath = Plugin::getPluginDirPath('/tempPdf/invoice.pdf');
        file_put_contents($pdfPath, $pdf);

        // Initialize new attachments
        $attachments = array();

        // Copy temp file
        $tempFile = copy(
            $pdfPath,
            Plugin::getPluginDirPath('/tempPdf') . '/' . $fileName
        );

        if ($tempFile) {
            $attachments[] = Plugin::getPluginDirPath('/tempPdf') . '/' . $fileName;
        }

        return $attachments;
    }

    /**
     * Create PDF
     *
     * @param $xmlData
     *
     * @return mixed
     * @since  1.0.0
     *
     */
    public function buildPdf($xmlData)
    {
        $getFormat = \WcElectronInvoice\Functions\filterInput($_GET, 'format', FILTER_UNSAFE_RAW);
        $getNonce  = \WcElectronInvoice\Functions\filterInput($_GET, 'nonce', FILTER_UNSAFE_RAW);
        $data      = ! empty($xmlData) && ! empty($xmlData[0]) ? (object)$xmlData[0] : null;
        // Override choice_type from $_GET['choice_type'] value
        $choiceType = \WcElectronInvoice\Functions\filterInput($_GET, 'choice_type', FILTER_UNSAFE_RAW);

        if (! $data) {
            return $xmlData;
        }

        // Default type choice.
        $data->choice_type = 'invoice';
        if ($choiceType) {
            $data->choice_type = $choiceType;
        }

        // Check params from url REFERER or URI
        $retrieveFromRemote = isset($_SERVER['HTTP_REFERER']) ?
            strpos($_SERVER['HTTP_REFERER'], 'format=pdf&nonce=') : false;
        $retrieveFromRemote = isset($_SERVER['REQUEST_URI']) ?
            strpos($_SERVER['REQUEST_URI'], 'format=pdf&nonce=') : $retrieveFromRemote;

        // Check click referer action
        $requestFromClick = (! is_user_logged_in() && false === wp_verify_nonce($getNonce, 'wc_el_inv_pop_invoice'));

        // Block request from not logged in user
        if ('pdf' === $getFormat &&
            ($requestFromClick && false === $retrieveFromRemote) &&
            'dev' !== WC_EL_INV_ENV
        ) {
            wp_send_json(esc_html__('ERROR: you can not view the PDF for security and privacy issues. To view it you must be logged in',
                WC_EL_INV_TEXTDOMAIN), 400);
            die();
        }

        if ('pdf' !== $getFormat) {
            return $xmlData;
        }

        $xml = new CreateXml(new \SimpleXMLElement(
                '<?xml version="1.0" encoding="UTF-8"?><xmlns:p:FatturaElettronica/>',
                LIBXML_NOERROR,
                false,
                'p',
                true)
        );

        // PDF file name
        $VatNumber            = preg_replace('/^' . preg_quote(GeneralFields::getGeneralInvoiceOptionCountryState(),
                '/') . '/',
            '', GeneralFields::getGeneralInvoiceOptionVatNumber()
        );
        $fileName             = GeneralFields::getGeneralInvoiceOptionCountryState() . $VatNumber . '_' . self::progressiveFileNumber($xmlData[0]);
        $xmlData[0]->filename = $fileName;

        return $xml->createFromCloud($xmlData, 'pdf');
    }

    /**
     * Create PDF
     *
     * @param array $xmlData The args for create Pdf
     *
     * @return mixed
     */
    public static function create($xmlData)
    {
        try {
            $instance = new CreatePdf();

            return $instance->buildPdf($xmlData);
        } catch (\Exception $e) {
            echo esc_html__('Create PDF Exception: ', WC_EL_INV_TEXTDOMAIN) . esc_html($e->getMessage()) . "\n";
        }
    }
}
