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

use SabaiApps\Directories\Component\Entity\Model\Bundle;
use SabaiApps\Directories\Component\System\Tool\AbstractTool;
use SabaiApps\Directories\Context;
use SabaiApps\Directories\Exception;

class ReassignPaymentPlansSystemTool extends AbstractTool {

	protected function _systemToolInfo() {
		return array(
			'label'       => __( 'Reassign payment plans', 'directories-pro' ),
			'description' => __( 'This tool lets you reassign payment plans to content items that currently have inactive payment plans assigned.', 'directories-pro' ),
			'weight'      => 60,
		);
	}

	public function systemToolSettingsForm( $step, array $values, array $parents = array(), ?Context $context = null ) {
		$current_payment_component = $this->_application->getComponent( 'Payment' )->getPaymentComponent( true );
		$options                   = $plans = array();
		foreach ( $this->_application->Entity_Bundles() as $bundle ) {
			if ( empty( $bundle->info['payment_enable'] )
				|| ( ! $field = $this->_application->Entity_Field( $bundle, 'payment_plan' ) )
			) {
				continue;
			}

			$options[ $bundle->name ] = $bundle->getGroupLabel() . ' - ' . $bundle->getLabel( 'singular' );
		}
		foreach ( array_keys( $this->_application->Payment_Components() ) as $payment_component_name ) {
			if ( $payment_component_name === $current_payment_component->paymentComponentName() ) {
				continue;
			}

			$payment_component = $this->_application->Payment_Components_Impl( $payment_component_name );
			if ( ! $payment_component->paymentIsEnabled() ) {
				continue;
			}

			$payment_component_label = $payment_component->paymentComponentInfo( 'label' );
			foreach ( array_keys( $options ) as $bundle_name ) {
				foreach ( $payment_component->paymentGetPlanIds( $bundle_name ) as $plan_id ) {
					if ( $plan = $payment_component->paymentGetPlanById( $bundle_name, $plan_id ) ) {
						if ( $plan->paymentPlanType() !== 'base'
							|| ( ! $bundle = $this->_application->Entity_Bundle( $bundle_name ) )
							|| ( ! $count = $this->_queryItems( $bundle, $plan_id, $payment_component_name )->count() )
						) {
							continue;
						}

						$plan_label = $plan->paymentPlanTitle();
						if ( $payment_component_name !== $current_payment_component->paymentComponentName() ) {
							$plan_label = $payment_component_label . ' - ' . $plan_label;
						}
						$plans[ $bundle_name ][ $payment_component_name ][ $plan_id ] = $plan_label . ' (' . $this->_application->H( sprintf( _n( $bundle->getLabel( 'count' ), $bundle->getLabel( 'count2' ), $count, 'directories-pro' ), $count ) ) . ')';
					}
				}
				if ( empty( $plans[ $bundle_name ] ) ) {
					unset( $options[ $bundle_name ] );
				}
			}
		}
		if ( empty( $options )
			|| empty( $plans )
		) {
			return false;
		}

		$form = array(
			'bundle' => array(
				'#title'      => __( 'Select content type', 'directories-pro' ),
				'#type'       => 'select',
				'#options'    => $options,
				'#horizontal' => true,
				'#required'   => true,
			),
		);
		foreach ( array_keys( $plans ) as $bundle_name ) {
			$current_plans = array( '' => __( '— Select —', 'directories-pro' ) );
			foreach ( $current_payment_component->paymentGetPlanIds( $bundle_name ) as $plan_id ) {
				if ( ( ! $plan = $current_payment_component->paymentGetPlanById( $bundle_name, $plan_id ) )
					|| $plan->paymentPlanType() !== 'base'
				) {
					continue;
				}

				$current_plans[ $plan_id ] = $plan->paymentPlanTitle();
			}
			$form[ $bundle_name ] = array(
				'#title'      => __( 'Select new payment plan', 'directories-pro' ),
				'#horizontal' => true,
				'#states'     => array(
					'visible' => array(
						sprintf( 'select[name="%s"]', $this->_application->Form_Form_fieldName( array( $parents, 'bundle' ) ) ) => array( 'value' => $bundle_name ),
					),
				),
			);
			foreach ( array_keys( $plans[ $bundle_name ] ) as $payment_component_name ) {
				foreach ( array_keys( $plans[ $bundle_name ][ $payment_component_name ] ) as $plan_id ) {
					$form[ $bundle_name ][ $plan_id . '-' . $payment_component_name ] = array(
						'#type'       => 'select',
						'#title'      => $plans[ $bundle_name ][ $payment_component_name ][ $plan_id ],
						'#options'    => $current_plans,
						'#horizontal' => true,
					);
				}
			}
		}

		return $form;
	}

	protected function _queryItems( Bundle $bundle, $planId, $paymentComponent ) {
		$query = $this->_application->Entity_Query( $bundle->entitytype_name )
			->fieldIs( 'bundle_name', $bundle->name )
			->fieldIs( 'payment_plan', $planId, 'plan_id' );
		if ( $paymentComponent === 'woocommerce' ) {
			$query->fieldIsIn( 'payment_plan', array( $paymentComponent, '' ), 'component' );
		} else {
			$query->fieldIs( 'payment_plan', $paymentComponent, 'component' );
		}
		return $query;
	}

	public function systemToolInit( array $settings, array &$storage, array &$logs, ?Context $context = null ) {
		$ret = array();
		foreach ( array_keys( $settings ) as $bundle_name ) {
			if ( $bundle_name === 'bundle'
				|| $bundle_name !== $settings['bundle']
				|| ( ! $bundle = $this->_application->Entity_Bundle( $bundle_name ) )
			) {
				continue;
			}

			foreach ( array_keys( $settings[ $bundle_name ] ) as $plan_key ) {
				if ( empty( $settings[ $bundle_name ][ $plan_key ] ) ) {
					continue;
				}

				list($plan_id, $payment_component_name) = explode( '-', $plan_key );
				$ret[ $bundle_name . '-' . $plan_key ]  = $this->_queryItems( $bundle, $plan_id, $payment_component_name )->count();
			}
		}

		return $ret;
	}

	public function systemToolRunTask( $task, array $settings, $iteration, $total, array &$storage, array &$logs, ?Context $context = null ) {
		list($bundle_name, $plan_id, $payment_component_name) = explode( '-', $task );
		if ( ! $bundle = $this->_application->Entity_Bundle( $bundle_name ) ) {
			return false;
		}

		$current_payment_component_name = $this->_application->getComponent( 'Payment' )->getPaymentComponent( true, true );
		$paginator                      = $this->_queryItems( $bundle, $plan_id, $payment_component_name )
			->sortById()
			->paginate( 20, 0 )
			->setCurrentPage( $iteration );
		$new_plan_id                    = $settings[ $bundle_name ][ $plan_id . '-' . $payment_component_name ];
		foreach ( $paginator->getElements() as $entity ) {
			try {
				$this->_application->Entity_Save(
					$entity,
					array(
						'payment_plan' => array(
							'plan_id'   => $new_plan_id,
							'component' => $current_payment_component_name,
						),
					)
				);
			} catch ( Exception\IException $e ) {
				$logs['error'][] = $e->getMessage();
			}
		}

		// Add success log
		$offset            = $paginator->getElementOffset();
		$logs['success'][] = sprintf(
			'Payment plan (ID: %d) reassigned for %s (%d - %d)',
			$new_plan_id,
			$bundle->getGroupLabel() . ' - ' . $bundle->getLabel(),
			$offset + 1,
			$offset + $paginator->getElementLimit()
		);

		return $paginator->getElementLimit();
	}
}
