<?php
namespace SabaiApps\Directories\Component\DirectoryPro\SystemTool;

use SabaiApps\Directories\Component\System\Tool\AbstractTool;
use SabaiApps\Directories\Component\Form\Form;
use SabaiApps\Directories\Context;
use SabaiApps\Directories\Component\Entity\Model\Bundle;
use SabaiApps\Directories\Component\Field\Type\IEmail;

class BulkSendEmailSystemTool extends AbstractTool {

	protected function _systemToolInfo() {
		return array(
			'label'       => __( 'Bulk send e-mail', 'directories-pro' ),
			'description' => __( 'This tool allows you to send emails in bulk to users or specific email addresses.', 'directories-pro' ),
			'weight'      => 70,
			'btn_label'   => __( 'Send E-mail', 'directories-pro' ),
			'hidden'      => true,
		);
	}

	protected function _getBundle( Context $context ) {
		return isset( $context->bundle ) && ( $bundle = $this->_application->Entity_Bundle( $context->bundle ) ) ? $bundle : false;
	}

	public function systemToolSettingsForm( $step, array $values, array $parents = array(), ?Context $context = null ) {
		if ( ! $bundle = $this->_getBundle( $context ) ) {
			return false;
		}

		$fields  = empty( $bundle->info['is_user'] ) ? array( 'author' => __( 'Author', 'directories-pro' ) ) : array();
		$fields += $this->_application->Entity_Field_options(
			$bundle,
			array(
				'prefix'      => __( 'Field - ', 'directories-pro' ),
				'name_prefix' => 'field-',
				'interface'   => 'Field\Type\IEmail',
			)
		);

		return array(
			'recipients' => array(
				'#type'       => 'checkboxes',
				'#title'      => __( 'Send to', 'directories-pro' ),
				'#options'    => $fields,
				'#horizontal' => true,
				'#required'   => true,
			),
			'subject'    => array(
				'#type'                  => 'textfield',
				'#title'                 => __( 'E-mail subject', 'directories-pro' ),
				'#placeholder'           => '',
				'#description'           => $desc = $this->_application->System_Util_availableTags( $this->_application->Entity_Tokens( $bundle, true, array( 'site' => true ) ) ),
				'#description_no_escape' => isset( $desc ),
				'#required'              => true,
				'#horizontal'            => true,
			),
			'body'       => array(
				'#type'                  => 'textarea',
				'#title'                 => __( 'E-mail message', 'directories-pro' ),
				'#description'           => isset( $desc ) ? $desc : null,
				'#description_no_escape' => isset( $desc ),
				'#required'              => true,
				'#rows'                  => 10,
				'#horizontal'            => true,
			),
			'query'      => array(
				'#title'            => __( 'Filter target items by field', 'directories-pro' ),
				'#tree'             => true,
				'#element_validate' => array(
					function ( Form $form, &$value, $element ) {
						if ( empty( $value['fields'] ) ) {
							return;
						}

						$queries = array();
						foreach ( array_filter( $value['fields'] ) as $query ) {
							if ( ! strlen( $query['field'] )
								|| ! strlen( trim( $query['query'] ) )
							) {
								continue;
							}

							$queries[ $query['field'] ] = $query['query'];
						}
						$value['fields'] = $queries;
					},
				),
				'fields'            => array(
					array(
						'#type'           => 'field_query',
						'#fields'         => $this->_application->Entity_Field( $bundle ),
						'#default_value'  => null,
						'#query_in_admin' => true,
					),
				),
				'_add'              => array(
					'#type' => 'addmore',
				),
				'#horizontal'       => true,
			),
			'num'        => array(
				'#type'          => 'slider',
				'#title'         => __( 'Number of items to process per request', 'directories-pro' ),
				'#horizontal'    => true,
				'#default_value' => 50,
				'#min_value'     => 1,
				'#max_value'     => 100,
				'#integer'       => true,
				'#required'      => true,
			),
		);
	}

	public function systemToolInit( array $settings, array &$storage, array &$logs, ?Context $context = null ) {
		if ( ! $bundle = $this->_getBundle( $context ) ) {
			return;
		}

		return array( $bundle->name => $this->_getQuery( $bundle, $settings, $logs )->count() );
	}

	protected function _getQuery( Bundle $bundle, array $settings, array &$logs ) {
		$query = $this->_application->Entity_Query( $bundle->entitytype_name, $bundle->name, empty( $settings['query']['fields'] ) ? array() : $settings['query']['fields'] );
		return $query;
	}

	public function systemToolRunTask( $task, array $settings, $iteration, $total, array &$storage, array &$logs, ?Context $context = null ) {
		if ( ! $bundle = $this->_getBundle( $context ) ) {
			return false;
		}

		$paginator = $this->_getQuery( $bundle, $settings, $logs )
			->sortById()
			->paginate( $settings['num'] )
			->setCurrentPage( $iteration );
		if ( $entities = $paginator->getElements() ) {
			foreach ( $entities as $entity ) {
				$emails = array();
				foreach ( $settings['recipients'] as $recipient ) {
					if ( strpos( $recipient, 'field-' ) === 0 ) {
						$field_name = substr( $recipient, strlen( 'field-' ) );
						if ( ( ! $field = $this->_application->Entity_Field( $bundle->name, $field_name ) )
							|| ( ! $field_type = $this->_application->Field_Type( $field->getFieldType(), true ) )
							|| ! $field_type instanceof IEmail
						) {
							$logs['error'][] = sprintf( __( 'Invalid field %s.', 'directories-pro' ), $recipient );
							continue;
						}
						foreach ( $field_type->fieldEmailAddress( $field, $entity, false ) as $field_value ) {
							$emails[ $field_value ] = $field_value;
						}
					} elseif ( $recipient === 'author' ) {
						if ( ( $author_id = $entity->getAuthorId() )
							&& ( $author = $this->_application->UserIdentity( $author_id ) )
							&& ! empty( $author->email )
						) {
							$emails[ $author->email ] = $author->email;
						}
					}
				}
				if ( empty( $emails ) ) {
					$logs['info'][] = sprintf( __( 'No recipient e-mail addresses found for item "%s".', 'directories-pro' ), $entity->getTitle() );
					continue;
				}
				$subject = $this->_application->Entity_Tokens_replace( $settings['subject'], $entity, true );
				$body    = $this->_application->Entity_Tokens_replace( $settings['body'], $entity, true );
				foreach ( $emails as $email ) {
					if ( $this->_application->getPlatform()->mail( $email, $subject, $body ) ) {
						$logs['success'][] = sprintf( __( 'E-mail sent to %1$s for item "%2$s".', 'directories-pro' ), $email, $entity->getTitle() );
					} else {
						$logs['error'][] = sprintf( __( 'E-mail could not be sent to %1$s for item "%2$s".', 'directories-pro' ), $email, $entity->getTitle() );
					}
				}
			}
		}

		return $paginator->getElementLimit();
	}
}
