<?php
/**
 * Handles email notifications for the WP Easy File Upload & Approval plugin.
 *
 * @package EASYFUA
 */

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

/**
 * Main Class for Email Manager
 * Send user notification for admin, user and also if all files are reviewed.
 */
class EASYFUA_Email_Manager {

	/**
	 * File manager handler for approve, reject, delete
	 *
	 * @var object $file_manager A file manager class.
	 */
	private $file_manager;

	/**
	 * Get the name of the site.
	 *
	 * @var string $site_name
	 */
	private $site_name;

	/**
	 * Set html format in email.
	 *
	 * @var array $html_email Wheather to send html mail.
	 */
	private $html_email;

	/**
	 * Main class constructor load hook and tables.
	 */
	public function __construct() {

		// File manager class.
		$this->file_manager = new EASYFUA_File_Manager();

		// Get sitename.
		$this->site_name = get_bloginfo( 'name' );

		// Set email to html format.
		$this->html_email = apply_filters( 'easyfua_html_email', true );

		// Hook into all files reviewed action. [send reviews approve,reject email]
		add_action( 'easyfua_all_files_reviewed', array( $this, 'send_submission_status_email' ), 10 );

		// Hook after submission [individual after form submission]
		add_action( 'easyfua_after_post_submitted', array( $this, 'send_admin_notification' ), 50 ); // send admin notification.
		add_action( 'easyfua_after_post_submitted', array( $this, 'send_user_notification' ), 40 );  // send user notification.
	}

	/**
	 * Get submission info like user email or name.
	 *
	 * @param mixed $submission File submission ID.
	 * @return array|void return name or email otherwise null.
	 */
	public function get_submission_info( $submission ) {
		if ( ! $submission ) {
			return;
		}

		// Getting submission data.
		if ( ! empty( $submission->user_id ) && $submission->user_id > 0 ) {
			$user  = get_userdata( $submission->user_id );
			$name  = $user->user_firstname;
			$email = $user->user_email;
		} else {
			$form_data = isset( $submission->form_data ) ? json_decode( $submission->form_data, true ) : array();
			$name      = ( isset( $form_data['name'] ) ? $form_data['name'] : 'Guest' );
			$email     = ( isset( $form_data['email'] ) ? $form_data['email'] : null );
		}

		return compact( 'name', 'email' );
	}

	/**
	 * Getting email recipient with sanitization.
	 *
	 * @param mixed $recipient List of emails separated by comma.
	 * @param mixed $data      Email templates or file data from the settings.
	 * @return string[]
	 */
	public function get_email_to( $recipient, $data = array() ) {
		$emails = explode( ',', $recipient );
		$to     = array();

		foreach ( $emails as $email ) {
			$email = trim( $email );

			// Placeholder email.
			if ( strtolower( $email ) === '{admin_email}' ) {
				$email = get_option( 'admin_email' );
			} elseif ( strtolower( $email ) === '{user_email}' ) {
				$email = $data['email'] ?? '';
			}

			// Validate and sanitize email.
			if ( is_email( $email ) ) {
				$to[] = sanitize_email( $email );
			}
		}

		return $to;
	}

	/**
	 * Get header based on the settings from the admin.
	 *
	 * @param mixed $header Header settings from plugin settings.
	 * @return string[]|void
	 */
	public function get_headers( $header ) {

		// No headers bail early.
		if ( empty( $header ) ) {
			return;
		}

		$headers = array();
		$lines   = explode( "\n", $header );

		// Using html email.
		if ( $this->html_email ) {
			$headers[] = 'Content-Type: text/html; charset=UTF-8';
		}

		foreach ( $lines as $line ) {
			$headers[] = ! empty( $line ) ? trim( html_entity_decode( $line ) ) : '';
		}

		return $headers;
	}

	/**
	 * Manually send a notification to the uploader. [action button was set in "class-easyfua-submissions-files"]
	 *
	 * @param mixed $submission_id File submission id.
	 * @return void
	 */
	public function notified_user( $submission_id ) {
		if ( $submission_id ) {
			add_filter(
				'easyfua_user_reviewed_subject',
				function ( $subject ) {
					return $subject . ' (Status Update)';
				},
				10
			);
			$this->send_submission_status_email( $submission_id );
		}
	}

