<?php

if ( !defined( 'ABSPATH' ) ) {
    exit; // Exit if accessed directly
}

/**
 * Implements DateBook_WC_Subscription Class
 *
 * @class   DateBook_WC_Subscription
 * @package DateBook WooCommerce Subscription
 * @since   3.0
 */
if ( !class_exists( 'DateBook_WC_Subscription' ) ) {

    class DateBook_WC_Subscription {


        protected $subscription_meta_data = array(
            'status'                 => '',
            'start_date'             => '',
            'payment_due_date'       => '',
            'expired_date'           => '',
            'cancelled_date'         => '',
            'payed_order_list'       => array(),
            'product_id'             => '',
            'variation_id'           => '',
            'product_name'           => '',
            'quantity'               => '',
            'line_subtotal'          => '',
            'line_total'             => '',
            'line_subtotal_tax'      => '',
            'line_tax'               => '',
            'line_tax_data'          => '',

            'cart_discount'          => '',
            'cart_discount_tax'      => '',

            'order_total'            => '',
            'order_currency'         => '',
            'renew_order'            => '',

            'prices_include_tax'     => '',

            'payment_method'         => '',
            'payment_method_title'   => '',

            'subscriptions_shippings' => '',

            'price_is_per'           => '',
            'price_time_option'      => '',
            'max_length'             => '',

            'order_ids'              => array(),
            'order_id'               => '',
            'user_id'                => '',
            'customer_ip_address'    => '',
            'customer_user_agent'    => '',

            'billing_first_name'     => '',
            'billing_last_name'      => '',
            'billing_company'        => '',
            'billing_address_1'      => '',
            'billing_address_2'      => '',
            'billing_city'           => '',
            'billing_state'          => '',
            'billing_postcode'       => '',
            'billing_country'        => '',
            'billing_email'          => '',
            'billing_phone'          => '',

            'shipping_first_name'    => '',
            'shipping_last_name'     => '',
            'shipping_company'       => '',
            'shipping_address_1'     => '',
            'shipping_address_2'     => '',
            'shipping_city'          => '',
            'shipping_state'         => '',
            'shipping_postcode'      => '',
            'shipping_country'       => ''
        );

	    /**
	     * The subscription (post) ID.
	     *
	     */
	    public $id = 0;

	    /**
	     * @var string
	     */
	    public $price_time_option;

	    /**
	     * @var int
	     */
	    public $variation_id;

	    /**
	     * $post Stores post data
	     *
	     */
	    public $post = null;

	    /**
	     * $post Stores post data
	     *
	     */
	    public $status;


        /**
         * Constructor
         *
         */
        public function __construct( $subscription_id = 0, $args = array() ) {

            add_action( 'init', array( $this, 'register_post_type' ) );

	        //populate the subscription if $subscription_id is defined
	        if ( $subscription_id ) {
		        $this->id = $subscription_id;
		        $this->populate();
	        }

	        //add a new subscription if $args is passed
	        if ( $subscription_id == '' && ! empty( $args ) ) {
		        $this->add_subscription( $args );
	        }

        }


	    /**
	     * __get function.
	     *
	     */
	    public function __get( $key ) {
		    $value = get_post_meta( $this->id, $key, true );

		    if ( ! empty( $value ) ) {
			    $this->$key = $value;
		    }

		    return $value;
	    }


	    /**
	     * set function.
	     *
	     */
	    public function set( $property, $value ) {

		    $this->$property = $value;

		    return update_post_meta( $this->id, $property, $value );
	    }


	    /**
	     * get function.
	     *
	     */
	    public function get( $property ) {
		    return isset( $this->$property ) ? $this->$property : '';
	    }

	    public function __isset( $key ) {
		    if ( ! $this->id ) {
			    return false;
		    }

		    return metadata_exists( 'post', $this->id, $key );
	    }


	    /**
	     * Populate the subscription
	     *
	     */
	    public function populate() {

		    $this->post = get_post( $this->id );

		    foreach ( $this->get_subscription_meta() as $key => $value ) {
			    $this->$key = $value;
		    }

		    do_action( 'wcaddon_subscription_loaded', $this );
	    }


		/**
		 * First step. Add subscription in database. Pending
		 * 
		 * @access public
		 * @param $args
		 */
	    public function add_subscription( $args ) {

			global $current_user, $period_list_array;
			wp_get_current_user();
			$current_user_id = DateBook_Utilities::datebook_replace_user_by_admin($current_user->ID, 1);

			$subscription_id = wp_insert_post( array(
				'post_author' => $current_user_id,
                'post_status' => 'publish',
	            'post_type'   => 'datebook_subscribe',
            ) );

            if( $subscription_id ){
				$this->id = $subscription_id;
				$meta = apply_filters( 'wcaddon_add_subcription_args', wp_parse_args( $args, $this->get_default_meta_data() ), $this );
				$meta['user_id'] = $current_user_id;

				$this->update_subscription_meta( $meta );
				$this->populate();
				
				// Get Subscription plans
				$all_splans = get_option('datebook_subscription_plans');
				
				if (is_array($all_splans)){
					foreach($all_splans as $key => $value){
						if (isset($value['wc_subscription_product']) && $value['wc_subscription_product'] == $args['product_id']) {

							$subscription_plan_title = isset($value['name_' . DATEBOOK_WPLANG]) ? $value['name_' . DATEBOOK_WPLANG] : $value['name_en_US'];

							$subscription_recurring = isset($value['recurring']) && $value['recurring'] == 1 ? '1' : '0';
							
							$subscription_price = isset($args['line_total']) && $args['line_total'] > 0 ? $args['line_total'] : 0; // line_total

							// Calculate the Subscription plan period time
							$subscription_period_number_key = $args['price_is_per'];
							$subscription_period_key = $args['price_time_option'];
							$subscription_period_expiration = $subscription_period_number_key > 0 ? date('Y-m-d H:i:s', strtotime("+" . $subscription_period_number_key . " " . $subscription_period_key)) : '0000-00-00 00:00:00';

							if ($subscription_price > 0) {

								$subscription_status = 'pending';

								$payment_gateway = $args['payment_method'];

							} else {

								$subscription_status = 'completed';
								
								$payment_gateway = 'free';

							}

							$subscription_type = 'subscription_woocommerce_payment';

							// Get profile id
							$profile_id = get_user_meta( $current_user_id, 'profile_postid', true );

							// Detect if a subscription plan is free for selected genders
							$admin_activated = 0;
							if(isset($_POST['free_for_gender']) && $_POST['free_for_gender'] == 1) {
								$gender = get_post_meta($profile_id, 'gender', true);
								if(isset($all_splans[$get_splan]['free_for_gender'][$gender])){
									$admin_activated = 1;
								}
							} else if (isset($_POST['admin_activated']) && $_POST['admin_activated'] == 1 && is_super_admin()) {
								$admin_activated = 1;
							}

							$new_submitted_subscription = isset($value['subscription_id']) ? array(
								'subscription_id'	=> $value['subscription_id'],
								'plan_price_period'	=> 0,
								'plan'				=> $value['subscription_id'],
								'plan_title'		=> $subscription_plan_title,
								'price'				=> $subscription_price,
								'currency'			=> $args['order_currency'],
								//'recurring'			=> '0',
								'recurring'			=> $subscription_recurring,
								'status'			=> $subscription_status,
								'type'				=> $subscription_type,

								'date'				=> date('Y-m-d H:i:s', time()),

								'start_date'		=> date('Y-m-d H:i:s', time()),
								'expiration_date'	=> $subscription_period_expiration,

								'starts'			=> date('Y-m-d H:i:s', time()), 
								'ends'				=> $subscription_period_expiration,

								'profile_id'		=> $profile_id,
								'user_id'			=> $current_user_id,
								'payment_gateway'	=> $payment_gateway,
								'post_id'			=> $this->id,

								'period_number_key'	=> '',
								'period_key'		=> '',
								'payment_page'		=> '',
								
								'datebooktkn'		=> '',
								'admin_activated'	=> $admin_activated,
								'referrer'			=> 'woocommerce',

							) : array();

							do_action('datebook_insert_member_payments_data', $new_submitted_subscription);

						}
					}
				}

            }

			return $subscription_id;
        }


        /**
         * Update post meta in subscription
         *
         */
        function update_subscription_meta( $meta ){
            foreach( $meta as $key => $value ){
	            update_post_meta( $this->id, $key, $value);
            }
        }


	    /**
	     * @param $order_id
	     *
	     */
	    public function start_subscription($order_id) {

			$payed = $this->payed_order_list;
			
		    //do not nothing if this subscription has payed with this order
		    if ( ! empty( $payed ) && is_array( $payed ) && in_array( $order_id, $payed ) ) {
			    return;
		    }

		    $payed = empty( $payed ) ? array() : $payed;

		    $order = wc_get_order( $order_id );

		    $new_status  = 'active';
		    $rates_payed = 1;
		    if ( $this->start_date == '' ) {
			    $this->set( 'start_date', current_time('timestamp') );
		    }

		    if ( $this->payment_due_date == '' ) {
			    //Change the next payment_due_date
			    $this->set( 'payment_due_date', $this->get_next_payment_due_date( 0, $this->start_date ) );
		    }

		    if ( $this->expired_date == '' && $this->max_length != '' ) {
			    $timestamp = datebook_wc_get_timestamp_from_option( current_time('timestamp'), $this->max_length, $this->price_time_option );
			    $this->set( 'expired_date', $timestamp );
		    }

		    $this->set( 'status', $new_status );

		    do_action( 'wcaddon_customer_subscription_payment_done_mail', $this );

		    $payed[] = $order_id;

		    $this->set( 'rates_payed', $rates_payed );
		    $this->set( 'payed_order_list', $payed );

        }


        /**
         * Update the subscription if a payment is done manually from user
         *
         */
        public function update_subscription( $order_id ) {


            $payed = $this->payed_order_list;
            //do not nothing if this subscription has payed with this order
            if ( !empty( $payed ) && is_array( $payed ) && in_array( $order_id, $payed ) ) {
                return;
            }

            //Change the status to active
	        $this->set( 'status', 'active' );

            //Change the next payment_due_date
            $price_is_per      = $this->price_is_per;
            $price_time_option = $this->price_time_option;
            $timestamp         = datebook_wc_get_timestamp_from_option( current_time('timestamp'), $price_is_per, $price_time_option );

	        $this->set( 'payment_due_date', $timestamp );
            //update _payed_order_list
            $payed[] = $order_id;
	        $this->set( 'payed_order_list', $payed );
	        $this->set( 'renew_order', 0);

        }


	    /**
	     * @return array
	     *
	     */
	    function get_subscription_meta(  ) {
            $subscription_meta = array();
            foreach ( $this->get_default_meta_data() as $key => $value ) {
            	$meta_value = get_post_meta( $this->id, $key, true );
                $subscription_meta[$key] = empty($meta_value) ? get_post_meta( $this->id, '_'.$key, true ) : $meta_value;
            }

            return $subscription_meta;
        }


	    /**
	     * Return an array of all custom fields subscription
	     *
	     */
	    private function get_default_meta_data(){
		    return $this->subscription_meta_data;
	    }


	    function cancel_subscription(){


            //Change the status to active

            $this->set( 'status', 'cancelled' );
            $this->set( 'cancelled_date', date( "Y-m-d H:i:s" ) );

            do_action('wcaddon_subscription_cancelled', $this->id);

            //if there's a pending order for this subscription change the status of the order to cancelled
            $order_in_pending = $this->renew_order;
            if( $order_in_pending ){
                $order = wc_get_order( $order_in_pending );
                if( $order ){
                    $order->update_status('failed');
                }
            }

        }


	    /**
	     * Return the next payment due date if there are rates not payed
	     *
	     */
	    public function get_next_payment_due_date( $trial_period = 0, $start_date = 0) {

		    $start_date = ( $start_date ) ? $start_date : current_time('timestamp');
		    if ( $this->num_of_rates == '' || ( intval( $this->num_of_rates ) - intval( $this->rates_payed ) ) > 0 ) {
			    $payment_due_date = ( $this->payment_due_date == '' ) ?  $start_date : $this->payment_due_date;
			    if( $trial_period != 0){
				    $timestamp = $start_date + $trial_period;
			    }else{
				    $timestamp = datebook_wc_get_timestamp_from_option( $payment_due_date, $this->price_is_per, $this->price_time_option );
			    }

			    return $timestamp;
		    }

		    return false;

	    }


	    /**
	     * Get the order object.
	     *
	     */
	    public function get_order(){
		    $this->order =  ( $this->order instanceof WC_Order ) ? $this->order : wc_get_order( $this->_order_id );

		    return $this->order;
	    }

	    /**
	     * Get billing customer email
	     *
	     */
	    public function get_billing_email() {
		    $billing_email = ! empty( $this->_billing_email ) ? $this->_billing_email : datebook_get_prop( $this->get_order(), '_billing_email');
		    return apply_filters( 'wcaddon_customer_billing_email', $billing_email, $this );
	    }

	    /**
	     * Get billing customer email
	     *
	     */
	    public function get_billing_phone() {
		    $billing_phone = ! empty( $this->_billing_phone ) ? $this->_billing_phone : datebook_get_prop( $this->get_order(), '_billing_phone' );
		    return apply_filters( 'wcaddon_customer_billing_phone', $billing_phone, $this );
	    }

	    /**
	     * Get subscription customer billing or shipping fields.
	     *
	     */
	    public function get_address_fields( $type = 'billing', $no_type = false, $prefix = '' ) {

		    $fields = array();

		    $value_to_check = '_'.$type.'_first_name';
		    if( ! isset( $this->$value_to_check ) ){
			    $fields = $this->get_address_fields_from_order( $type, $no_type, $prefix );
		    }else{
			    $order = $this->get_order();
			    $meta_fields = $order->get_address( $type );

			    foreach ( $meta_fields as $key => $value ) {
				    $field_name           = '_' . $type . '_' . $key;
				    $field_key            = $no_type ? $key : $type . '_' . $key;
				    $fields[ $prefix.$field_key ] = $this->$field_name;
			    }
		    }

		    return $fields;
	    }

	    /**
	     * Return the fields billing or shipping of the parent order
	     *
	     */
	    public function get_address_fields_from_order( $type = 'billing', $no_type = false, $prefix = '' ) {
		    $fields = array();
		    $order  = $this->get_order();
		    if ( $order ) {
			    $meta_fields = $order->get_address( $type );

			    if ( is_array( $meta_fields ) ) {
				    foreach ( $meta_fields as $key => $value ) {
					    $field_key            = $no_type ? $key : $type . '_' . $key;
					    $fields[ $prefix.$field_key ] = $value;
				    }
			    }
		    }

		    return $fields;
	    }

	    /**
	     * Return if the subscription can be cancelled by user
	     *
	     */
	    public function can_be_cancelled() {
		    $status = array( 'pending', 'cancelled' );

		    //the administrator and shop manager can switch the status to cancelled
		    $post_type_object = get_post_type_object( DateBook_WC_Start()->post_name );
		    if ( current_user_can( $post_type_object->cap->delete_post, $this->ID ) ) {
			    $return = true;
		    } else if ( ! in_array( $this->status, $status ) && get_option( 'wcaddon_allow_customer_cancel_subscription' ) == 'yes' ) {
			    $return = true;
		    } else {
			    $return = false;
		    }

		    return apply_filters( 'wcaddon_can_be_cancelled', $return, $this );
	    }

	    /**
	     * Return if the subscription can be reactivate by user
	     *
	     */
	    public function can_be_create_a_renew_order() {
		    $status = array( 'pending', 'expired' );

		    // exit if no valid subscription status
		    if ( in_array( $this->status, $status ) || $this->payment_due_date == $this->expired_date ) {
			    return false;
		    }

		    //check if the subscription have a renew order
		    $renew_order = $this->has_a_renew_order();

		    // if order doesn't exist, or is cancelled, we create order
		    if ( ! $renew_order || ( $renew_order && ( $renew_order->get_status() == 'cancelled' ) ) ) {
			    $result = true;
		    } // otherwise we return order id
		    else {
			    $result =  datebook_get_order_id( $renew_order );
		    }

		    return apply_filters( 'wcaddon_can_be_create_a_renew_order', $result, $this );
	    }

	    /**
	     * Return the renew order if exists
	     *
	     */
	    public function has_a_renew_order() {

		    $return         = false;
		    $renew_order_id = $this->renew_order;

		    if ( $renew_order_id ) {
			    $order = wc_get_order( $renew_order_id );
			    $order && $return = $order;
		    }

		    return $return;
	    }

	    /**
	     * Add failed attemp
	     *
	     */
	    public function register_failed_attemp( $attempts = false, $latest_attemp = false ) {

		    $order = wc_get_order( $this->order_id );

		    if ( false === $attempts ) {
			    $failed_attemp = datebook_get_prop( $order, 'failed_attemps' );
			    $attempts      = intval( $failed_attemp ) + 1;
		    }

		    if ( ! $latest_attemp ) {
			    datebook_save_prop( $order, 'failed_attemps', $attempts, false, true );
			    do_action( 'wcaddon_customer_subscription_payment_failed_mail', $this );
		    }
	    }


    }

}