<?php

namespace POPxPMPro\Providers;

use WcElectronInvoice\Providers\DateTimeProvider;

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

class OrderRefund extends \WcElectronInvoice\Providers\OrderRefund {

    /**
     * PMPro does not have a native refund record.
     * This adapter exposes a refund entity on top of the same source order id.
     *
     * @var Order
     */
    protected $parentOrder;

    public function __construct( $order, $provider, $tax_provider ) {
        parent::__construct( $order, $provider, $tax_provider );
        $this->parentOrder = new Order( $order, $provider, $tax_provider );
    }

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

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

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

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

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

    function get_data() {
        $data = $this->parentOrder->get_data();

        $data['id']             = $this->get_id();
        $data['parent_id']      = $this->get_parent_id();
        $data['status']         = $this->get_status();
        $data['date_created']   = $this->get_date_created();
        $data['date_modified']  = $this->get_date_modified();
        $data['date_completed'] = $this->get_date_completed();
        $data['date_paid']      = $this->get_date_refunded();
        $data['order_type']     = $this->get_type();
        $data['shipping_total'] = $this->get_shipping_total();
        $data['shipping_tax']   = $this->get_shipping_tax();
        $data['total']          = $this->get_total();
        $data['cart_tax']       = -1 * abs( (float) $data['cart_tax'] );
        $data['total_tax']      = -1 * abs( (float) $data['total_tax'] );
        $data['taxes']          = [
            'subtotal' => [ 1 => $data['total_tax'] ],
            'total'    => [ 1 => $data['total_tax'] ],
        ];
        $data['amount'] = abs($this->get_total());
        $data['reason'] = __('Refund', WC_EL_INV_TEXTDOMAIN);
        $data['refunded_by'] = 1;
        $data['refunded_payment'] = true;
        $data['invoice_sent']   = $this->get_invoice_sent();
        $data['invoice_type']   = $this->get_invoice_type();

        return $data;
    }

    function get_status() {
        return 'refunded';
    }

    function get_meta( $key, $single = true ) {
        return $this->parentOrder->get_meta( $key, $single );
    }

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

    function delete_meta( $key ) {
        return $this->parentOrder->delete_meta( $key );
    }

    function get_total() {
        return -1 * abs( (float) $this->parentOrder->get_total() );
    }

    function get_total_refunded() {
        return $this->parentOrder->get_total_refunded();
    }

    function get_refunds() {
        return [];
    }

    function get_payment_method() {
        return $this->parentOrder->get_payment_method();
    }

    function get_parent_id() {
        return $this->parentOrder->get_id();
    }

    function get_parent_order() {
        return $this->parentOrder;
    }

    function get_invoice_type() {
        return $this->parentOrder->get_invoice_type();
    }

    function get_billing_tax_code() {
        return $this->parentOrder->get_billing_tax_code();
    }

    function get_sdi_type() {
        return $this->parentOrder->get_sdi_type();
    }

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

    function get_type() {
        return 'shop_order_refund';
    }

    function get_type_label( $orderType = '' ) {
        return __( 'Refund', WC_EL_INV_TEXTDOMAIN );
    }

    function get_remaining_refund_amount() {
        return 0;
    }

    function get_remaining_refund_items() {
        return 0;
    }

    function get_total_qty_refunded() {
        return 1;
    }

    function get_items( $type = 'line_item' ) {
        switch ( $type ) {
            case 'line_item':
                return [ new RefundOrderItem( $this->order ) ];

            case 'fee':
                $fees = $this->parentOrder->get_items( 'fee' );
                foreach ( $fees as $index => $fee ) {
                    if ( isset( $fee->total ) ) {
                        $fees[ $index ]->total = -1 * abs( (float) $fee->total );
                    }
                    if ( isset( $fee->total_tax ) ) {
                        $fees[ $index ]->total_tax = -1 * abs( (float) $fee->total_tax );
                    }
                }

                return $fees;

            case 'shipping':
                return [];

            case 'tax':
                return $this->parentOrder->get_items( 'tax' );

            default:
                return [];
        }
    }

    function get_qty_refunded_for_item() {
        return 1;
    }

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

        return $value;
    }

    function get_invoice_sent_timestamp( $order_id = '' ) {
        $order_id = $order_id ?: $this->get_id();

        return get_pmpro_membership_order_meta( $order_id, 'refund_invoice_sent_timestamp', true );
    }

    function set_invoice_sent( $sent, $order_id = '' ) {
        $order_id = $order_id ?: $this->get_id();

        return update_pmpro_membership_order_meta( $order_id, 'refund_invoice_sent', $sent );
    }

    function set_invoice_sent_timestamp( $timestamp, $order_id = '' ) {
        $order_id = $order_id ?: $this->get_id();

        return update_pmpro_membership_order_meta( $order_id, 'refund_invoice_sent_timestamp', $timestamp );
    }

    function get_vat_number() {
        return $this->parentOrder->get_vat_number();
    }

    function get_order_number_invoice() {
        return $this->get_meta( "refund_number_invoice-{$this->get_id()}" );
    }

    function get_refund_payment_method() {
        return $this->parentOrder->get_refund_payment_method();
    }

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

    function get_edit_order_url() {
        return $this->parentOrder->get_edit_order_url();
    }

    function get_currency() {
        return $this->parentOrder->get_currency();
    }

    function get_currency_symbol( $currency ) {
        return $this->parentOrder->get_currency_symbol( $currency );
    }

    function get_billing_country() {
        return $this->parentOrder->get_billing_country();
    }

    function get_billing_choice_type() {
        return $this->parentOrder->get_billing_choice_type();
    }

    function get_nature_rc() {
        return $this->parentOrder->get_nature_rc();
    }

    function get_ref_norm_rc() {
        return $this->parentOrder->get_ref_norm_rc();
    }

    function has_status( $status ) {
        return $this->get_status() === $status;
    }

    function get_date_created() {
        return $this->get_date_refunded();
    }

    function get_date_completed() {
        return $this->get_date_refunded();
    }

    function get_date_modified() {
        return $this->get_date_refunded();
    }

    function get_shipping_total() {
        return -1 * abs( (float) $this->parentOrder->get_shipping_total() );
    }

    function get_shipping_tax() {
        return -1 * abs( (float) $this->parentOrder->get_shipping_tax() );
    }

    /**
     * Get the refunded date.
     *
     * @return DateTimeProvider
     * @throws \Exception
     */
    function get_date_refunded() {
        $refunded_date = $this->get_meta( 'refunded_date' ) ?: date( 'Y-m-d H:i:s', current_time( 'timestamp' ) );

        return new DateTimeProvider( $refunded_date );
    }

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

    function get_tax_refunded_for_item( $item_id, $item_type ) {
        return $this->parentOrder->get_tax_refunded_for_item( $item_id, $item_type );
    }

    function set_date_completed( $timestamp ) {
        // PMPro refund adapter is backed by the parent order meta only.
    }

    function save() {
        $this->parentOrder->save();
    }
}