	/**
	 * Send an email when all files are reviewed. [approve, reject]
	 *
	 * @param int $submission_id The submission ID.
	 */
	public function send_submission_status_email( $submission_id ) {

		// No submission id bail early.
		if ( ! $submission_id ) {
			return;
		}

		$rows         = '';
		$files        = $this->file_manager->get_submission_files( $submission_id );
		$file_count   = count( $files );
		$status_notif = easyfua_settings( 'submission_status' ); // Get 'submission status' email template.
		$submission   = $this->file_manager->get_submission( $submission_id );
		$headers      = array('Content-Type: text/html; charset=UTF-8');

		// Get user info display_name & email.
		$user_info = $this->get_submission_info( $submission );

		// Custom icon status.
		$status_icons = array(
			'approved' => '✅ ' . __( 'Approved', 'easy-file-upload-approval' ),
			'rejected' => '❌ ' . __( 'Rejected', 'easy-file-upload-approval' ),
			// phpcs:ignore
			// 'deleted'  => '🗑️ ' . __( 'Deleted', 'easy-file-upload-approval' ),
		);

		// Loop all files.
		foreach ( $files as $file ) {
			$file_status = isset( $file['file_status'] ) ? $file['file_status'] : '';
			$status      = isset( $status_icons[ $file_status ] ) ? $status_icons[ $file_status ] : esc_html( $file_status );

			// Add note if rejected.
			if ( 'rejected' === $file_status ) {
				if ( ! empty( $file['admin_note'] ) ) {
					$status = sprintf(
						'%s <span>(%s %s)</span>',
						esc_html( $status ),
						esc_html__( 'note:', 'easy-file-upload-approval' ),
						wp_kses_post( $file['admin_note'] )
					);
				}
			}

			$rows .= sprintf(
				'<tr><td>%s</td><td>%s</td><td>%s</td></tr>',
				esc_html( $file['file_name'] ),
				esc_html( $file['file_type'] ),
				$status
			);
		}

		// Singular and plural text.
		$singular_plural_subject = _n(
			'file has',
			'files have',
			$file_count,
			'easy-file-upload-approval'
		);

		// Default subject.
		$subject = sprintf(
			// translators: %s will be replaced with "file has" or "files have".
			esc_html__( 'Your uploaded %s been reviewed', 'easy-file-upload-approval' ),
			esc_html( $singular_plural_subject )
		);

		// Custom: Subject from admin settings.
		if ( easyfua_isset( $status_notif, 'subject' ) ) {
			$subject = esc_html( $status_notif['subject'] );
			if ( strpos( $status_notif['subject'], '%s' ) !== false ) {
				$subject = str_replace( '%s', $singular_plural_subject, $subject );
			}
		}

		// Setup Headers.
		if ( easyfua_isset( $status_notif, 'headers' ) ) {
			$headers = (array) $this->get_headers( $status_notif['headers'] );
		}

		// Send email to.
		$user_email = sanitize_email( $user_info['email'] ?? '' );
		if ( easyfua_isset( $status_notif, 'email' ) ) {
			$user_email = $this->get_email_to( $status_notif['email'], $user_info );
		}

		// Email "Body Messsage" (Use default or custom template from the settings).
		$body_message = easyfua_email_template( 'status-notification' );
		if ( easyfua_isset( $status_notif, 'message' ) ) {
			$body_message = $status_notif['message'];
		}

		// Replacing %s with "file has" or "files have".
		if ( strpos( $body_message, '%s' ) !== false ) {
			$body_message = str_replace( '%s', $singular_plural_subject, $body_message );
		}

		// Submission data placeholder and their values.
		$data = array(
			'{display_name}' => esc_html( ucfirst( $user_info['name'] ) ?? '' ),
			'{files_data}'   => $rows,
			'{site_name}'    => $this->site_name,
		);

		// Replacing placeholders.
		$message = strtr( $body_message, $data );

		// Apply filters for subject and message.
		$subject = apply_filters( 'easyfua_user_reviewed_subject', $subject, $files );
		$message = apply_filters( 'easyfua_user_reviewed_message', $message, $files );

		// Custom Action before sent.
		do_action( 'easyfua_before_status_notification_send', $subject, $message );

		// Send an email.
		wp_mail( $user_email, $subject, wp_kses_post( $message ), $headers );
	}

