<?php
/**
 * Collection class.
 *
 * @package SaveToWishlist\Classes\Factories
 * @since 1.0.0
 */
namespace SaveToWishlist\Classes\Factories;

use SaveToWishlist\Abstracts\Singleton;
use SaveToWishlist\Helpers\Helper_Functions;
use SaveToWishlist\Classes\Factories\Collection_Item;

/**
 * Class Collection
 *
 * This class creates an instance of a collection.
 *
 * @since 1.0.0
 */
class Collection extends Singleton {

    /**
     * Collection user ID.
     *
     * @var int
     */
    public $user_id;

    /**
     * Collection user display name.
     *
     * @var string
     *
     * @since 1.0.5
     */
    public $user_name = '';

    /**
     * Collection URL code.
     *
     * @var string
     */
    public $url_code;

    /**
     * Collection ID.
     *
     * @var int
     */
    public $id;

    /**
     * Collection key.
     *
     * @var string | number
     */
    public $key;

    /**
     * Collection name.
     *
     * @var string
     */
    public $name;

    /**
     * Collection description.
     *
     * @var string
     */
    public $description;

    /**
     * Collection items.
     *
     * @var array
     */
    public $items = array();

    /**
     * Collection status.
     *
     * @var string
     */
    public $status;

    /**
     * Collection is default.
     *
     * @var bool
     */
    public $is_default;

    /**
     * Collection is public.
     *
     * @var bool
     */
    public $is_public;

    /**
     * Collection created at.
     *
     * @var string
     */
    public $created_at;

    /**
     * Collection updated at.
     *
     * @var string
     *
     * @since 1.0.6
     */
    public $updated_at;

    /**
     * Collection emails.
     *
     * @var array
     */
    public $emails = array();

    /**
     * Collection user IDs.
     *
     * @var array
     */
    public $user_ids = array();

    /**
     * Collection allowed edit emails.
     *
     * @var array
     */
    public $allowed_edit_emails = array();

    /**
     * Collection allowed roles.
     *
     * @var array
     */
    public $allowed_roles = array();

    /**
     * Helper functions.
     *
     * @var Helper_Functions
     */
    private $helper_functions;

    /**
     * Constructor.
     *
     * @param object $item Item.
     *
     * @since 1.0.0
     */
    public function __construct( $item ) {
        $this->helper_functions = Helper_Functions::instance();

        $this->key                 = $item->id;
        $this->user_id             = $item->user_id;
        $this->url_code            = ! empty( $item->url_code ) ? $item->url_code : '';
        $this->id                  = $item->id;
        $this->name                = $item->name;
        $this->description         = $item->description;
        $this->items               = $this->get_collection_items( $item->id );
        $this->status              = $item->status;
        $this->is_default          = $item->is_default;
        $this->is_public           = $item->is_public;
        $this->created_at          = $item->created_at;
        $this->updated_at          = $item->updated_at;
        $this->emails              = $this->get_field_data( $item, array( 'emails' ) );
        $this->user_ids            = $this->get_field_data( $item, array( 'user_ids' ) );
        $this->allowed_edit_emails = $this->get_field_data( $item, array( 'allowed_edit_emails' ) );
        $this->allowed_roles       = $this->get_field_data( $item, array( 'allowed_roles' ) );

        $user            = get_userdata( $this->user_id );
        $this->user_name = $user ? $user->display_name : '';
    }

    /**
     * Get an instance of a collection.
     *
     * @param object $item Item.
     *
     * @since 1.0.0
     * @access public
     *
     * @return Collection
     */
    public static function get_instance( $item ) {
        return new self( $item );
    }

    /**
     * Get the collection items.
     *
     * @param int $collection_id Collection ID.
     *
     * @since 1.0.0
     * @access public
     *
     * @return array
     */
    public function get_collection_items( $collection_id ) {
        global $wpdb;

        $cache_key   = 'collection_items_' . $collection_id;
        $cache_group = STWLITE_CACHE_GROUP;

        $items = wp_cache_get( $cache_key, $cache_group );

        if ( false === $items ) {
            // phpcs:disable
            $items = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}stw_collection_items WHERE collection_id = %d", $collection_id ) );
            // phpcs:enable

            wp_cache_set( $cache_key, $items, $cache_group, DAY_IN_SECONDS );
        }

        $data = array_map(
            function ( $item ) {
                return Collection_Item::get_instance( $item );
            },
            $items
        );

        // Filter the data.
        $data = apply_filters( 'stwlite_collection_items_data', $data );

        return $data;
    }

    /**
     * Get the field data.
     *
     * @param object $data The collection data.
     * @param array  $fields The fields to get.
     *
     * @since 1.0.0
     * @access public
     *
     * @return mixed The field data (array if single field, array with keys if multiple fields).
     */
    public function get_field_data( $data, $fields = array() ) {
        // Filter the data.
        $data = apply_filters( 'stwlite_single_collection_data', $data );

        // Get fields from the data.
        $fields = array_intersect( array_keys( get_object_vars( $data ) ), $fields );

        // Get the values for the requested fields.
        $result = array();
        foreach ( $fields as $field ) {
            $value = $data->$field;
            // Ensure array fields are returned as arrays.
            if ( in_array( $field, array( 'emails', 'user_ids', 'allowed_edit_emails', 'allowed_roles' ), true ) ) {
                $result[ $field ] = is_array( $value ) ? $value : ( ! empty( $value ) ? (array) $value : array() );
            } else {
                $result[ $field ] = $value;
            }
        }

        // If only one field requested, return its value directly.
        if ( count( $result ) === 1 ) {
            return reset( $result );
        }

        // Return the fields as an array with field names as keys and their values.
        return $result;
    }
}
