<?php

namespace App\Models\Service;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Leenooks\Carbon as LeenooksCarbon;

use App\Interfaces\ServiceItem;
use App\Models\{Account,Service};
use App\Models\Supplier\Type as SupplierType;
use App\Traits\{ScopeAccountUserAuthorised,ScopeServiceActive};

abstract class Type extends Model implements ServiceItem
{
	use ScopeAccountUserAuthorised,ScopeServiceActive;

	protected $casts = [
		'connect_at' => 'datetime:Y-m-d',
		'expire_at' => 'datetime:Y-m-d',
	];

	public $timestamps = FALSE;

	public function __get($key): mixed
	{
		return match ($key) {
			'contract_term' => $this->service->offering->contract_term,
			'has_expired' => (! $this->in_contract) && ($this->service->invoice_next && $this->service->invoice_next->isPast()),
			'in_contract' => $this->expire_at && $this->expire_at->isFuture(),

			default => parent::__get($key),
		};
	}

	/* RELATIONS */

	/**
	 * Account this service belongs to
	 * @return \Illuminate\Database\Eloquent\Relations\HasOneThrough
	 */
	public function account()
	{
		return $this->hasOneThrough(Account::class,Service::class);
	}

	/**
	 * @NOTE: The service_id column could be discarded, if the id column=service_id
	 * @return \Illuminate\Database\Eloquent\Relations\MorphOne
	 */
	public function service()
	{
		return $this->morphOne(Service::class,'type','model','id','service_id');
	}

	public function traffic()
	{
		// Return a null relationship by default, if the child class doesnt track usage (and thus no usage table)
		return $this->hasMany(Generic::class,'id')
			->where('id',NULL)
			->where('site_id',$this->site_id);
	}

	/* ATTRIBUTES */

	/**
	 * We need to cast some dates to LeenooksCarbon to get access to startOfHalf()/endOfHalf() methods
	 *
	 * @param $value
	 * @return LeenooksCarbon|null
	 */
	public function getExpireAtAttribute($value): ?LeenooksCarbon
	{
		return $value ? LeenooksCarbon::create($value) : NULL;
	}

	public function getServiceExpireAttribute(): ?LeenooksCarbon
	{
		return $this->expire_at ?: $this->service->invoice_next_at;
	}

	/* METHODS */

	/**
	 * The supplier's service that we provide
	 *
	 * @return SupplierType
	 */
	public function supplied(): SupplierType
	{
		return $this->service->offering->supplied ?: new \App\Models\Supplier\Generic();
	}

	/**
	 * Default usage summary is empty if the underlying model doesnt capture usage
	 *
	 * @param int $months
	 * @return Collection
	 */
	public function usage_summary(int $months=2): Collection
	{
		return collect();
	}

	/**
	 * Validation used to accept form input
	 *
	 * @return mixed
	 */
	public function validation(): array
	{
		return [];
	}
}