	/**
	 * Notify admin after form submission.
	 *
	 * @param mixed $submission_id File submission id.
	 * @return void
	 */
	public function send_admin_notification( $submission_id ) {

		// No submission id bail early.
		if ( ! $submission_id ) {
			return;
		}

		$submission_url = wp_nonce_url( admin_url( sprintf( 'admin.php?page=easyfua-main-menu&sub=view-files&submission_id=%d', absint( $submission_id ) ) ), 'easyfua-nonce' );
		$files          = (array) $this->file_manager->get_submission_files( $submission_id );
		$submission     = $this->file_manager->get_submission( $submission_id );
		$admin_notif    = easyfua_settings( 'admin_notif' );
		$headers        = array('Content-Type: text/html; charset=UTF-8');
		$admin_email    = get_option( 'admin_email' ); // default email recipient.

		// Get user info display_name & email.
		$submission_info = $this->get_submission_info( $submission );

		// Use _n() to show "file" vs "files" in admin message.
		$file_word = _n( 'file', 'files', count( $files ), 'easy-file-upload-approval' );

		// Default subject.
		$subject = sprintf(
			// translators: %s will be replaced with "file" or "files".
			__( 'New %s submission', 'easy-file-upload-approval' ),
			$file_word
		);

		// Custom: Subject from admin settings.
		if ( easyfua_isset( $admin_notif, 'subject' ) ) {
			$subject = esc_html( $admin_notif['subject'] );
			if ( strpos( $admin_notif['subject'], '%s' ) !== false ) {
				$subject = str_replace( '%s', $file_word, $subject );
			}
		}

		// Setup Headers.
		if ( easyfua_isset( $admin_notif, 'headers' ) ) {
			$headers = (array) $this->get_headers( $admin_notif['headers'] );
		}

		// Send email to.
		if ( easyfua_isset( $admin_notif, 'email' ) ) {
			$admin_email = $this->get_email_to( $admin_notif['email'] );
		}

		// Email "Body Messsage" (Use default or custom template from the settings).
		$body_message = easyfua_email_template( 'admin-notification' );
		if ( easyfua_isset( $admin_notif, 'message' ) ) {
			$body_message = $admin_notif['message'];
		}

		// Submission data placeholder and their values.
		$data = array(
			'{display_name}'   => esc_html( ucfirst( $submission_info['name'] ) ?? '' ),
			'{email}'          => sanitize_email( $submission_info['email'] ?? '' ),
			'{submitted_at}'   => easyfua_date( $submission->submitted_at ?? '' ),
			'{total_files}'    => absint( $submission->total_files ?? 0 ),
			'{submission_url}' => esc_url( $submission_url ?? '' ),
			'{site_name}'      => $this->site_name,
		);

		// Replacing placeholders.
		$message = strtr( $body_message, $data );

		// Apply filters for subject and message.
		$subject = apply_filters( 'easyfua_admin_submission_subject', $subject, $files );
		$message = apply_filters( 'easyfua_admin_submission_message', $message, $files );

		// Custom Action before sent.
		do_action( 'easyfua_before_admin_notification_send', $subject, $message );

		// Send email.
		wp_mail( $admin_email, $subject, wp_kses_post( $message ), $headers );
	}

	/**
	 * Notify or email user after form submission.
	 *
	 * @param mixed $submission_id File submission ID.
	 * @return void
	 */
	public function send_user_notification( $submission_id ) {

		// Bail early.
		if ( ! $submission_id ) {
			return;
		}

		// Get submission and files data.
		$files      = $this->file_manager->get_submission_files( $submission_id );
		$submission = $this->file_manager->get_submission( $submission_id );
		$user_notif = easyfua_settings( 'user_notif' );
		$headers    = array('Content-Type: text/html; charset=UTF-8');

		// Get user info display_name & email.
		$user_info = $this->get_submission_info( $submission );

		// Build files table.
		$rows = '';
		foreach ( $files as $file ) {
			$rows .= sprintf(
				'<tr>
					<td>%s</td>
					<td>%s</td>
					<td>%s</td>
					<td>%s</td>
				</tr>',
				esc_html( $file['file_name'] ),
				esc_html( $file['file_type'] ),
				esc_html( easyfua_format_file_size( $file['file_size'] ) ),
				esc_html( easyfua_date( $file['submitted_at'] ) ),
			);
		}

		// Singular and plural text.
		$singular_plural_subject = _n( 'file has', 'files have', count( $files ), 'easy-file-upload-approval' );

		// Default: Mail subject.
		$subject = sprintf(
			esc_html__( 'Your %s been submitted successfully', 'easy-file-upload-approval' ),
			esc_html( $singular_plural_subject )
		);

		// Custom: Subject from admin settings.
		if ( easyfua_isset( $user_notif, 'subject' ) ) {
			$subject = esc_html( $user_notif['subject'] );
			if ( strpos( $user_notif['subject'], '%s' ) !== false ) {
				$subject = str_replace( '%s', $singular_plural_subject, $subject );
			}
		}

		// Setup Headers.
		if ( easyfua_isset( $user_notif, 'headers' ) ) {
			$headers = (array) $this->get_headers( $user_notif['headers'] );
		}

		// Send email to.
		$user_email = sanitize_email( $user_info['email'] ?? '' );
		if ( easyfua_isset( $user_notif, 'email' ) ) {
			$user_email = $this->get_email_to( $user_notif['email'], $user_info );
		}

		// Email Body Messsage (Use default or custom template from the settings).
		$body_message = easyfua_email_template( 'user-notification' );
		if ( easyfua_isset( $user_notif, 'message' ) ) {
			$body_message = $user_notif['message'];
		}

		// Submission data placeholder and their values.
		$data = array(
			'{display_name}' => esc_html( ucfirst( $user_info['name'] ) ?? '' ),
			'{files_data}'   => $rows,
			'{site_name}'    => $this->site_name,
		);

		// Replacing placeholders.
		$message = strtr( $body_message, $data );

		// Custom Action before sent.
		do_action( 'easyfua_before_user_notification_send', $subject, $message );

		// Apply filters for subject and message.
		$subject = apply_filters( 'easyfua_user_submission_subject', $subject, $files );
		$message = apply_filters( 'easyfua_user_submission_message', $message, $files );

		// Send email.
		wp_mail( $user_email, $subject, wp_kses_post( $message ), $headers );
	}
}
