<?php
/**
 * Helper class to get fields from tables
 *
 * @package crewhrm
 */

namespace CrewHRM\Models;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}


use CrewHRM\Helpers\_Array;

/**
 * The class to get fields
 */
class Field {
	/**
	 * Get specific field/s from table
	 *
	 * @var string
	 */
	private $table;

	/**
	 * Set up the table to operate in
	 *
	 * @param string $table Table name to get data from
	 * @return void
	 */
	public function __construct( string $table ) {
		$this->table = $table;
	}

	/**
	 * Get instance by table name
	 *
	 * @param string $name      The table name to get instance for
	 * @param string $arguments The arguments to make instance with
	 * @return self
	 */
	public static function __callStatic( $name, $arguments ) {
		// Run time cache
		static $instances = array();

		if ( ! isset( $instances[ $name ] ) ) {
			$instances[ $name ] = new self( DB::$name() );
		}

		return $instances[ $name ];
	}

	/**
	 * Get specific fields by specific where clause
	 *
	 * @param array        $where Array of values to use as where clause
	 * @param string|array $field The field or array of fields to get data from the table
	 * @param mixed        $fallback Default return value if single field not found or null
	 *
	 * @return mixed
	 */
	public function getField( array $where, $field, $fallback = null ) {

		global $wpdb;

		// Prepare select columns and where clause
		$columns      = is_array( $field ) ? array_values( $field ) : array( $field );
		$column_place = implode( ', ', array_fill( 0, count( $columns ), '%i' ) );
		$where_clause = '1=1';
		$args         = $columns;
		$args[]       = $this->table;

		// Loop through conditions
		foreach ( $where as $col => $val ) {
			$where_clause .= ' AND %i=%s';
			$args[]        = (string) $col;
			$args[]        = $val;
		}

		$row = $wpdb->get_row(
			$wpdb->prepare( 'SELECT ' . $column_place . ' FROM %i WHERE ' . $where_clause . ' LIMIT 1', ...$args ), // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
			ARRAY_A
		);

		$row = ! empty( $row ) ? _Array::castRecursive( $row ) : array();

		return ! is_array( $field ) ? ( $row[ $field ] ?? $fallback ) : $row;
	}

	/**
	 * Get specifc column by where clause
	 *
	 * @param array  $where    Where condition array to get data based on
	 * @param string $col_name The column name to get
	 * @return array
	 */
	public function getCol( array $where, string $col_name ) {

		$where_clause = '1=1';
		$args         = array( $col_name, $this->table );

		// Loop through conditions
		foreach ( $where as $col => $val ) {
			$where_clause .= ' AND %i=%s';
			$args[]        = (string) $col;
			$args[]        = $val;
		}

		global $wpdb;
		$col = $wpdb->get_col(
			$wpdb->prepare( 'SELECT %i FROM %i WHERE ' . $where_clause, ...$args ) // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
		);

		return _Array::getArray( $col );
	}

	/**
	 * Update fields
	 *
	 * @param array $update The value to be updated
	 * @param array $where Where condition to update based on
	 * @return void
	 */
	public function updateField( array $update, array $where ) {
		global $wpdb;
		$wpdb->update( $this->table, $update, $where );
	}
}
