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

use SabaiApps\Directories\Application;
use SabaiApps\Directories\Component\Entity\Type\IEntity;
use SabaiApps\Directories\Component\Payment\IOrder;
use SabaiApps\Directories\Component\Payment\ISubscription;
use SabaiApps\Directories\Exception;

class UtilHelper {

	public function actionLabel( Application $application, $action, $wasDeactivated = false ) {
		switch ( $action ) {
			case 'upgrade':
				return __( 'Upgrade / Downgrade', 'directories-pro' );
			case 'renew':
				return __( 'Renewal', 'directories-pro' );
			case 'order_addon':
				return __( 'Order Add-on', 'directories-pro' );
			case 'resubscribe':
				return __( 'Resubscribe', 'directories-pro' );
			case 'claim':
				return __( 'Claim', 'directories-pro' );
			default:
				return $wasDeactivated ? __( 'Re-activation', 'directories-pro' ) : __( 'Initial Post', 'directories-pro' );
		}
	}

	public function hasPendingOrder( Application $application, IEntity $entity, ?array $actions = null ) {
		if ( ! $payment_component = $application->getComponent( 'Payment' )->getPaymentComponent() ) {
			return false;
		}

		return $payment_component->paymentHasPendingOrder( $entity, isset( $actions ) ? $actions : array( 'add', 'submit', 'renew', 'upgrade', 'order_addon' ) );
	}

	public function isSuspended( Application $application, IEntity $entity ) {
		$application->Entity_Field_load( $entity );
		$entity_plan_extra_data = $entity->getSingleFieldValue( 'payment_plan', 'extra_data' );
		return ! empty( $entity_plan_extra_data['suspended_at'] );
	}

	public function handleExpired( Application $application, $entityType, array $entities, $action = null ) {
		if ( empty( $entities ) ) {
			return;
		}

		if ( $entityType === 'user' ) {
			$action = 'no_plan';
		}
		if ( ! isset( $action ) ) {
			$action = $application->getComponent( 'Payment' )->getConfig( 'plan', 'expired_action' );
		}
		switch ( $action ) {
			case 'trash':
				$values           = array();
				$values['status'] = $application->Entity_Status( $entityType, 'trash' );
				$msg              = 'Trashed item: %s (ID: %d)';
				$this->_unapplyEntityFeatures( $application, $entities, $values, $msg );
				break;
			case 'draft':
				$values           = array();
				$values['status'] = $application->Entity_Status( $entityType, 'draft' );
				$msg              = 'Marked draft: %s (ID: %d)';
				$this->_unapplyEntityFeatures( $application, $entities, $values, $msg );
				break;
			case 'no_plan':
			case 'no_plan_author':
				$values = array( 'payment_plan' => false );
				if ( $action === 'no_plan' ) {
					$msg = 'Unassigned payment plan from item: %s (ID: %d)';
				} else {
					$values['author'] = false;
					$msg              = 'Unassigned payment plan and author from item: %s (ID: %d)';
				}
				$this->_unapplyEntityFeatures( $application, $entities, $values, $msg );
				break;
			case 'none':
				break;
			default:
				if ( defined( 'DRTS_PAYMENT_NO_DEACTIVATION' ) && DRTS_PAYMENT_NO_DEACTIVATION ) {
					break;
				}

				$values = array( 'payment_plan' => array( 'deactivated_at' => time() ) );
				if ( $status = $application->Filter( 'payment_entities_deactivated_status', 'draft', array( $entityType, $entities ) ) ) {
					$values['status'] = $application->Entity_Status( $entityType, $status );
				}
				$msg = 'Marked draft and deactivated: %s (ID: %d)';
				$this->_unapplyEntityFeatures( $application, $entities, $values, $msg );
		}
		$application->Action( 'payment_expired_entities_handled', array( $entityType, $entities, $action ) );
	}

	protected function _unapplyEntityFeatures( Application $application, array $entities, array $values = array(), $msg = null ) {
		foreach ( array_keys( $entities ) as $entity_id ) {
			try {
				$application->Payment_Features_unapply( $entities[ $entity_id ], null, $values );
			} catch ( Exception\IException $e ) {
				$application->logError( $e );
				continue;
			}
			if ( isset( $msg ) ) {
				$application->logNotice( sprintf( $msg, $entities[ $entity_id ]->getTitle(), $entity_id ) );
			}
		}
	}

	public function suspendEntities( Application $application, $entityType, array $entities, array $values = array(), ?array &$logs = null ) {
		if ( empty( $entities ) ) {
			return;
		}

		$values['status'] = $application->Entity_Status( $entityType, 'draft' );
		foreach ( array_keys( $entities ) as $entity_id ) {
			try {
				$values['payment_plan'] = array(
					'suspended_at'     => time(),
					'suspended_status' => $entities[ $entity_id ]->getStatus(),
				);
				$application->Entity_Save( $entities[ $entity_id ], $values );
			} catch ( Exception\IException $e ) {
				if ( isset( $logs ) ) {
					$logs['error'][] = $e->getMessage();
				} else {
					$application->logError( $e );
				}
				continue;
			}

			// Suspend translated entities
			foreach ( $application->Entity_Translations( $entities[ $entity_id ], false ) as $translated_entity ) {
				try {
					$application->Entity_Save( $translated_entity, $values );
				} catch ( Exception\IException $e ) {
					if ( isset( $logs ) ) {
						$logs['error'][] = $e->getMessage();
					} else {
						$application->logError( $e );
					}
					continue;
				}
			}

			if ( isset( $logs ) ) {
				$logs['success'][] = sprintf( 'Suspended item: %s (ID: %d)', $entities[ $entity_id ]->getTitle(), $entity_id );
			}
		}
	}

	public function unsuspendEntities( Application $application, $entityType, array $entities, ?array &$logs = null ) {
		if ( empty( $entities ) ) {
			return;
		}

		$default_status = $application->Entity_Status( $entityType, 'publish' );
		foreach ( array_keys( $entities ) as $entity_id ) {
			try {
				$values = array(
					'status'       => $default_status,
					'payment_plan' => array( 'suspended_at' => 0 ),
				);
				if ( ( $current_payment_plan = $entities[ $entity_id ]->getSingleFieldValue( 'payment_plan' ) )
					&& ! empty( $current_payment_plan['extra_data']['suspended_status'] )
				) {
					$values['status'] = $current_payment_plan['extra_data']['suspended_status'];
				}
				$application->Entity_Save( $entities[ $entity_id ], $values );
			} catch ( Exception\IException $e ) {
				if ( isset( $logs ) ) {
					$logs['error'][] = $e->getMessage();
				} else {
					$application->logError( $e );
				}
				continue;
			}

			// Unsuspend translated entities
			foreach ( $application->Entity_Translations( $entities[ $entity_id ], false ) as $translated_entity ) {
				try {
					$application->Entity_Save( $translated_entity, $values );
				} catch ( Exception\IException $e ) {
					if ( isset( $logs ) ) {
						$logs['error'][] = $e->getMessage();
					} else {
						$application->logError( $e );
					}
					continue;
				}
			}

			if ( isset( $logs ) ) {
				$logs['success'][] = sprintf( 'Unsuspended item: %s (ID: %d)', $entities[ $entity_id ]->getTitle(), $entity_id );
			}
		}
	}

	public function triggerOrderEvent( Application $application, $name, IOrder $order ) {
		$application->Action( 'payment_order_' . $name, array( $order ) );
	}

	public function triggerSubscriptionEvent( Application $application, $name, ISubscription $subscription ) {
		$application->Action( 'payment_subscription_' . $name, array( $subscription ) );
	}
}
