<?php
/**
 * Extends the Purchase Order Class and exports it as PDF
 *
 * @package         Atum\PurchaseOrders
 * @subpackage      Exports
 * @author          BE REBEL - https://berebel.studio
 * @copyright       ©2025 Stock Management Labs™
 *
 * @since           1.3.9
 */

namespace Atum\PurchaseOrders\Exports;

defined( 'ABSPATH' ) || die;

use Atum\Inc\Helpers;
use Atum\PurchaseOrders\Models\PurchaseOrder;
use Atum\PurchaseOrders\PurchaseOrders;
use Atum\Suppliers\Supplier;
use Mpdf\Mpdf;
use Mpdf\MpdfException;
use Mpdf\Output\Destination;


class POExport extends PurchaseOrder {
	
	/**
	 * The company data
	 *
	 * @var array
	 */
	private $company_data = [];

	/**
	 * The shipping data
	 *
	 * @var array
	 */
	private $shipping_data = [];

	/**
	 * Only for PDF debugging during development.
	 *
	 * @var bool
	 */
	private $debug_mode = FALSE;

	/**
	 * Whether to return the HTML code instead of a PDF
	 *
	 * @var bool
	 */
	private $return_html;

	
	/**
	 * POExport constructor
	 *
	 * @since 1.3.9
	 *
	 * @param int  $id   The PO ID.
	 * @param bool $html Optional. Whether to return the HTML code instead of a PDF.
	 */
	public function __construct( $id = 0, bool $html = FALSE ) {

		$post_type         = get_post_type( $id );
		$this->return_html = $html;
		
		if ( PurchaseOrders::get_post_type() !== $post_type ) {
			/* translators: the post ID */
			wp_die( sprintf( esc_html__( 'Not a Purchase Order (%d)', ATUM_TEXT_DOMAIN ), (int) $id ) );
		}
		
		// Always read items.
		parent::__construct( $id );
		
		$this->load_extra_data();
		
	}

	/**
	 * Get all extra data not present in a PO by default
	 *
	 * TODO: THIS NEEDS A FULL REFACTORY AND TO CREATE A MODEL FOR THE STORE DETAILS. ALSO NOT IT SHOULDN'T STORE SEPARATED META KEYS.
	 *
	 * @since 1.3.9
	 */
	private function load_extra_data() {

		$default_country   = get_option( 'woocommerce_default_country', '' );
		$country_state     = wc_format_country_state_string( Helpers::get_option( 'country', $default_country ) );
		$countries         = WC()->countries;
		$default_city      = $countries->get_base_city();
		$default_adress    = $countries->get_base_address();
		$default_address_2 = $countries->get_base_address_2();
		$default_postcode  = $countries->get_base_postcode();

		// Company data.
		$this->company_data = array(
			'company'    => Helpers::get_option( 'company_name', '' ),
			'address_1'  => Helpers::get_option( 'address_1', $default_adress ),
			'address_2'  => Helpers::get_option( 'address_2', $default_address_2 ),
			'city'       => Helpers::get_option( 'city', $default_city ),
			'state'      => $country_state['state'] ?? '',
			'postcode'   => Helpers::get_option( 'zip', $default_postcode ),
			'country'    => $country_state['country'] ?? '',
			'tax_number' => Helpers::get_option( 'tax_number', '' ),
		);
		
		if ( 'yes' === Helpers::get_option( 'same_ship_address', 'yes' ) ) {
			$this->shipping_data = $this->company_data;
		}
		else {

			// Shipping data.
			$country_state = wc_format_country_state_string( Helpers::get_option( 'ship_country', $default_country ) );
			
			$this->shipping_data = array(
				'company'   => Helpers::get_option( 'ship_to', '' ),
				'address_1' => Helpers::get_option( 'ship_address_1', $default_adress ),
				'address_2' => Helpers::get_option( 'ship_address_2', $default_address_2 ),
				'city'      => Helpers::get_option( 'ship_city', $default_city ),
				'state'     => $country_state['state'] ?? '',
				'postcode'  => Helpers::get_option( 'ship_zip', $default_postcode ),
				'country'   => $country_state['country'] ?? '',
			);

		}
		
	}

	/**
	 * Return header content if exist
	 *
	 * @since 1.3.9
	 *
	 * @return string
	 */
	public function get_content() {
		
		$total_text_colspan = 3;
		$post_type          = get_post_type_object( get_post_type( $this->get_id() ) );
		$currency           = $this->currency;
		$discount           = $this->get_total_discount();

		if ( $discount ) {
			$desc_percent = 50;
			$total_text_colspan++;
		}
		else {
			$desc_percent = 60;
		}

		$taxes               = $this->get_taxes();
		$n_taxes             = count( $taxes );
		$desc_percent       -= $n_taxes * 10;
		$total_text_colspan += $n_taxes;

		$line_items_fee      = $this->get_items( 'fee' );
		$line_items_shipping = $this->get_items( 'shipping' );
		$po                  = $this;
		
		ob_start();

		Helpers::load_view( 'reports/purchase-order-html', compact( 'po', 'total_text_colspan', 'post_type', 'currency', 'discount', 'desc_percent', 'taxes', 'n_taxes', 'line_items_fee', 'line_items_shipping' ) );

		return ob_get_clean();
		
	}
	
