<?php

namespace App\Models\Service;

use Illuminate\Support\Collection;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Leenooks\Carbon;

use App\Interfaces\{ServiceItem,ServiceUsage};
use App\Models\AdslSupplierPlan;
use App\Models\Base\ServiceType;
use App\Traits\NextKey;

class Adsl extends ServiceType implements ServiceItem,ServiceUsage
{
	private const LOGKEY = 'MSA';

	use NextKey;
	const RECORD_ID = 'service__adsl';

	protected $dates = [
		'service_connect_date',
		'service_contract_date'
	];
	protected $table = 'ab_service__adsl';

	/** RELATIONSHIPS **/

	/**
	 * The suppliers product
	 *
	 * @return \Illuminate\Database\Eloquent\Relations\HasOne
	 */
	public function product()
	{
		return $this
			->hasOne(AdslSupplierPlan::class,'id','adsl_supplier_plan_id')
			->withDefault(function() {
				$o = new AdslSupplierPlan;
			});
	}

	/**
	 * The accounts that this user manages
	 *
	 * @return \Illuminate\Database\Eloquent\Relations\HasMany
	 */
	public function traffic()
	{
		// @todo Need to include site_id in this relation
		return $this->hasMany(AdslTraffic::class,'ab_service_adsl_id');
	}

	/** SCOPES */

	/**
	 * Search for a record
	 *
	 * @param        $query
	 * @param string $term
	 * @return
	 */
	public function scopeSearch($query,string $term)
	{
		// Build our where clause
		return parent::scopeSearch($query,$term)
			->orwhere('service_number','like','%'.$term.'%')
			->orWhere('service_address','like','%'.$term.'%')
			->orWhere('ipaddress','like','%'.$term.'%');
	}

	/** ATTRIBUTES **/

	/**
	 * @deprecated use $o->service_name;
	 * @return mixed|string
	 */
	public function getNameAttribute()
	{
		return $this->service_number ?: $this->service_address;
	}

	/**
	 * Return the service address
	 *
	 * @return string
	 */
	public function getServiceDescriptionAttribute(): string
	{
		return strtoupper($this->service_address) ?: 'NO Service Address';
	}

	public function getServiceExpireAttribute(): \Carbon\Carbon
	{
		// TODO: Implement getServiceExpireAttribute() method.
	}

	/**
	 * Return the service number
	 *
	 * @return string
	 */
	public function getServiceNameAttribute(): string
	{
		return $this->service_number ?: $this->service_address;
	}

	/**
	 * Is this service currently in a contract
	 *
	 * @return bool
	 */
	public function inContract(): bool
	{
		return $this->service_contract_date AND $this->service_contract_date->addMonths($this->contract_term)->isFuture();
	}

	/**
	 * Return service usage data
	 *
	 * @param int $days
	 * @return Collection
	 */
	public function usage(int $days=31): Collection
	{
		$maxdate = $this->usage_last_date();

		if (! $maxdate)
			return collect();

		Log::debug(sprintf('%s:Getting Usage data for [%d] days from [%s]',self::LOGKEY,$days,$maxdate->date->format('Y-m-d')),['m'=>__METHOD__]);

		return $this->traffic()
			->where('date','<=',$maxdate->date->format('Y-m-d'))
			->where('date','>=',$maxdate->date->subDays($days)->format('Y-m-d'))
			->get();
	}

	/**
	 * Find the last date any traffic was recorded for a service
	 *
	 * @return AdslTraffic|null
	 */
	private function usage_last_date(): ?AdslTraffic
	{
		return $this->traffic
			->sortBy('date')
			->last();
	}

	public function usage_summary(int $months=2): Collection
	{
		$maxdate = $this->usage_last_date();

		if (! $maxdate)
			return collect();

		Log::debug(sprintf('%s:Getting Usage data for [%d] months from [%s]',self::LOGKEY,$months,$maxdate),['m'=>__METHOD__]);

		// Go back an extra month;
		$start = $maxdate->date->subMonths($months);

		// If we are before the 15th
		if ($start->day < 15) {
			$start = Carbon::createFromFormat('Y-m-d',$start->subMonth()->format('Y-m-').'15');
		} else {
			$start = $start->subDays($start->day-15);
		}

		Log::debug(sprintf('%s:Getting Usage data from [%s]',self::LOGKEY,$start->format('Y-m-d')),['m'=>__METHOD__]);

		$result = collect();

		foreach ($this->traffic()
			->where('date','>=',$start->format('Y-m-d'))
			->where('date','<=',$maxdate->date->format('Y-m-d'))
			->get()->groupBy(function($item) {
				return sprintf('%s->%s',$item->trafficMonthStart->format('d M'),$item->trafficMonthEnd->format('d M'));
		}) as $key => $o) {
			$result->put($key,$o->sum('total'));
		}

		return $result;
	}
}