<?php

/**
 * Envío de las notificaciones.
 * copyright Simple Direct Plugins - support@simpledirectplugins.com
 *
 * https://woocommerce.github.io/code-reference/classes/WC-Email.html
 *
 * @author 			Simple Direct Plugins
 * @link			https://simpledirectplugins.com
 * @since			3.0.0
 * @package			SCOSWoo
 * 
 *
 */

defined ('ABSPATH') or exit;

if (!class_exists ('SCOS_Notification')) :

	#[AllowDynamicProperties]

	Class SCOS_Notification extends WC_Email {

		public function __construct ($estado, $notificaciones) {

			$this->estado         = $estado;
			$this->notificaciones = $notificaciones;

			$this->id             = 'scos_order_status_' . $this->estado->post_name;
			$this->enabled        = $this->enabled && is_array ($this->notificaciones);
			$this->plain          = false; //Is it in plain text?
			$this->customer_email = in_array ('cliente', $this->notificaciones);
			$this->title          = sprintf ('%s %s', esc_html__('Order', 'woocommerce'), sanitize_text_field ($this->estado->post_title) ? mb_strtolower (sanitize_text_field ($this->estado->post_title), 'UTF-8') : esc_html__('in status Custom #', 'sdp-custom-order-status-for-woocommerce') . $this->estado->ID); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
			/* translators: the title of the order status */
			$this->description    = sprintf (esc_html__('Order status %s notification', 'sdp-custom-order-status-for-woocommerce'), sanitize_text_field ($this->estado->post_title) ?: esc_html__('custom #', 'sdp-custom-order-status-for-woocommerce') . $this->estado->ID);
			$this->subject        = get_field ('scos_asunto', $this->estado->ID);
			$this->heading        = $this->get_heading() ?: get_field ('scos_heading', $this->estado->ID) ?: $this->subject;
			$this->text_align     = is_rtl() ? 'right' : 'left';

			if (in_array ('admin', $this->notificaciones)) {

				if ($emails_admin = get_field ('scos_email_admin', $this->estado->ID))
					$this->recipient = str_replace (';', ',', $emails_admin);

				else
					$this->recipient = get_option ('admin_email');
				}

			WC_Email::__construct(); //parent::__construct() está obsoleto desde PHP5.3.
			}

		public function trigger ($id_pedido, $manual = false, $estado = false) {

			if (!$this->is_enabled() && !$manual) //Si se ha forzado manualmente la enviamos, aunque la notificación esté deshabilitada.
				return;

			$this->id_pedido = $id_pedido;
			$this->object    = wc_get_order ($this->id_pedido); //El pedido.
			$this->date      = wp_date (wc_date_format(), strtotime ($this->object->get_date_created()));

			if ($this->customer_email) {

				$this->enviar_cliente = true;
				$this->send(sanitize_email ($this->object->get_billing_email()), sanitize_text_field ($this->get_subject()), $this->get_content(), $this->get_headers(), $this->get_attachments());
				}

			if ($this->recipient) {

				$this->enviar_cliente = false;

				foreach (explode (',', $this->recipient) as $email_admin)
					$this->send(sanitize_email ($email_admin), sanitize_text_field ($this->get_subject()), $this->get_content(), $this->get_headers(), $this->get_attachments());
				}

			$manual and //Si se envían manualmente las notificaciones, añadimos una nota al pedido.
				/* translators: the title of the order status */
				$this->object->add_order_note(sprintf (esc_html__('Notifications for the %s status have been sent manually.', 'sdp-custom-order-status-for-woocommerce'), sanitize_text_field ($estado->post_title) ? : sprintf (esc_html__('custom #%s', 'sdp-custom-order-status-for-woocommerce'), $estado->ID)));
			}

		public function get_subject () {

			return $this->establece_variables($this->subject);
			}

		public function get_content_html () {

			ob_start();
			do_action ('woocommerce_email_header', $this->heading, $this); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
			echo wp_kses_post ($this->plantilla = get_field ('scos_plantilla', $this->estado->ID));

			if ($this->settings['additional_content']) //Opción de contenido adicional de los ajustes de correo electrónico de WC.
				printf ('<p>%s</p>', wp_kses_post ($this->settings['additional_content']));

			do_action ('woocommerce_email_footer', $this); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound

			return $this->establece_variables(ob_get_clean());
			}

		public function get_content_plain () {

			$this->plain = true;

			ob_start();

			$linea = '';

			for ($i = 0; $i < floor (strlen ($this->establece_variables($this->heading)) / 2); $i++)
				$linea .= '=-';

			echo esc_html ($linea) . "=\n";
			echo esc_html ($this->heading) . "\n";
			echo esc_html ($linea) . "=\n";

			echo wp_kses_post ($this->plantilla = get_field ('scos_plantilla', $this->estado->ID));

			if ($this->settings['additional_content']) //Opción de contenido adicional de los ajustes de correo electrónico de WC.
				echo "\n" . wp_kses_post ($this->settings['additional_content']) . "\n";

			echo wp_kses_post (apply_filters ('woocommerce_email_footer_text', get_option ('woocommerce_email_footer_text'))); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound

			return html_entity_decode (wp_strip_all_tags (str_replace (['<br>', '<p>', '€', '&euro;', '&nbsp;'], ["\n", "\n\n", 'EUR', 'EUR', ' '], $this->establece_variables(ob_get_clean()))));
			}

		private function establece_variables ($texto) {

			$num_pedido = $this->devuelve_num_pedido($this->id_pedido);
			$phone_safe = sanitize_text_field ($this->object->get_billing_phone());
			$url_safe   = esc_url (get_bloginfo ('url'));
			$variables  = [
				'%%first_name%%'		=> sanitize_text_field ($this->object->get_billing_first_name()),
				'%%last_name%%'			=> sanitize_text_field ($this->object->get_billing_last_name()),
				'%%company%%'			=> sanitize_text_field ($this->object->get_billing_company()),
				'%%order_number%%'		=> $num_pedido,
				'%%email%%'   			=> sanitize_email ($this->object->get_billing_email()),
				'%%table%%'	  			=> $this->crea_tabla_pedido(),
				'%%notes%%'				=> sanitize_text_field ($this->object->get_customer_note()) ? : esc_html__ ('No order notes.', 'sdp-custom-order-status-for-woocommerce'),
				'%%downloads%%'			=> $this->crea_tabla_descargas(),
				'%%total%%'   			=> esc_html (html_entity_decode (wp_strip_all_tags (wc_price ($this->object->get_total())))),
				'%%billing_details%%'	=> wp_kses_post ($this->crea_bloque_datos('facturacion')),
				'%%shipping_details%%'	=> wp_kses_post ($this->crea_bloque_datos('envio')) ? : wp_kses_post ($this->crea_bloque_datos('facturacion')), //Si no se han establecido, son los mismos que los de facturación.
				'%%phone%%'				=> $this->plain ? $phone_safe : sprintf ('<span class="telefono"><a href="tel:%s">%s</a></span>', $phone_safe, $phone_safe),
				'%%shipping_method%%'	=> sanitize_text_field ($this->object->get_shipping_method()),
				'%%payment%%'			=> sanitize_text_field ($this->object->get_payment_method_title()),
				'%%instructions%%'		=> wp_kses_post ($this->instrucciones_metodo_pago()),
				'%%order_date%%'		=> esc_html ($this->date),

				//También añadimos los marcadores de posición que establece WC.
				'{order_date}'			=> esc_html ($this->date),
				'{order_number}'		=> $num_pedido,
				'{site_title}'			=> sanitize_text_field (get_bloginfo ('name')),
				'{site_address}'		=> $url_safe,
				'{site_url}'			=> $url_safe,
				];

			/**
			 * Incluye un marcador de posición para el NIF.
			 * 
			 * @since	5.1.6
			 * 
			 */
			if (class_exists ('Plugin_Pide_NIF') || class_exists ('APG_Campo_NIF'))
				$variables['%%tax%%'] = sanitize_text_field ($this->object->get_meta('_billing_nif'));

			/**
			 * Incluye un marcador de posición para el EU VAT.
			 * 
			 * @since	5.1.9
			 * 
			 */
			if (class_exists ('WC_EU_VAT_Number_Init')) //WooCommerce EU VAT Number.
				$variables['%%euvat%%'] = sanitize_text_field ($this->object->get_meta('_billing_vat_number'));

			else if (class_exists ('YITH_WooCommerce_EU_VAT')) //YITH WooCommerce EU VAT, OSS & IOSS Premium.
				$variables['%%euvat%%'] = sanitize_text_field ($this->object->get_meta('yweu_billing_vat'));

			foreach ($variables as $variable => $valor)
				if (isset ($variable) && isset ($valor))
					$texto = str_replace ($variable, $valor, $texto);

			return $texto;
			}

		/**
		 * Devuelve la tabla resumen del pedido.
		 *
		 * @since 3.0.0
		 *
		 */
		private function crea_tabla_pedido () {

			$args = apply_filters ('woocommerce_email_order_items_args', //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
				[
					'order'					=> $this->object,
					'items'					=> $this->object->get_items(),
					'show_download_links'	=> $this->object->is_download_permitted() && $this->customer_email,
					'show_sku'				=> false,
					'show_image'			=> false,
					'image_size'			=> [32, 32],
					'plain_text'			=> $this->plain,
					'sent_to_admin'			=> in_array ('admin', $this->notificaciones),
					]
				);

			ob_start();
			do_action ('woocommerce_email_before_order_table', $this->object, in_array ('admin', $this->notificaciones), $this->plain, $this); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound

			if ($this->plain) : //Notificaciones en texto plano.

				printf ('[%s #%s] (%s)', esc_html (strtoupper ('Order', 'woocommerce')), esc_html ($this->devuelve_num_pedido($this->id_pedido)), esc_html (strtoupper ($this->date)));

				echo "\n";
				echo wp_kses_post (wc_get_email_order_items ($this->object, $args));
				echo "==========\n";

				foreach ($this->object->get_order_item_totals() as $linea_total => $datos_linea)
					printf ('%s %s%s', esc_html ($datos_linea ['label']), esc_html ($datos_linea['value']), "\n");

				echo "\n----------------------------------------\n";

			else : //Notificaciones en HTML.

				$link = $this->enviar_cliente ? $this->object->get_view_order_url() : admin_url (sprintf (SCOS_HPOS_ACTIVE ? 'admin.php?page=wc-orders&action=edit&id=%s' : 'post.php?post=%s&action=edit', $this->id_pedido));

				?>

					<h2><?php printf ('<a target="_blank" href="%s" style="font-weight:bold">[%s #%s]</a> (%s)', esc_url ($link), esc_html__('Order', 'woocommerce'), esc_html ($this->devuelve_num_pedido($this->id_pedido)), esc_html ($this->date));  // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch ?></h2>

					<div style="margin-bottom:40px">

						<table class="td" cellspacing="0" cellpadding="6" border="1" style="border-width:1px;border-style:solid;vertical-align:middle;width:100%">
							<thead>
								<tr>
									<th class="td" scope="col" style="border-width:1px;border-style:solid;vertical-align:middle;padding:12px;text-align:<?php echo esc_attr ($this->text_align); ?>"><?php esc_html_e('Product', 'woocommerce');  // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch ?></th>
									<th class="td" scope="col" style="border-width:1px;border-style:solid;vertical-align:middle;padding:12px;text-align:<?php echo esc_attr ($this->text_align); ?>"><?php esc_html_e('Quantity', 'woocommerce');  // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch ?></th>
									<th class="td" scope="col" style="border-width:1px;border-style:solid;vertical-align:middle;padding:12px;text-align:<?php echo esc_attr ($this->text_align); ?>"><?php esc_html_e('Price', 'woocommerce');  // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch ?></th>
								</tr>
							</thead>

							<tbody>

								<?php echo wp_kses_post (wc_get_email_order_items ($this->object, $args)); ?>

							</tbody>

							<tfoot>

								<?php

									foreach ($this->object->get_order_item_totals() as $linea_total => $datos_linea)
										printf ('
											<tr>
												<th class="td" scope="row" colspan="2" style="border-width:1px;border-style:solid;vertical-align:middle;padding:12px;text-align:%s;border-top-width:4px">
													%s
												</th>
												<td class="td" style="border-width:1px;border-style:solid;vertical-align:middle;padding:12px;text-align:%s;border-top-width:4px">
													%s
												</td>
											</tr>',
											esc_attr ($this->text_align),
											esc_html ($datos_linea['label']),
											esc_attr ($this->text_align),
											esc_html (html_entity_decode (wp_strip_all_tags ($datos_linea['value'])))
											);

								?>

							</tfoot>
						</table>

					</div>

				<?php

			endif;

			do_action ('woocommerce_email_after_order_table', $this->object, in_array ('admin', $this->notificaciones), $this->plain, $this); //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound

			return ob_get_clean();
			}

		/**
		 * Devuelve la descripción del método de pago.
		 * Si se paga mediante transferencia, devuelve también el número de cuenta.
		 *
		 * @since 5.0.0
		 *
		 */
		private function instrucciones_metodo_pago () {

			$metodo        = $this->object->get_payment_method();
			$metodos       = WC()->payment_gateways()->payment_gateways();
			$instrucciones = isset ($metodos[$metodo]->instructions) ? sprintf ('<p>%s</p>', esc_html ($metodos[$metodo]->instructions)) : '';

			if ('bacs' == $metodo) { //Sólo si el método de pago para el pedido es la transferencia bancaria.

				//$instrucciones = json_encode ($metodos[$metodo]);

				$datos = [
					'account_number' => __('Account number', 'woocommerce'), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
					'bank_name'		 => __('Bank name', 'woocommerce'), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
					'sort_code'		 => __('Sort code', 'woocommerce'), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
					'iban'			 => __('IBAN', 'woocommerce'), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
					'bic'			 => __('BIC / Swift', 'woocommerce'), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
					];

				foreach ($metodos['bacs']->account_details as $cuenta) { //Puede haber más de una cuenta bancaria.

					$relleno = false;

					foreach ($datos as $dato => $texto_dato) {

						if (isset ($cuenta[$dato]) && strlen ($cuenta[$dato])) {

							$relleno = true;
							break; //Con que haya uno relleno ya no comprobamos más, hay que mostrar datos de esta cuenta.
							}
						}

					if (!$relleno)
						continue; //Si no se ha rellenado ningún dato para esta cuenta, seguimos con la siguiente.

					$instrucciones .= '<p>';

					foreach ($datos as $dato => $texto_dato)
						if (isset ($cuenta[$dato]) && strlen ($cuenta[$dato]))
							$instrucciones .= esc_html ($texto_dato) . ': ' .  esc_html ($cuenta[$dato]) . '<br>';

					$instrucciones .= '</p>';
					}
				}

			return $this->plain ? str_replace (['<p>', '</p>', '<br>'], ["\n", "\n", "\n"], $instrucciones) : $instrucciones;
			}

		/**
		 * Devuelve la tabla de descargas.
		 * https://woocommerce.wp-a2z.org/oik_api/wc_orderget_downloadable_items/
		 * woocommerce/templates/emails/plain/email-downloads.php
		 *
		 * @since 4.0.0
		 *
		 */
		private function crea_tabla_descargas () {

			if (!$this->object->has_downloadable_item() || !$this->object->is_download_permitted()) //Si el pedido no tiene archivos descargables o la descarga no está permitida nos vamos de aquí.
				return '';

			$descargas = $this->object->get_downloadable_items();
			$columnas  = apply_filters ('woocommerce_email_downloads_columns', //phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
				[
					'download-product' => esc_html__('Product', 'woocommerce'), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
					'download-expires' => esc_html__('Expires', 'woocommerce'), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
					'download-file'    => esc_html__('Download', 'woocommerce'), // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
					]
				);

			ob_start();

			if ($this->plain) : //Notificaciones en texto plano.

				echo esc_html (strtoupper (esc_html__('Downloads', 'woocommerce'))) . "\n"; // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch

				foreach ($descargas as $descarga) {

					foreach ($columnas as $columna_id => $columna_nombre) {

						printf ('%s: ', esc_html ($columna_nombre));

						if (has_action ('woocommerce_email_downloads_column_' . $columna_id))
							//phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
							do_action ('woocommerce_email_downloads_column_' . $columna_id, $descarga, true); //$this->plain

						else {

							switch ($columna_id) {

								case 'download-product':

									sanitize_text_field ($descarga['product_name']);

									break;

								case 'download-file':

									printf ('%s - %s', esc_html ($descarga['download_name']), esc_url ($descarga['download_url']));

									break;

								case 'download-expires':

									if (isset ($descarga['access_expires']))
										esc_html (wp_date (wc_date_format(), strtotime ($descarga['access_expires'])));

									else
										esc_html_e('Never', 'woocommerce'); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch

									break;
								}
							}

						echo "\n"; //Fin de columna.
						}

					echo "\n"; //Fin de descarga.
					}

			else : //Notificaciones en HTML.

				printf ('<h2 class="woocommerce-order-downloads__title">%s</h2>', esc_html__('Downloads', 'woocommerce')); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
				echo '<table class="td" cellspacing="0" cellpadding="6" style="width:100%;font-family:\'Helvetica Neue\',Helvetica,Roboto,Arial,sans-serif;margin-bottom:40px" border="1"><thead><tr>';

				foreach ($columnas as $columna_id => $columna_nombre)
					printf ('<th class="td" scope="col" style="text-align:%s">%s</th>', esc_attr ($this->text_align), esc_html ($columna_nombre));

				echo '</tr></thead><tbody>';

				foreach ($descargas as $descarga) {

					echo '<tr>';

					foreach ($columnas as $columna_id => $columna_nombre) {

						printf ('<td class="td" style="text-align:%s">', esc_attr ($this->text_align));

						if (has_action ('woocommerce_email_downloads_column_' . $columna_id))
							//phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
							do_action ('woocommerce_email_downloads_column_' . $columna_id, $descarga, false); //$this->plain

						else {

							switch ($columna_id) {

								case 'download-product':

									printf ('<a href="%s">%s</a>', esc_url (get_permalink ($descarga['product_id'])), esc_url ($descarga['product_name']));

									break;

								case 'download-file':

									printf ('<a href="%s" class="woocommerce-MyAccount-downloads-file button alt">%s</a>', esc_url ($descarga['download_url']), esc_html ($descarga['download_name']));
									
									break;

								case 'download-expires':

									if (isset ($descarga['access_expires']))
										printf ('<time datetime="%s" title="%s">%s</time>', esc_html (gmdate ('Y-m-d', strtotime ($descarga['access_expires']))), esc_html (strtotime ($descarga['access_expires'])), esc_html (date_i18n (wc_date_format(), strtotime ($descarga['access_expires']))));

									else
										esc_html_e ('Never', 'woocommerce'); // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch

									break;
								}
							}

						echo '</td>';
						}

					echo '</tr>';
					}

				echo '</tbody></table>';

			endif;

			return ob_get_clean();
			}

		/**
		 * Devuelve el bloque de datos de facturación/envío.
		 *
		 * @since 	3.1.4
		 *
		 * @param 	string ('facturacion' || 'envio')
		 * @return 	string
		 *
		 */
		private function crea_bloque_datos ($datos) {

			$bloque = '';
			
			if ('facturacion' === $datos) {

				$direccion = $this->object->get_formatted_billing_address() and
					$bloque = sprintf ('%s<br>', $direccion);

				if (null == ($nif = $this->object->get_meta('_billing_nif')))
					$nif = $this->object->get_meta('NIF');
					
				if (isset ($nif) && strlen ($nif))
					$bloque .= sprintf ('%s: %s<br>', null != ($campo_nif = get_option ('nif_texto_campo')) ? sanitize_text_field ($campo_nif) : esc_html__('NIF/CIF', 'sdp-custom-order-status-for-woocommerce'), sanitize_text_field ($nif));

				if (null !== ($euvat = $this->object->get_meta('_billing_vat_number')) && strlen ($euvat)) //WooCommerce EU VAT Number.
					$bloque .= sprintf ('%s: %s<br>', null != ($campo_euvat = get_option ('woocommerce_eu_vat_number_field_label')) ? sanitize_text_field ($campo_euvat) : esc_html__('EU VAT number', 'sdp-custom-order-status-for-woocommerce'), sanitize_text_field ($euvat));

				if (null !== ($euvat = $this->object->get_meta('yweu_billing_vat')) && strlen ($euvat)) //YITH WooCommerce EU VAT, OSS & IOSS Premium.
					$bloque .= sprintf ('%s: %s<br>', null != ($campo_euvat = get_option ('ywev_eu_vat_field_label')) ? sanitize_text_field ($campo_euvat) : esc_html__('EU VAT number', 'sdp-custom-order-status-for-woocommerce'), sanitize_text_field ($euvat));
				}

			else if ('envio' == $datos)
				$direccion = $this->object->get_formatted_shipping_address() and
					$bloque = sprintf ('%s<br>', $direccion);

			return $this->plain ? str_replace ('<br>', "\n", $bloque) : sprintf ('<p class="direccion-%s">%s</p>', $datos, $bloque);
			}

		/**
		 * Devuelve el número de pedido configurado a partir del número de pedido real.
		 * Puede no coincidir si hay activo un plugin de números de pedido secuenciales.
		 *
		 * @param 	int|string 		ID
		 * @return 	int|string 		ID
		 *
		 * @since 	2.5.0
		 *
		 */
		private function devuelve_num_pedido ($id_pedido) {

			/**
			 * Sequential Order Numbers for WooCommerce (SkyVerge).
			 * https://wordpress.org/plugins/woocommerce-sequential-order-numbers/
			 * 
			 */
			if (class_exists ('WC_Seq_Order_Number'))
				$meta = '_order_number';

			/**
			 * WooCommerce Sequential Order Numbers Pro (SkyVerge).
			 * https://woocommerce.com/products/sequential-order-numbers-pro/
			 * 
			 */
			else if (class_exists ('WC_Seq_Order_Number_Pro'))
				$meta = '_order_number_formatted';

			/**
			 * YITH Sequential Order Number (YITH).
			 * https://yithemes.com/themes/plugins/yith-woocommerce-sequential-order-number/
			 * 
			 */
			else if (function_exists ('YITH_Sequential_Order_Number_Premium_Init'))
				$meta = '_ywson_custom_number_order_complete';

			/**
			 * Sequential Order Number for WooCommerce (WebToffee).
			 * https://wordpress.org/plugins/wt-woocommerce-sequential-order-numbers/
			 * 
			 */
			else if (function_exists ('run_wt_advanced_order_number'))
				$meta = '_order_number';

			else
				return $id_pedido;

			return $this->object->get_meta($meta);
			}

		}

endif;