<?php

namespace WooPoPCozmosLabsPMS\Providers;

use WcElectronInvoice\Providers\DateTimeProvider;

defined( 'ABSPATH' ) || die( 'Not allowed.' );

class Order extends \WcElectronInvoice\Providers\Order {

	/**
	 * @var \PMS_Payment
	 *
	 */
	protected $order;

	function set_order( $order ) {
		$this->order = $order;
	}

	function get_id() {
		return $this->order->id;
	}

	function set_id() {
		$this->id = $this->order->id;
	}

	function set_payment_method() {
		$this->payment_method = $this->get_payment_method();
	}

	function get_provider() {
		return $this->provider->name();
	}

	function get_provider_label() {
		return $this->provider->get_label();
	}

	function set_data() {
		$this->data = $this->order->get_data( $this->get_id() );
	}

	function get_data() {

		$data = $this->order->get_data( $this->id );

		$data['id']             = (int) $this->get_id();
		$data['parent_id']      = (int) $this->get_parent_id();
		$data['status']         = $this->get_status();

		$data['date_created']   = $data['date'];
		$data['date_modified']  = $this->get_date_modified();
		$data['date_completed'] = $this->get_date_completed();

		$data['billing']        = $this->get_billing_data();
		$data['provider']       = $this->get_provider();
		$data['provider_label'] = $this->get_provider_label();
		$data['order_type']     = $this->get_type();

		// currency
		$data['currency']        = $this->get_currency();
		$data['currency_symbol'] = $this->get_currency_symbol( $data['currency'] );

		// customer user agent
		$data['customer_user_agent'] = '';

		// customer order note
		$data['customer_note'] = '';

		// payment method
		$data['payment_method']       = $this->get_payment_method();
		$data['payment_method_title'] = $this->get_payment_method();

		// shipping
		$data['shipping_total'] = $this->get_shipping_total();
		$data['shipping_tax']   = $this->get_shipping_tax();
		$data['shipping']       = [];

		// total
		$data['total'] = $this->get_total();

		// discount and discount tax
		$data['discount_total'] = $this->get_discount_total();
		$data['discount_tax']   = $this->get_discount_tax();

		// cart tax
		$data['cart_tax'] = $this->get_cart_tax();

		// total tax
		$data['total_tax'] = $this->get_total_tax();
		$data['taxes']     = array(
			'total'    => array(
				$this->get_total_tax()
			),
			'subtotal' => array(
				$this->get_total_tax()
			)
		);

		// create via
		$data['created_via'] = '';

		// payment completed
		$data['date_paid'] = $this->get_date_completed();

		return $data;
	}

	function get_meta( $key, $single = true ) {

		switch ( $key ) {
			case '_billing_choice_type':
				return $this->get_billing_choice_type();
			default:
				return pms_get_payment_meta( $this->id, $key, $single );
		}

	}

	function update_meta( $key, $value ){
		return pms_update_payment_meta( $this->id, $key, $value );
	}

	function delete_meta( $key ) {
		return pms_delete_payment_meta( $this->id, $key );
	}

	function get_total() {
		return $this->order->amount;
	}

	function get_total_refunded() {
		$status = $this->get_status();
		switch ( $status ) {
			case 'completed':
			case 'pending':
				return 0;
			case 'refunded':
				return $this->get_total();
		}
	}

	function get_refunds() {
		// TODO: Implement get_refunds() method.
	}

	function get_remaining_refund_amount() {
		$payment_status = $this->order->status;
		switch ( $payment_status ) {
			case 'completed':
			case 'pending':
				return $this->get_total();
			case 'refunded':
				return 0;
		}
	}

	function get_remaining_refund_items() {

		$status = $this->get_status();
		switch ( $status ) {
			case 'completed':
			case 'pending':
				return 1;
			case 'refunded':
				return 0;
		}

	}

	function get_refund_payment_method() {
		$refund_payment_method = $this->order->payment_gateway;

		switch ( $refund_payment_method ) {
			case 'stripe':
				return 'stripe';
			case 'paypal':
			case 'paypal_standard':
				return 'paypal';
			case 'bank_transfer':
				return 'bank_transfer';
			case 'cash':
				return 'cash';
			case 'manual':
				return 'manual';
			default:
				return 'unknown';
		}
	}

	function get_total_qty_refunded() {
		$status = $this->get_status();
		switch ( $status ) {
			case 'completed':
			case 'pending':
				return 0;
			case 'refunded':
				return 1;
		}
	}

