<?php

namespace App\Models;

use CodeIgniter\Database\ResultInterface;
use CodeIgniter\Model;
use stdClass;

/**
 * Tax class
 */
class Tax extends Model
{
	protected $table = 'tax_rates';
	protected $primaryKey = 'tax_rate_id';
	protected $useAutoIncrement = true;
	protected $useSoftDeletes = false;
	protected $allowedFields = [
		'rate_tax_code_id',
		'rate_tax_category_id',
		'rate_jurisdiction_id',
		'tax_rate',
		'tax_rounding_code'
	];

	/**
	 * Determines if a given row is on file
	 */
	public function exists(int $tax_rate_id): bool
	{
		$builder = $this->db->table('tax_rates');
		$builder->where('tax_rate_id', $tax_rate_id);

		return ($builder->get()->getNumRows() == 1);	//TODO: ===
	}

	/**
	 * Gets total of rows
	 */
	public function get_total_rows(): int
	{
		$builder = $this->db->table('tax_rates');

		return $builder->countAllResults();
	}

	/**
	 * Gets list of tax rates that are assigned to a particular tax category
	 */
	public function get_tax_category_usage(int $tax_category_id): int
	{
		$builder = $this->db->table('tax_rates');
		$builder->where('rate_tax_category_id', $tax_category_id);

		return $builder->countAllResults();
	}

	/**
	 * Gets the row for a particular id
	 */
	public function get_info(int $tax_rate_id): object
	{
		$builder = $this->db->table('tax_rates');
		$builder->select('tax_rate_id');
		$builder->select('rate_tax_code_id');
		$builder->select('tax_code');
		$builder->select('tax_code_name');
		$builder->select('rate_jurisdiction_id');
		$builder->select('jurisdiction_name');
		$builder->select('rate_tax_category_id');
		$builder->select('tax_category');
		$builder->select('tax_rate');
		$builder->select('tax_rounding_code');

		$builder->join('tax_codes',
			'rate_tax_code_id = tax_code_id', 'LEFT');
		$builder->join('tax_categories',
			'rate_tax_category_id = tax_category_id', 'LEFT');
		$builder->join('tax_jurisdictions',
			'rate_jurisdiction_id = jurisdiction_id', 'LEFT');
		$builder->where('tax_rate_id', $tax_rate_id);

		$query = $builder->get();

		if($query->getNumRows() == 1)	//TODO: probably should use === here since getNumRows() returns an int.
		{
			return $query->getRow();
		}
		else
		{
			//Get empty base parent object
			$tax_rate_obj = new stdClass();
			$tax_rate_obj->tax_rate_id = null;
			$tax_rate_obj->rate_tax_code_id = null;
			$tax_rate_obj->tax_code = '';
			$tax_rate_obj->tax_code_name = '';
			$tax_rate_obj->rate_tax_category_id = null;
			$tax_rate_obj->tax_category = '';
			$tax_rate_obj->tax_rate = 0.0;
			$tax_rate_obj->tax_rounding_code = '0';
			$tax_rate_obj->rate_jurisdiction_id = null;
			$tax_rate_obj->jurisdiction_name = '';

			return $tax_rate_obj;
		}
	}

	/**
	 * Get taxes to be collected for a given tax code
	 */
	 public function get_taxes(int $tax_code_id, int $tax_category_id): array
	 {
		 $sql = 'select tax_rate_id, rate_tax_code_id, tax_code, tax_code_name, tax_type, cascade_sequence, rate_tax_category_id, tax_category, 
			rate_jurisdiction_id, jurisdiction_name, tax_group, tax_rate, tax_rounding_code,tax_categories.tax_group_sequence + tax_jurisdictions.tax_group_sequence as tax_group_sequence 
			from ' . $this->db->prefixTable('tax_rates') . ' 
			left outer join ' . $this->db->prefixTable('tax_codes') . ' on rate_tax_code_id = tax_code_id 
			left outer join ' . $this->db->prefixTable('tax_categories') . ' as tax_categories on rate_tax_category_id = tax_category_id 
			left outer join ' . $this->db->prefixTable('tax_jurisdictions') . ' as tax_jurisdictions on rate_jurisdiction_id = jurisdiction_id 
			where rate_tax_code_id = ' . $this->db->escape($tax_code_id) . ' and rate_tax_category_id = ' . $this->db->escape($tax_category_id) . '
			order by cascade_sequence, tax_group, jurisdiction_name, tax_jurisdictions.tax_group_sequence + tax_categories.tax_group_sequence';

		$query = $this->db->query($sql);

		return $query->getResultArray() ?: [];
	}

	/**
	 * Gets information about a particular tax_code
	 */
	public function get_rate_info(int $tax_code_id, int $tax_category_id): object
	{
		$builder = $this->db->table('tax_rates');
		$builder->join('tax_categories', 'rate_tax_category_id = tax_category_id');
		$builder->where('rate_tax_code_id', $tax_code_id);
		$builder->where('rate_tax_category_id', $tax_category_id);

		$query = $builder->get();

		if($query->getNumRows() == 1)	//TODO: this should probably be ===
		{
			return $query->getRow();
		}
		else
		{
			//Get empty base parent object
			$tax_rate_obj = new stdClass();

			//Get all the fields from tax_codes table
			foreach($this->db->getFieldNames('tax_rates') as $field)
			{
				$tax_rate_obj->$field = '';
			}
			//Get all the fields from tax_rates table
			foreach($this->db->getFieldNames('tax_categories') as $field)
			{
				$tax_rate_obj->$field = '';
			}

			return $tax_rate_obj;
		}
	}

