<?php (defined('BASEPATH')) OR exit('No direct script access allowed');

/**
 * Bloom Iris Agency - Base Model
 * --------------------------------------------------------------------------
 * Provides a thin, predictable CRUD layer that every model extends.
 * Children only need to set $table (and optionally $order_by, $soft_delete).
 * --------------------------------------------------------------------------
 */
require APPPATH.'third_party/MX/Model.php';

#[\AllowDynamicProperties]
class MY_Model extends MX_Model {

	/** @var string The database table this model maps to */
	protected $table = '';

	/** @var string Primary key column */
	protected $primary_key = 'id';

	/** @var string Default ordering, e.g. 'created_at DESC' */
	protected $order_by = 'id DESC';

	/** @var bool Whether the table has a deleted_at column for soft deletes */
	protected $soft_delete = FALSE;

	public function __construct()
	{
		parent::__construct();
		$this->load->database();
	}

	/* --------------------------------------------------------------------
	 * READ
	 * ----------------------------------------------------------------- */

	/** Get all rows, optionally filtered, with default ordering. */
	public function get_all($where = array(), $limit = NULL, $offset = 0)
	{
		if ( ! empty($where)) $this->db->where($where);
		if ($this->soft_delete) $this->db->where('deleted_at', NULL);
		if ($this->order_by) $this->db->order_by($this->order_by);
		if ($limit !== NULL) $this->db->limit($limit, $offset);

		return $this->db->get($this->table)->result_array();
	}

	/** Get a single row by primary key. */
	public function get($id)
	{
		$this->db->where($this->primary_key, $id);
		if ($this->soft_delete) $this->db->where('deleted_at', NULL);
		return $this->db->get($this->table)->row_array();
	}

	/** Get the first row matching a where clause. */
	public function get_by($where)
	{
		$this->db->where($where);
		if ($this->soft_delete) $this->db->where('deleted_at', NULL);
		return $this->db->get($this->table)->row_array();
	}

	/** Count rows matching an optional where clause. */
	public function count($where = array())
	{
		if ( ! empty($where)) $this->db->where($where);
		if ($this->soft_delete) $this->db->where('deleted_at', NULL);
		return $this->db->count_all_results($this->table);
	}

	/* --------------------------------------------------------------------
	 * WRITE
	 * ----------------------------------------------------------------- */

	/** Insert a row, returning the new insert ID. */
	public function insert($data)
	{
		if ($this->has_column('created_at') && ! isset($data['created_at']))
		{
			$data['created_at'] = date('Y-m-d H:i:s');
		}
		$this->db->insert($this->table, $data);
		return $this->db->insert_id();
	}

	/** Update a row by primary key. */
	public function update($id, $data)
	{
		if ($this->has_column('updated_at'))
		{
			$data['updated_at'] = date('Y-m-d H:i:s');
		}
		$this->db->where($this->primary_key, $id);
		return $this->db->update($this->table, $data);
	}

	/** Update rows matching a where clause. */
	public function update_where($where, $data)
	{
		$this->db->where($where);
		return $this->db->update($this->table, $data);
	}

	/** Delete a row (soft delete if enabled). */
	public function delete($id)
	{
		if ($this->soft_delete)
		{
			return $this->update($id, array('deleted_at' => date('Y-m-d H:i:s')));
		}
		$this->db->where($this->primary_key, $id);
		return $this->db->delete($this->table);
	}

	/** Count all rows in the table. */
	public function count_all()
	{
		return $this->db->count_all_results($this->table);
	}

	/** Count rows matching a where clause. */
	public function count_where($where = array())
	{
		if ( ! empty($where)) $this->db->where($where);
		return $this->db->count_all_results($this->table);
	}

	/** Reorder rows: accepts an array of [id => sort_order]. */
	public function reorder($pairs)
	{
		foreach ($pairs as $id => $order)
		{
			$this->db->where($this->primary_key, (int) $id)
				->update($this->table, array('sort_order' => (int) $order));
		}
		return TRUE;
	}

	/* --------------------------------------------------------------------
	 * HELPERS
	 * ----------------------------------------------------------------- */

	/** Check whether the table has a given column (cached). */
	protected function has_column($column)
	{
		static $cache = array();
		if ( ! isset($cache[$this->table]))
		{
			$cache[$this->table] = $this->db->list_fields($this->table);
		}
		return in_array($column, $cache[$this->table]);
	}

	/** Expose the table name. */
	public function table()
	{
		return $this->table;
	}
}