	function get_qty_refunded_for_item() {
		// always return 1, because we can't refund a subscription plan partially
		// or more than one subscription plan in a single payment
		return 1;
	}

	function get_total_refunded_for_item( $item_id, $item_type ) {
		return $this->order->amount;
	}

	function get_tax_refunded_for_item( $item_id, $item_type ) {
		// taxes for a subscription item is the total tax
		return $this->get_total_tax();
	}

	function get_parent_id() {
		return $this->order->id;
	}

	private function get_billing_data() {

		$billing_data = [];

		// pms meta, user meta fallback
		$billing_map = [
			'first_name'   => [
				'pms'        => 'pms_billing_first_name',
				'user_meta'  => 'first_name',
				'user_field' => false
			],
			'last_name'    => [
				'pms'        => 'pms_billing_last_name',
				'user_meta'  => 'last_name',
				'user_field' => false
			],
			'email'        => [
				'pms'        => 'pms_billing_email',
				'user_meta'  => false,
				'user_field' => 'user_email'
			],
			'company'      => [
				'pms'        => 'pms_billing_company',
				'user_meta'  => false,
				'user_field' => false
			],
			'address_1'    => [
				'pms'        => 'pms_billing_address',
				'user_meta'  => false,
				'user_field' => false
			],
			'city'         => [
				'pms'        => 'pms_billing_city',
				'user_meta'  => false,
				'user_field' => false
			],
			'state'        => [
				'pms'        => 'pms_billing_state',
				'user_meta'  => false,
				'user_field' => false
			],
			'postcode'    => [
				'pms'        => 'pms_billing_zip',
				'user_meta'  => false,
				'user_field' => false
			],
			'country'      => [
				'pms'        => 'pms_billing_country',
				'user_meta'  => false,
				'user_field' => false
			],
			'vat_number'   => [
				'pms'        => 'pms_vat_number',
				'user_meta'  => false,
				'user_field' => false
			],
			'tax_code'   => [
				'pms'        => 'pms_tax_code',
				'user_meta'  => false,
				'user_field' => false
			],
			'choice_type'  => [
				'pms'        => 'pms_choice_type',
				'user_meta'  => false,
				'user_field' => false
			],
			'invoice_type' => [
				'pms'        => 'pms_invoice_type',
				'user_meta'  => false,
				'user_field' => false
			],
			'sdi_type'     => [
				'pms'        => 'pms_sdi_type',
				'user_meta'  => false,
				'user_field' => false
			],
		];

		$user_id = $this->get_user_id();
		foreach ( $billing_map as $key => $map ) {

			if ( empty( $billing_data[ $key ] ) && isset( $map['pms'] ) ) {
				$billing_data[ $key ] = pms_get_payment_meta( $this->id, $map['pms'], true );
			}

			if ( empty( $billing_data[ $key ] ) && $map['user_meta'] ) {
				$billing_data[ $key ] = get_user_meta( $user_id, $map['user_meta'], true );
			}


			if ( empty( $billing_data[ $key ] ) && $map['user_field'] ) {
				$user_data            = (array) get_userdata( $user_id );
				$billing_data[ $key ] = isset( $user_data[ $map['user_field'] ] ) ? $user_data[ $map['user_field'] ] : '';
			}

		}

		return $billing_data;

	}

	function get_billing_choice_type() {
		$billing_choice_type = pms_get_payment_meta( $this->id, 'pms_choice_type', true );

		return ! empty( $billing_choice_type ) ? $billing_choice_type : 'invoice';
	}

	function get_billing_first_name(){
		return $this->get_billing_data()['first_name'];
	}

	function get_billing_last_name(){
		return $this->get_billing_data()['last_name'];
	}

	function get_billing_company(){
		return $this->get_billing_data()['company'];
	}

	function get_billing_email(){
		return $this->get_billing_data()['email'];
	}

	function get_billing_phone(){
		// PMS doesn't have phone field
		return '';
	}

	function get_billing_address_1(){
		return $this->get_billing_data()['address_1'];
	}

	function get_billing_postcode(){
		return $this->get_billing_data()['postcode'];
	}

	function get_billing_country() {
		return $this->get_billing_data()['country'];
	}

	function get_billing_city() {
		return $this->get_billing_data()['city'];
	}

	function get_billing_state() {
		return $this->get_billing_data()['state'];
	}

	function get_user_id() {
		return (int) $this->order->user_id;
	}