	/**
	Inserts or updates a tax_rates entry
	*/
	public function save_value(array &$tax_rate_data, int $tax_rate_id = NEW_ENTRY): bool
	{
		$builder = $this->db->table('tax_rates');
		if($tax_rate_id == NEW_ENTRY || !$this->exists($tax_rate_id))
		{
			if($builder->insert($tax_rate_data))
			{
				$tax_rate_data['tax_rate_id'] = $this->db->insertID();

				return true;
			}
		}
		else
		{
			$builder->where('tax_rate_id', $tax_rate_id);

			if($builder->update($tax_rate_data))
			{
				return true;
			}
		}

		return false;
	}

	/**
	 * Deletes a single tax rate entry
	 */
	public function delete($tax_rate_id = null, bool $purge = false): bool
	{
		$builder = $this->db->table('tax_rates');

		return $builder->delete(['tax_rate_id' => $tax_rate_id]);
	}

	/**
	 * Deletes a list of tax rates
	 */
	public function delete_list(array $tax_rate_ids): bool
	{
		$builder = $this->db->table('tax_rates');
		$builder->whereIn('tax_rate_id', $tax_rate_ids);

		return $builder->delete();
	}

	/**
	 * Gets tax_codes
	 */
	public function get_found_rows(string $search): int
	{
		return $this->search($search, 0, 0, 'tax_code_name', 'asc', true);
	}

	/**
	 * Performs a search on tax_rates
	 */
	public function search(string $search, ?int $rows = 0, ?int $limit_from = 0, ?string $sort = 'tax_code_name', ?string $order = 'asc', ?bool $count_only = false)
	{
		// Set default values
		if($rows == null) $rows = 0;
		if($limit_from == null) $limit_from = 0;
		if($sort == null) $sort = 'tax_code_name';
		if($order == null) $order = 'asc';
		if($count_only == null) $count_only = false;

		$builder = $this->db->table('tax_rates');

		// get_found_rows case
		if($count_only)
		{
			$builder->select('COUNT(tax_rate_id) as count');
		} else
		{
			$builder->select('tax_rate_id');
			$builder->select('tax_code');
			$builder->select('rate_tax_code_id');
			$builder->select('tax_code_name');
			$builder->select('rate_jurisdiction_id');
			$builder->select('jurisdiction_name');
			$builder->select('rate_tax_category_id');
			$builder->select('tax_category');
			$builder->select('tax_rate');
			$builder->select('tax_rounding_code');
		}

		$builder->join('tax_codes', 'rate_tax_code_id = tax_code_id', 'LEFT');
		$builder->join('tax_categories', 'rate_tax_category_id = tax_category_id', 'LEFT');
		$builder->join('tax_jurisdictions', 'rate_jurisdiction_id = jurisdiction_id', 'LEFT');

		if(!empty($search))
		{
			$builder->like('rate_tax_code', $search);
			$builder->orLike('tax_code_name', $search);
		}

		// get_found_rows case
		if($count_only)
		{
			return $builder->get()->getRow()->count;
		}

		$builder->orderBy($sort, $order);

		if($rows > 0)
		{
			$builder->limit($rows, $limit_from);
		}

		return $builder->get();
	}

	/**
	 * @param string $tax_code_type
	 * @return string
	 */
	public function get_tax_code_type_name(string $tax_code_type): string	//TODO: if this is being called from the view and passed through GET params then it will come through as a string... better if we can get it as an int though.
	{
		if($tax_code_type == '0')	//TODO: ===.  Also, replace this with ternary notation. The whole function becomes a nice one-liner.
		{
			return lang('Taxes.tax_included');
		}
		else
		{
			return lang('Taxes.tax_excluded');
		}
	}

	/**
	 * @param int $tax_category_id
	 * @return string
	 */
	public function get_tax_category(int $tax_category_id): string
	{
		$builder = $this->db->table('tax_categories');
		$builder->select('tax_category');
		$builder->where('tax_category_id', $tax_category_id);

		return $builder->get()->getRow()->tax_category;
	}

	/**
	 * @return ResultInterface
	 */
	public function get_all_tax_categories(): ResultInterface
	{
		$builder = $this->db->table('tax_categories');
		$builder->orderBy('tax_category_id');

		return $builder->get();
	}

	/**
	 * @param string $tax_category
	 * @return int
	 */
	public function get_tax_category_id(string $tax_category): int	//TODO: $tax_category is not used in this function and get_tax_category_id() is not called in the code.  It may be that this needs to be deprecated and removed.
	{
		$builder = $this->db->table('tax_categories');
		$builder->select('tax_category_id');

		return $builder->get()->getRow()->tax_category_id;
	}
}
