<?php

namespace App\Models\Service;

use Carbon\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;

use App\Interfaces\ServiceUsage;
use App\Models\Supplier\Broadband as SupplierBroadband;
use App\Models\Supplier\Type as SupplierType;
use App\Models\Usage\Broadband as UsageBroadband;
use App\Rules\IPv6_CIDR;

/**
 * Class Broadband (Service)
 * Services that are Internet Broadband
 */
class Broadband extends Type implements ServiceUsage
{
	private const LOGKEY = 'MSB';

	protected $table = 'service_broadband';

	/* INTERFACES */

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

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

	/**
	 * The usage information for broadband
	 *
	 * @return \Illuminate\Database\Eloquent\Relations\HasMany
	 * @todo rename to usage()
	 */
	public function traffic()
	{
		return $this->hasMany(UsageBroadband::class,'service_item_id');
	}

	/* ATTRIBUTES */

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

	/**
	 * The type of technology used to provide this Internet Service
	 *
	 * @param $value
	 * @return null|string
	 */
	public function getTechnologyAttribute($value): ?string
	{
		return $value ?: $this->supplied()->technology;
	}

	/* OVERRIDES */

	/**
	 * Service update validation
	 *
	 * @return array
	 */
	public function validation(): array
	{
		return [
			'service_number' => 'nullable|string|min:10|max:11',
			'service_address' => 'nullable|string|min:5',
			'service_username' => 'exclude_without:pppoe|nullable|string|min:3',
			'service_password' => 'exclude_without:pppoe|nullable|string|min:8',
			'pppoe' => 'nullable|in:on',
			'connect_at' => 'nullable|date',
			'start_at' => 'nullable|date',
			'expire_at' => 'nullable|date|after:start_at',
			'ipaddress' => 'nullable|ipv4',
			'ip6address' => ['nullable',new IPv6_CIDR],
		];
	}

	/* METHODS */

	/**
	 * Return the suppliers offering that this service is providing
	 *
	 * @return SupplierType
	 * @todo This column provided_adsl_plan_id should either be deprecated or renamed.
	 */
	public function supplied(): SupplierType
	{
		return $this->provided_adsl_plan_id
			? SupplierBroadband::findOrFail($this->provided_adsl_plan_id)
			: $this->service->offering->supplied;
	}

	/**
	 * 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();

		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 UsageBroadband|null
	 */
	private function usage_last_date(): ?UsageBroadband
	{
		return $this->traffic()
			->orderBy('date','DESC')
			->limit(1)
			->get()
			->first();
	}

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

		if (! $maxdate)
			return collect();

		// 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);
		}

		$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;
	}
}