<?php
/**
 * Objects: Payout
 *
 * @package     AffiliateWP
 * @subpackage  Database
 * @copyright   Copyright (c) 2017, Sandhills Development, LLC
 * @license     http://opensource.org/licenses/gpl-2.0.php GNU Public License
 * @since       1.9
 */

namespace AffWP\Affiliate;

#[\AllowDynamicProperties]

/**
 * Implements a payout object.
 *
 * @since 1,9
 *
 * @see AffWP\Base_Object
 * @see affwp_get_payouts()
 *
 * @property-read int $ID Alias for `$payout_id`.
 */
final class Payout extends \AffWP\Base_Object {

	/**
	 * Payout ID.
	 *
	 * @access public
	 * @since  1.9
	 * @var    int
	 */
	public $payout_id = 0;

	/**
	 * Batch ID the payout belongs to. Zero for ungrouped payouts (inline pays, legacy records).
	 *
	 * @access public
	 * @since  2.33.0
	 * @var    int
	 */
	public $batch_id = 0;

	/**
	 * Affiliate ID.
	 *
	 * @access public
	 * @since  1.9
	 * @var    int
	 */
	public $affiliate_id = 0;

	/**
	 * IDs for referrals associated with the payout.
	 *
	 * @access public
	 * @since  1.9
	 * @var    array
	 */
	public $referrals = array();

	/**
	 * Payout amount.
	 *
	 * @access public
	 * @since  1.9
	 * @var    float
	 */
	public $amount;

	/**
	 * Payout method.
	 *
	 * @access public
	 * @since  1.9
	 * @var    string
	 */
	public $payout_method;

	/**
	 * Payout account.
	 *
	 * @access public
	 * @since  2.4
	 * @var    string
	 */
	public $service_account;

	/**
	 * Payouts Service payout ID.
	 *
	 * @access public
	 * @since  2.4
	 * @var    int
	 */
	public $service_id;

	/**
	 * Payouts Service invoice link.
	 *
	 * @access public
	 * @since  2.4
	 * @var    string
	 */
	public $service_invoice_link;

	/**
	 * Payout description.
	 *
	 * @access public
	 * @since  2.4
	 * @var    string
	 */
	public $description;

	/**
	 * Payout status.
	 *
	 * @access public
	 * @since  1.9
	 * @var    string
	 */
	public $status;

	/**
	 * Machine-readable failure category, populated on the payout row when
	 * status is 'failed'. NULL or empty on successful payouts.
	 *
	 * One of the AffWP\Payouts\Failure_Class constants:
	 * - transient
	 * - affiliate_action_required
	 * - admin_action_required
	 * - data_error
	 * - unknown
	 *
	 * Read by the drawer's Next Steps card, the auto-email pipeline, and
	 * the daily auto-retry sweep to dispatch the correct action per
	 * failure class without re-parsing the description field.
	 *
	 * @access public
	 * @since  2.33.0
	 * @var    string|null
	 */
	public $failure_class;

	/**
	 * Number of times this payout's referral set has been retried.
	 *
	 * 0 for an original payout. Each retry created via `affwp_retry_payout()`
	 * carries its parent's count + 1, so the value is the depth of the retry
	 * chain. The auto-retry sweep skips any failed payout whose count has
	 * reached `affwp_payout_max_retry_attempts()`, bounding how many times a
	 * persistently-failing payout can be re-attempted.
	 *
	 * @access public
	 * @since  2.33.0
	 * @var    int
	 */
	public $retry_count = 0;

	/**
	 * ID of the payout that superseded this one, or 0.
	 *
	 * Set on a failed payout when `affwp_retry_payout()` (or a method switch)
	 * dispatches a replacement: the replacement's ID is recorded here and the
	 * original is kept as an immutable audit record. The admin payouts list
	 * hides superseded rows by default so a retry chain collapses to its
	 * current tail; the drawer surfaces a "Replaced by #N" link.
	 *
	 * @access public
	 * @since  2.33.0
	 * @var    int
	 */
	public $superseded_by_payout_id = 0;

	/**
	 * Payout date.
	 *
	 * @access public
	 * @since  1.9
	 * @var    string
	 */
	public $date;

	/**
	 * ID of the user who generated the payout.
	 *
	 * @access public
	 * @since  1.9.5
	 * @var    int
	 */
	public $owner = 0;

	/**
	 * Token to use for generating cache keys.
	 *
	 * @access public
	 * @since  1.9
	 * @var    string
	 * @static
	 *
	 * @see AffWP\Base_Object::get_cache_key()
	 */
	public static $cache_token = 'affwp_payouts';

	/**
	 * Database group.
	 *
	 * Used in \AffWP\Base_Object for accessing the affiliates DB class methods.
	 *
	 * @since 1.9
	 * @access public
	 * @var string
	 */
	public static $db_group = 'affiliates:payouts';

	/**
	 * Object type.
	 *
	 * Used as the cache group and for accessing object DB classes in the parent.
	 *
	 * @access public
	 * @since  1.9
	 * @var    string
	 * @static
	 */
	public static $object_type = 'payouts';

	/**
	 * Sanitizes an affiliate object field.
	 *
	 * @access public
	 * @since  1.9
	 * @static
	 *
	 * @param string $field        Object field.
	 * @param mixed  $value        Field value.
	 * @return mixed Sanitized field value.
	 */
	public static function sanitize_field( $field, $value ) {
		if ( in_array( $field, array( 'payout_id', 'batch_id', 'affiliate_id', 'ID', 'owner', 'service_id', 'retry_count', 'superseded_by_payout_id' ) ) ) {
			$value = (int) $value;
		}

		if ( 'referrals' === $field ) {
			$value = implode( ',', wp_parse_id_list( $value ) );
		}

		if ( 'amount' === $field ) {
			$value = floatval( $value );
		}

		return $value;
	}

}