	/**
	 * @return string shop_order or shop_order_refund (to distinguish between order and refund)
	 */
	function get_type() {
		switch ( $this->order->type ) {
			case 'subscription_initial_payment':
				return 'shop_order';
			case 'manual_payment':
				return 'shop_order';
			default:
				return 'shop_order';
		}

	}

	function get_type_label( $type ) {

		switch ( $type ) {
			case 'subscription_initial_payment':
				return __( 'Initial Payment', WC_EL_INV_TEXTDOMAIN );
			case 'manual_payment':
				return __( 'Manual Payment', WC_EL_INV_TEXTDOMAIN );
			default:
				return __( 'Payment', WC_EL_INV_TEXTDOMAIN );
		}

	}

	function get_items( $type = 'line_item' ) {
		$items = array();

		switch ( $type ) {
			case 'line_item':
                // tax not include
                $unitPrice = $this->get_total() - $this->get_total_tax();
				// get subscription id
				$subscription                        = new SubscriptionPlanDecorator( $this->order->subscription_id );
				$subscription->price                 = $unitPrice;
				$subscription->total_tax             = $this->get_total_tax();
				$subscription->qty_refunded_for_item = 0;
				$subscription->order_id              = $this->get_id();
				$items[]                             = new OrderItem( $subscription );
				break;
			case 'fee':

				break;
			case 'shipping':
				// no shipping for digital subscription
				break;
			case 'tax':
				$items[] = new TaxOrderItem( $this->order );
				break;
			case 'coupon':
				// TODO: Implement data for coupon?
				break;
		}


		return $items;
	}

    function get_invoice_sent($order_id = '')
    {
	    $order_id = $order_id ?: $this->id;
        $value    = pms_get_payment_meta($order_id, 'pms_invoice_sent', true);
        if (is_bool($value)) {
            return $value ? 'sent' : 'no_sent';
        }

        return $value;
    }

	function get_invoice_sent_timestamp( $order_id = '' ) {
        $order_id = empty( $order_id ) ? $this->id : $order_id;
		return pms_get_payment_meta( $order_id, 'pms_invoice_timestamp', true );
	}

	function set_invoice_sent( $sent, $order_id = '' ) {
        $order_id = empty( $order_id ) ? $this->id : $order_id;
		return pms_update_payment_meta( $order_id, 'pms_invoice_sent', $sent );
	}

	function set_invoice_sent_timestamp( $timestamp, $order_id = '' ) {
		$order_id = empty( $order_id ) ? $this->id : $order_id;
		pms_update_payment_meta( $order_id, 'pms_invoice_timestamp', $timestamp );
	}

	function get_invoice_type() {
		return pms_get_payment_meta( $this->id, 'pms_invoice_type', true );
	}

	function get_billing_tax_code() {
		return pms_get_payment_meta( $this->id, 'pms_tax_code', true );
	}

	function get_sdi_type() {
		return pms_get_payment_meta( $this->id, 'pms_sdi_type', true );
	}

	function get_vat_number() {
		return pms_get_payment_meta( $this->id, 'pms_vat_number', true );
	}

    function get_order_number_invoice()
    {
        $number     = $this->get_meta('order_number_invoice');
        $pms_number = pms_get_payment_meta($this->id, 'pms_inv_invoice_number', true);
        if ($pms_number && '' !== $pms_number && ! $number) {
            return $pms_number;
        } else {
            return $number;
        }
    }

	function get_edit_user_url() {
		return get_edit_user_link( $this->get_user_id() );
	}

	function get_edit_order_url() {

		return add_query_arg(
			array(
				'page'       => 'pms-payments-page',
				'pms-action' => 'edit_payment',
				'payment_id' => $this->get_id()
			),
			admin_url( 'admin.php' )
		);

	}

	function get_status() {

		$status = $this->order->status;

		// map pms payment status to woocommerce order status
		switch ( $status ) {
			case 'completed':
				return 'completed';
			case 'pending':
				return 'processing';
			case 'failed':
				return 'failed';
			case 'cancelled':
				return 'cancelled';
			case 'refunded':
				return 'refunded';
			default:
				return 'unknown';
		}
	}

	function get_currency() {
		return \pms_get_active_currency();
	}

	function get_currency_symbol( $currency ) {
		return \pms_get_currency_symbol( $currency );
	}

