<?php namespace MeowCrew\CancellationOffers\Frontend\OfferPopup\Actions;

use MeowCrew\CancellationOffers\SurveyAnswers\SurveyAnswer;
use WC_Subscription;
use Exception;
use WC_Coupon;
use WP_Error;

/**
 * Class TakeDiscountAction
 *
 * @package MeowCrew\CancellationOffers\Frontend\Actions
 */
class TakeDiscountAction extends PopupActionAbstract {
	
	const ACTION_NAME = 'cos_take_discount';
	
	public function run() {
		
		try {
			$this->validateRequest();
			
			$subscription    = $this->getSubscription();
			$offerEntity     = $this->getOffer();
			$user            = $this->getUser();
			$surveyItemTitle = $this->getSurveyTitle();
			$surveyText      = $this->getSurveyText();
			
			$offerIndex    = isset( $_GET['offer_index'] ) ? intval( $_GET['offer_index'] ) : 0;
			$discountOffer = $offerEntity->getOfferByIdOrIndex( $offerIndex );
			
			if ( ! $discountOffer ) {
				throw new Exception( 'Invalid offer index' );
			}
			
			$surveyAnswerInstance = new SurveyAnswer( $offerEntity->getId(), $subscription->get_id(), $user->ID,
				$offerEntity->getSurvey()->isEnabled(), $surveyItemTitle, $surveyText, $discountOffer->isEnabled(),
				true, null );
			
			if ( $discountOffer->getOfferType() === 'coupon' ) {
				$coupon = new WC_Coupon( $discountOffer->getCouponId() );
				
				$this->applyCouponDiscount( $coupon, $subscription );
				
				$surveyAnswerInstance->setCouponId( $coupon->get_id() );
				
			} elseif ( $discountOffer->getOfferType() === 'skip_renewal' ) {
				$this->applySkipNextRenewal( $subscription );
				
				$surveyAnswerInstance->setCouponId( - 1 );
			}
			
			$subscription->add_meta_data( '_cos_offer_discount_applied', $this->getOffer()->getId(), true );
			$subscription->save();
			
			$surveyAnswerInstance->save();
			
		} catch ( Exception $e ) {
			wc_add_notice( $e->getMessage(), 'error' );
			wp_die();
		}
	}
	
	protected function applyCouponDiscount( WC_Coupon $coupon, WC_Subscription $subscription ) {
		$subscription = $this->getSubscription();
		
		$result = $subscription->apply_coupon( $coupon );
		
		if ( $result instanceof WP_Error ) {
			throw new Exception( esc_html( $result->get_error_message() ) );
		}
		
		// translators: %s: coupon code
		$subscription->add_order_note( sprintf( __( 'Subscription retention achieved through discount offer (%s)',
			'cancellation-surveys-offers-woocommerce-subscriptions' ), $coupon->get_code() ) );
		
		wc_add_notice( __( 'Discount has been applied', 'cancellation-surveys-offers-woocommerce-subscriptions' ) );
		
		$subscription->add_meta_data( '_cos_offer_discount_applied', $this->getOffer()->getId(), true );
		$subscription->save();
	}
	
	/**
	 * Skip next renewal
	 *
	 * @param  WC_Subscription  $subscription
	 *
	 * @throws Exception
	 */
	protected function applySkipNextRenewal( WC_Subscription $subscription ) {
		$currentNextPaymentDate = $this->getSubscription()->get_date( 'next_payment' );
		
		if ( ! $currentNextPaymentDate ) {
			throw new Exception( esc_html__( 'Next payment date is not set',
				'cancellation-surveys-offers-woocommerce-subscriptions' ) );
		}
		
		$currentNextPaymentDateTimestamp = strtotime( $currentNextPaymentDate );
		
		// Add one billing period to the next payment date
		$newNextPaymentDate = wcs_add_time( $subscription->get_billing_interval(), $subscription->get_billing_period(),
			$currentNextPaymentDateTimestamp, 'offset_site_time' );
		
		$subscription->update_dates( array(
			'next_payment' => gmdate( 'Y-m-d H:i:s', $newNextPaymentDate ),
		) );
		
		$subscription->add_order_note( __( 'Subscription retention achieved through skipping renewal',
			'cancellation-surveys-offers-woocommerce-subscriptions' ) );
		
		wc_add_notice( __( 'Next renewal date is updated to ',
				'cancellation-surveys-offers-woocommerce-subscriptions' ) . date_i18n( wc_date_format(),
				$newNextPaymentDate ) );
	}
	
	public function getActionName(): string {
		return self::ACTION_NAME;
	}
}
