<?php

defined( 'ABSPATH' ) or exit;

class PWLPAR_Member {

    /* Member Properties */
    protected $id;
    protected $display_name;
    protected $login;
    protected $email;
    protected $is_enrolled;
    protected $join_date;
    protected $balance;
    protected $total_orders;
    protected $total_revenue;
    protected $average_order_value;

    function __construct( $args = array() ) {

        $default_args = apply_filters( 'pwlpar_member_default_args', array(
            'user_id'               => 0,
            'display_name'          => '',
            'login'                 => '',
            'email'                 => '',
            'is_enrolled'           => 'yes',
            'join_date'             => '',
            'balance'               => false,
            'total_orders'          => false,
            'total_revenue'         => false,
            'average_order_value'   => false,
        ) );

        $args = wp_parse_args( $args, $default_args );

        if ( isset( $args['id'] ) && empty( $args['user_id'] ) ) {
            $args['user_id'] = $args['id'];
        }

        $this->id                   = absint( $args['user_id'] );
        $this->display_name         = $args['display_name'];
        $this->login                = $args['login'];
        $this->email                = $args['email'];
        $this->is_enrolled          = $args['is_enrolled'];
        $this->join_date            = $args['join_date'];
        $this->balance              = $args['balance'];
        $this->total_orders         = $args['total_orders'];
        $this->total_revenue        = $args['total_revenue'];
        $this->average_order_value  = $args['average_order_value'];
    }

    /* Getters */
    public function get_id( $context = 'view' ) {
        return $this->id;
    }

    public function get_display_name( $context = 'view' ) {
        return $this->display_name;
    }

    public function get_login( $context = 'view' ) {
        return $this->login;
    }

    public function get_email( $context = 'view' ) {
        return $this->email;
    }

    public function get_is_enrolled( $context = 'view' ) {
        if ( $context == 'edit' ) {
            return $this->is_enrolled;
        }

        return ( $this->is_enrolled == 'yes' );
    }

    public function get_join_date( $context = 'view' ) {
        if ( $context == 'edit' ) {
            return $this->join_date;
        }

        return pwlpar_format_date( $this->join_date );
    }

    public function get_balance( $context = 'view' ) {
        // Lazy-loaded.
        if ( $this->balance === false ) {
            $this->balance = pwlpar_get_member_point_balance( $this );
        }

        if ( $context == 'edit' ) {
            return $this->balance;
        }

        return pwlpar_format_points( $this->balance );
    }

    public function get_total_orders( $context = 'view' ) {
        // Lazy-loaded.
        if ( $this->total_orders === false ) {
            $this->load_stats();
        }

        if ( $context == 'edit' ) {
            return $this->total_orders;
        }

        return number_format_i18n( $this->total_orders );
    }

    public function get_total_revenue( $context = 'view' ) {
        // Lazy-loaded.
        if ( $this->total_revenue === false ) {
            $this->load_stats();
        }

        if ( $context == 'edit' ) {
            return $this->total_revenue;
        }

        return wc_price( $this->total_revenue );
    }

    public function get_average_order_value( $context = 'view' ) {
        // Lazy-loaded.
        if ( $this->average_order_value === false ) {
            $this->load_stats();
        }

        if ( $context == 'edit' ) {
            return $this->average_order_value;
        }

        return wc_price( $this->average_order_value );
    }



    /* Setters */
    public function set_is_enrolled( $is_enrolled ) {
        $this->is_enrolled = $is_enrolled;
    }

    public function set_join_date( $join_date ) {
        $this->join_date = $join_date;
    }



    /* Public methods */
    public function save() {
        do_action( 'pwlpar_member_save', $this );

        update_user_meta( $this->id, PWLPAR_USER_META_KEY_IS_MEMBER, $this->is_enrolled );
        update_user_meta( $this->id, PWLPAR_USER_META_KEY_JOIN_DATE, $this->join_date );

        do_action( 'pwlpar_member_saved', $this );

        return $this->id;
    }

    public function get_edit_url() {
        $url = get_edit_user_link( $this->get_id() );
        return apply_filters( 'pwlpar_member_edit_url', $url, $this );
    }


    /* Private methods */
    private function load_stats() {
        global $wpdb;

        // Only lazy load this data once per instance.
        if ( $this->total_orders !== false ) {
            return;
        }

        $this->total_orders = 0;
        $this->total_revenue = 0;
        $this->average_order_value = 0;

        if ( !empty( $this->get_id() ) ) {
            //
            // Querying the WooCommerce database directly for performance reasons.
            //
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $result = $wpdb->get_row( $wpdb->prepare( "
                SELECT
                    SUM( CASE WHEN parent_id = 0 THEN 1 ELSE 0 END ) AS total_orders,
                    SUM( total_sales ) AS total_revenue,
                    CASE WHEN SUM( CASE WHEN parent_id = 0 THEN 1 ELSE 0 END ) = 0 THEN NULL ELSE SUM( total_sales ) / SUM( CASE WHEN parent_id = 0 THEN 1 ELSE 0 END ) END AS average_order_value
                FROM
                    {$wpdb->prefix}wc_customer_lookup AS c
                LEFT JOIN
                    {$wpdb->prefix}wc_order_stats AS s ON (c.customer_id = s.customer_id AND ( s.status NOT IN ( 'wc-auto-draft','wc-trash','wc-pending','wc-failed','wc-cancelled','wc-checkout-draft' ) ))
                WHERE
                    c.user_id = %d
                ",
                $this->get_id()
            ) );

            $this->total_orders = $result->total_orders;
            $this->total_revenue = $result->total_revenue;
            $this->average_order_value = $result->average_order_value;
        }
    }
}