	function get_payment_method() {


		switch ( $this->order->payment_gateway ) {
			case 'stripe':
				return 'stripe';
			case 'paypal':
			case 'paypal_standard':
				return 'paypal';
			case 'bank_transfer':
				return 'bank_transfer';
			case 'cash':
				return 'cash';
			case 'manual':
				return 'bacs';
			default:
				return 'unknown';
		}
	}

	function has_status( $status ) {
		// TODO: Implement has_status() method.
	}

	function get_date_completed() {

		$completed_data = $this->get_completed_data();
		$completed_data = isset( $completed_data['date'] ) ? $completed_data['date'] : '';

		return new DateTimeProvider($completed_data);

	}

	function get_date_paid() {
		// PMS doesn't have a date paid field
		// paid === completed
		return $this->get_date_completed();
	}

	/**
	 * Get the payment modified date.
	 * @return mixed|string
	 */
	function get_date_modified() {

		// the modified date is the last log line date
		$logs = $this->get_log();
		if ( empty( $logs ) ) {
			return '';
		}
		$last_log = end( $logs );

		if(!isset($last_log['date'])) {
			return '';
		}

		return new DateTimeProvider($last_log['date']);
	}

	function get_date_created() {
		return new DateTimeProvider($this->order->date);
	}

	function get_shipping_total() {
		// it's a digital product, no shipping
		return 0;
	}

	function get_shipping_tax() {
		// it's a digital product, no shipping
		return 0;
	}

	function get_nature_rc() {
		return \pms_get_payment_meta( $this->id, 'nature_rc', true );
	}

	function get_ref_norm_rc() {
		return \pms_get_payment_meta( $this->id, 'ref_norm_rc', true );
	}

	/**
	 * Get the discount total.
	 * @return mixed
	 */
	function get_discount_total() {
		return \pms_get_payment_meta( $this->id, 'pms_discount_total', true );
	}

	/**
	 * Get the discount tax.
	 * @return float|int
	 */
	function get_discount_tax() {
		$discount_total = $this->get_discount_total();
		$tax_rate       = pms_get_payment_meta( $this->id, 'pms_tax_rate', true );

		if ( empty( $discount_total ) || empty( $tax_rate ) ) {
			return 0;
		}

		return $discount_total * $tax_rate / 100;

	}

	/**
	 * Get the cart tax.
	 * @return int
	 */
	private function get_cart_tax() {
		// cart tax set to 0
		// what's cart tax???
		return 0;
	}

	/**
	 * Get the total tax for the payment.
	 * @return float|int
	 */
	function get_total_tax() {
		$tax_rate = pms_get_payment_meta( $this->id, 'pms_tax_rate', true );
		$total    = $this->get_total();

		if ( empty( $tax_rate ) ) {
			return 0;
		}

		return $total * $tax_rate / 100;
	}

	function set_date_completed( $timestamp ) {
		// nothing to do here
	}

	/**
	 * Get payment logs.
	 *
	 * @return array
	 */
	function get_log() {
		return $this->order->logs;
	}

	/**
	 * Get payment refund data from the logs.
	 * @return mixed|void
	 */
	function get_refunded_data() {

		$log = $this->get_log();
		if ( empty( $log ) ) {
			return [];
		}

		// reverse the log array to get the last refund log
		$log = array_reverse( $log );

		foreach ( $log as $item ) {

			// empty type field
			if ( ! isset( $item['type'] ) ) {
				continue;
			}

			// empty new_data field
			if ( ! isset( $item['data']['new_data'] ) ) {
				continue;
			}

			// not of type status_changed
			if ( $item['type'] !== 'status_changed' ) {
				continue;
			}

			if ( $item['type'] === 'status_changed' && $item['data']['new_data']['status'] === 'refunded' ) {
				return $item['data']['old_data'];
			}
		}


	}

	/**
	 * Get completed payment data from the logs.
	 * @return mixed|void
	 */
	function get_completed_data() {

		$log = $this->get_log();
		if ( empty( $log ) ) {
			return [];
		}

		$log = array_reverse( $log );

		foreach ( $log as $item ) {

			// empty type field
			if ( ! isset( $item['type'] ) ) {
				continue;
			}

			// empty new_data field
			if ( ! isset( $item['data']['new_data'] ) ) {
				continue;
			}

			// not of type status_changed
			if ( $item['type'] !== 'status_changed' ) {
				continue;
			}

			if ( $item['data']['new_data']['status'] !== 'completed' ) {
				return $item['data']['old_data'];
			}
		}

	}

	function save() {
		// nothing to do here
	}
}
