<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;

use App\Traits\NextKey;
use App\Traits\PushNew;
use Leenooks\Carbon;

class InvoiceItem extends Model
{
	use NextKey,PushNew;
	const RECORD_ID = 'invoice_item';
	public $incrementing = FALSE;

	protected $table = 'ab_invoice_item';
	const CREATED_AT = 'date_orig';
	const UPDATED_AT = 'date_last';

	protected $dates = ['date_start','date_stop'];
	public $dateFormat = 'U';

	private $_tax = 0;

	public function invoice()
	{
		return $this->belongsTo(Invoice::class);
	}

	/**
	 * Product for this item
	 *
	 * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
	 */
	public function product()
	{
		return $this->belongsTo(Product::class);
	}

	public function service()
	{
		return $this->belongsTo(Service::class);
	}

	public function taxes()
	{
		return $this->hasMany(InvoiceItemTax::class);
	}

	/** ATTRIBUTES **/

	/**
	 * Start date for the invoice item line
	 *
	 * We need cast this value to a Leenooks\Carbon for access to startOfHalf() endOfHalf() methods
	 *
	 * @param $value
	 * @return Carbon
	 * @throws \Exception
	 */
	public function getDateStartAttribute($value)
	{
		if (! is_null($value))
			return Carbon::createFromTimestamp($value);
	}

	/**
	 * End date for the invoice item line
	 *
	 * We need cast this value to a Leenooks\Carbon for access to startOfHalf() endOfHalf() methods
	 *
	 * @param $value
	 * @return Carbon
	 * @throws \Exception
	 */
	public function getDateStopAttribute($value)
	{
		if (! is_null($value))
			return Carbon::createFromTimestamp($value);
	}

	public function getItemTypeNameAttribute()
	{
		$types = [
			1=>'Hardware',                          // *
			2=>'Service Relocation Fee',            // * Must have corresponding SERVICE_ID
			3=>'Service Change',                    // * Must have corresponding SERVICE_ID
			4=>'Service Connection',                // * Must have corresponding SERVICE_ID
			6=>'Service Cancellation',              // * Must have corresponding SERVICE_ID
			7=>'Extra Product/Service Charge',      // * Service Billing in advance, Must have corresponding SERVICE_ID
			8=>'Product Addition',                  // * Additional Product Customisation, Must have corresponding SERVICE_ID
			120=>'Credit/Debit Transfer',           // * SERVICE_ID is NULL, MODULE_ID is NULL, MODULE_REF is NULL : INVOICE_ID is NOT NULL
			123=>'Shipping',
			124=>'Late Payment Fee',                // * SERVICE_ID is NULL, MODULE_ID = CHECKOUT MODULE,
			125=>'Payment Fee',                     // * SERVICE_ID is NULL, MODULE_ID = CHECKOUT MODULE, MODULE_REF = CHECKOUT NAME
			126=>'Other',                           // * MODEL_ID should be a module
			127=>'Rounding',                        // * SERVICE_ID is NULL, MODULE_ID is NULL, MODULE_REF is NULL
		];

		switch ($this->item_type)
		{
			// * Line Charge Topic on Invoice.
			case 0:
				return sprintf('%s [%s]','Product/Service',
					$this->date_start == $this->date_stop ? $this->date_start->format('Y-m-d') : sprintf('%s -> %s',$this->date_start->format('Y-m-d'),$this->date_stop->format('Y-m-d')));

			// * Excess Service Item, of item 0, must have corresponding SERVICE_ID
			case 5:
				return sprintf('%s [%s] (%s)','Excess Usage',
					$this->date_start == $this->date_stop ? $this->date_start->format('Y-m-d') : sprintf('%s -> %s',$this->date_start->format('Y-m-d'),$this->date_stop->format('Y-m-d')),
					$this->module_text()
				);

			default:
				return ($this->module_id == 30 ? 'Additional Charge: ' : '').Arr::get($types,$this->item_type,'Unknown');
		}
	}

	public function getSubTotalAttribute()
	{
		return $this->quantity * $this->price_base;
	}

	public function getTaxAttribute()
	{
		if (! $this->_tax)
		{
			foreach ($this->taxes as $o)
			{
				$this->_tax += $o->amount;
			}
		}

		return $this->_tax;
	}

	public function getTotalAttribute()
	{
		return $this->tax + $this->sub_total;
	}

	/** FUNCTIONS **/

	/**
	 * Add taxes to this record
	 */
	public function addTaxes(Collection $taxes)
	{
		// Refuse to change an existing record
		if ($this->exists)
			throw new \Exception('Refusing to add Taxes to existing record');

		foreach($taxes as $to)
		{
			$iit = new InvoiceItemTax;
			$iit->tax_id = $to->id;
			$iit->amount = round($this->quantity*$this->price_base*$to->rate,3);
			$iit->site_id = 1;
			$this->taxes->push($iit);
		}
	}

	public function module_text()
	{
		switch ($this->module_id)
		{
			// Charges Module
			case 30: return Charge::findOrFail($this->module_ref)->name;

			default: abort(500,'Unable to handle '.$this->module_id);
		}

	}
}