	/**
	 * Return formatted company address
	 *
	 * @return string
	 */
	public function get_company_address() {
		
		return apply_filters( 'atum/purchase_orders/po_export/company_address', WC()->countries->get_formatted_address( $this->company_data ), $this->company_data );

	}
	
	/**
	 * Return formatted supplier address (includes VAT number if saved)
	 *
	 * @return string
	 */
	public function get_supplier_address() {
		
		$address     = '';
		$supplier_id = $this->get_supplier( 'id' );
		
		if ( $supplier_id ) {

			$supplier = new Supplier( $supplier_id );
			
			$address = WC()->countries->get_formatted_address( array(
				'first_name' => $supplier->name,
				'company'    => $supplier->tax_number,
				'address_1'  => $supplier->address,
				'city'       => $supplier->city,
				'state'      => $supplier->state,
				'postcode'   => $supplier->zip_code,
				'country'    => $supplier->country,
			) );
			
		}
		
		return apply_filters( 'atum/purchase_orders/po_export/supplier_address', $address, $supplier_id );
		
	}
	
	/**
	 * Return formatted company address
	 *
	 * @since 1.3.9
	 *
	 * @return string
	 */
	public function get_shipping_address() {
		
		return apply_filters( 'atum/purchase_orders/po_export/shipping_address', WC()->countries->get_formatted_address( $this->shipping_data ), $this->shipping_data, $this->id );
		
	}

	/**
	 * Getter for the company's Tax/VAT number
	 *
	 * @since 1.7.0
	 *
	 * @return string
	 */
	public function get_tax_number() {

		return $this->company_data['tax_number'];
	}

	/**
	 * Return an array with stylesheets needed to include in the pdf
	 *
	 * @since 1.3.9
	 *
	 * @param string $output Whether the output array of stylesheets are returned as a path or as an URL.
	 *
	 * @return array
	 */
	public function get_stylesheets( $output = 'path' ) {
		
		$prefix = 'url' === $output ? ATUM_URL : ATUM_PATH;
		
		return apply_filters( 'atum/purchase_orders/po_export/css', array( $prefix . 'assets/css/atum-po-export.css' ), $output, $this );
	}

	/**
	 * Getter for the debug mode
	 *
	 * @since 1.9.1
	 */
	public function get_debug_mode() {
		return $this->debug_mode || ( ! empty( $_GET['debug'] ) && 1 === absint( $_GET['debug'] ) );
	}

	/**
	 * Generate the PO PDF/HTML
	 *
	 * @since 1.9.1
	 *
	 * @param Destination $destination_mode
	 *
	 * @return string|\WP_Error
	 *
	 * @throws \Mpdf\MpdfException
	 */
	public function generate( $destination_mode = Destination::INLINE ) {

		try {

			$return_html = TRUE === $this->debug_mode || TRUE === $this->return_html;
			$atum_dir    = Helpers::get_atum_uploads_dir();
			$temp_dir    = $atum_dir . apply_filters( 'atum/purchase_orders/po_export/temp_pdf_dir', 'tmp' );

			if ( ! is_dir( $temp_dir ) ) {

				// Try to create it.
				$success = mkdir( $temp_dir, 0775, TRUE );

				// If wasn't created, use default uploads folder.
				if ( ! $success || ! is_writable( $temp_dir ) ) {
					$temp_dir = $atum_dir;
				}

			}

			do_action( 'atum/purchase_orders/po_export/generate', $this->id );

			// Try to set the backtrack limit to a higher value and avoid issues with huge amount of data.
			@ini_set( 'pcre.backtrack_limit', '9999999' );

			$mpdf = new Mpdf( [
				'mode'    => 'utf-8',
				'format'  => 'A4',
				'tempDir' => $temp_dir,
			] );

			// Add support for non-Latin languages.
			$mpdf->useAdobeCJK      = TRUE; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
			$mpdf->autoScriptToLang = TRUE; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
			$mpdf->autoLangToFont   = TRUE; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase

			$mpdf->SetTitle( __( 'Purchase Order', ATUM_TEXT_DOMAIN ) );

			$mpdf->default_available_fonts = $mpdf->available_unifonts;

			$html = '';
			$css  = $this->get_stylesheets( $return_html ? 'url' : 'path' );

			foreach ( $css as $file ) {

				if ( $return_html ) {
					$html .= '<link rel="stylesheet" href="' . $file . '" media="all">'; // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedStylesheet
				}
				else {
					$stylesheet = file_get_contents( $file ); // phpcs:ignore WordPress.WP.AlternativeFunctions
					$mpdf->WriteHTML( $stylesheet, 1 );
				}

			}

			if ( $return_html ) {
				$html .= $this->get_content();

				return $html;
			}

			$mpdf->WriteHTML( $this->get_content() );

			return $mpdf->Output( "po-{$this->id}.pdf", $destination_mode );

		} catch ( MpdfException $e ) {
			return new \WP_Error( 'atum_pdf_generation_error', $e->getMessage() );
		}

	}

}
