<?php

/**
 * Mass pay users
 *
 * @author Matt Gates <http://mgates.me>
 * @package WC_Vendors
 * @since 1.9.0
 * @version 2.6.5
 */
class WCV_Mass_Pay {
 // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedClassFound


    /**
     * The plugin directory.
     *
     * @var string
     */
    private static $pluginDir;

    /**
     * The orders paid.
     *
     * @var array
     */
    private $orders_paid = array();

    /**
     * Pay out all outstanding commission.
     *
     * @return array
     */
    public function do_payments() {
        $vendors         = array();
        self::$pluginDir = trailingslashit( __DIR__ );
        $vendors         = $this->get_users();

        return $this->pay_vendors( $vendors );
    }


    /**
     * Include the PayPal API.
     */
    private function include_paypal_sdk() {
        $path = self::$pluginDir . 'api/lib';
        set_include_path( get_include_path() . PATH_SEPARATOR . $path ); // phpcs:ignore
        require_once 'services/PayPalAPIInterfaceService/PayPalAPIInterfaceServiceService.php';
        require_once 'PPLoggingManager.php';
    }


    /**
     * Retrieve all vendors and their due commission.
     *
     * @return array
     */
    private function get_users() {
        $orders = WCV_Commission::get_all_due();
        if ( empty( $orders ) ) {
return false;
        }

        // Initialize the arrays.
        $vendors     = array();
        $due_amounts = array();

        foreach ( $orders as $data ) {
            $due_amounts[ $data->vendor_id ][] = $data->total_due;
            if ( 'yes' === get_option( 'wcvendors_vendor_give_shipping', 'no' ) ) {
                $due_amounts[ $data->vendor_id ][] += $data->total_shipping;
            }
            $this->orders_paid[] = $data->id;
        }

        foreach ( $due_amounts as $vendor_id => $totals_due ) {
            $due_amounts[ $vendor_id ] = array_sum( $totals_due );
        }

        foreach ( $due_amounts as $vendor_id => $total_due ) {
            $user_id        = $vendor_id;
            $commission_due = $total_due;
            $paypal_email   = get_user_meta( $vendor_id, 'pv_paypal', true );

            // Skip vendors that haven't filled a paypal address
            // Or that don't have an outstanding balance.
            if ( empty( $paypal_email ) || empty( $commission_due ) ) {
continue;
            }

            // Who knows if it exists more than once. Let's not take a risk
            // Therefore, we add the total due to perhaps a previously existing one.
            $vendors[ $paypal_email ] = array(
                'user_id'   => $user_id,
                'total_due' => ! empty( $vendors[ $paypal_email ][ $user_id ]['total_due'] )
                        ? $vendors[ $paypal_email ][ $user_id ]['total_due'] + $commission_due
                        : $commission_due,
            );
        }

        return $vendors;
    }


    /**
     * Delete due commission for a vendor.
     *
     * @param array $vendor_ids The vendor IDs.
     *
     * @return bool
     */
    private function purge_user_meta( $vendor_ids ) {

        return (bool) WCV_Commission::set_vendor_commission_paid( $vendor_ids );
    }


    /**
     * Pay out all due commission.
     *
     * @param array $vendors The vendors data.
     *
     * @return array
     */
    private function pay_vendors( $vendors ) {
        if ( empty( $vendors ) ) {
            $return = array(
                'status' => 'error',
                'msg'    => __( 'No vendors found to pay. Maybe they haven\'t set a PayPal address?', 'wc-vendors' ),
            );
            $this->mail_results( $return );

            return $return;
        }

        $vendor_ids = array();

        $this->include_paypal_sdk();

        $logger                      = new PPLoggingManager( 'MassPay' );
        $massPayRequest              = new MassPayRequestType();
        $massPayRequest->MassPayItem = array();

        $total_pay = 0;
        foreach ( $vendors as $user_paypal => $user ) {
            // Don't attempt to process payments for users that owe the admin money.
            if ( $user['total_due'] <= 0 ) {
continue;
            }

            $total_pay                    += $user['total_due'];
            $masspayItem                   = new MassPayRequestItemType();
            $masspayItem->Amount           = new BasicAmountType( get_woocommerce_currency(), $user['total_due'] );
            $masspayItem->ReceiverEmail    = $user_paypal;
            $massPayRequest->MassPayItem[] = $masspayItem;
            $vendor_ids[]                  = $user['user_id'];
        }

        $massPayReq                 = new MassPayReq();
        $massPayReq->MassPayRequest = $massPayRequest;

        $paypalService = new PayPalAPIInterfaceServiceService();

        // Wrap API method calls on the service object with a try catch.
        try {
            $massPayResponse = $paypalService->MassPay( $massPayReq );
        } catch ( Exception $ex ) {
            $return = array(
                'status' => 'error',
                'msg'    => sprintf( /* translators: %s is the error message. */ __( 'Error: %s', 'wc-vendors' ), $ex->getMessage() ),
                'total'  => $total_pay,
            );

            return $return;
        }

        $return = array();

        if ( isset( $massPayResponse ) ) {
            if ( 'Success' === $massPayResponse->Ack ) {
                if ( $this->purge_user_meta( $vendor_ids ) ) {
                    $return = array(
                        'status' => 'updated',
                        'msg'    => __( 'All due commission has been paid for. ', 'wc-vendors' ),
                        'total'  => $total_pay,
                    );
                } else {
                    $return = array(
                        'status' => 'error',
                        'msg'    => __( 'All due commission has been paid for, but I could not clear it from their profiles due to an internal error. Commission will still be listed as due. Please manually mark the commission as paid from the Commissions page.', 'wc-vendors' ),
                        'total'  => $total_pay,
                    );
                }
            } else {
                $return = array(
                    'status' => 'error',
                    'msg'    => sprintf( '%s. %s (%s): %s.', $massPayResponse->Ack, $massPayResponse->Errors->ShortMessage, $massPayResponse->Errors->ErrorCode, $massPayResponse->Errors->LongMessage ),
                    'total'  => $total_pay,
                );
            }
        }

        $this->mail_results( $return );

        return $return;
    }


    /**
     * Mail the manual payment results.
     *
     * @param array $result The result array.
     *
     * @return bool
     */
    private function mail_results( $result ) {

        $send_results = get_option( 'wcvendors_payments_paypal_email_enable' );

        if ( ! $send_results ) {
            return false;
        }

        $to      = sanitize_email( get_option( 'woocommerce_email_from_address' ) );
        $subject = __( 'WooCommerce: Mass payments for vendors update', 'wc-vendors' );

        $message  = __( 'Hello! A payment was just triggered to mass pay all vendors their due commission.', 'wc-vendors' ) . PHP_EOL . PHP_EOL;
        $message .= sprintf( /* translators: %s is the payment status. */ __( 'Payment status: %s.', 'wc-vendors' ), $result['status'] ) . PHP_EOL;
        $message .= sprintf( /* translators: %s is the payment message. */ __( 'Payment message: %s.', 'wc-vendors' ), $result['msg'] ) . PHP_EOL;

        if ( ! empty( $result['total'] ) ) {
            $message .= sprintf( /* translators: %s is the payment total. */ __( 'Payment total: %s.', 'wc-vendors' ), $result['total'] );
        }

        $sent = wp_mail( $to, $subject, $message, 'From: ' . $to . "\r\n" );

        return $sent;
    }
}
