<?php

namespace App\Models;

use AgliPanci\LaravelCase\Facades\CaseBuilder;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;

use App\Casts\CompressedString;
use App\Traits\{QueryCacheableConfig,ScopeActive};

class Domain extends Model
{
	use HasFactory,ScopeActive,QueryCacheableConfig;

	private const CACHE_TIME = 3600;
	private const STATS_MONTHS = 6;

	protected $casts = [
		'homepage' => CompressedString::class,
	];

	/* SCOPES */

	/**
	 * Only query active records
	 */
	public function scopePublic($query)
	{
		return $query->where('public',TRUE);
	}

	/* RELATIONS */

	public function echoareas()
	{
		return $this->hasMany(Echoarea::class);
	}

	public function fileareas()
	{
		return $this->hasMany(Filearea::class);
	}

	public function nodelist_filearea()
	{
		return $this->belongsTo(Filearea::class);
	}

	public function zones()
	{
		return $this->hasMany(Zone::class);
	}

	/* ATTRIBUTES */

	public function getHomePageAttribute(?string $value): string
	{
		//0xFD2FB528
		return $this->castAttribute('homepage',$value) ?: 'No available information at the moment.';
	}

	/* METHODS */

	/**
	 * Get some message area stats for this domain
	 *
	 * @param bool $byarea
	 * @param Collection|NULL $systems
	 * @return Collection
	 */
	public function daily_area_stats(bool $byarea=FALSE,Collection $systems=NULL): Collection
	{
		if (! $this->echoareas->count())
			return collect();

		$echostats = Echomail::cacheFor(self::CACHE_TIME)->select([DB::raw('datetime::date as date'),'echoarea_id','echoareas.name',DB::raw('COUNT(*)')])
				->join('echoareas',['echoareas.id'=>'echomails.echoarea_id'])
				->join('domains',['domains.id'=>'echoareas.domain_id'])
				->where('domain_id',$this->id)
				->when($systems?->count(),function($query) use ($systems) { return $query->whereIn('fftn_id',$systems->pluck('addresses')->flatten()->pluck('id')->toArray()); })
				->where('datetime','>=',Carbon::now()->subMonths(self::STATS_MONTHS)->startOfMonth())
				->groupBy(['echoarea_id','echoareas.name','date'])
				->orderBy('date')
				->orderBy('echoareas.name')
				->with(['echoarea'])
				->get();

		if ($byarea)
			return $echostats
				->sortBy('name')
				->groupBy(['echoarea_id'])
				->map(function($item,$key) {
					return [
						'name' => $item->first()->echoarea->name,
						'data' => $item->groupby('date')->map(function($item) {
							return [
								'x' => Carbon::create($item->first()->date)->timestamp*1000,
								'y' => $item->sum('count')
							];
						})->values(),
						'dashStyle' => 'ShortDot',
						'visible'=>(bool)$item->first()->echoarea->show,
					];
				})->values();

		else
			return $echostats
				->groupBy('date')
				->map(function($item) { return ['x'=>Carbon::create($item->first()->date)->timestamp*1000,'y'=>$item->sum('count')]; })
				->values();
	}

	public function echoarea_stats(): Collection
	{
		$dt = Carbon::now()->startOfday();
		$case = CaseBuilder::whenRaw("datetime >= '?'",$dt->subDay()->format('Y-m-d'))->thenRaw("'day'")
			->whenRaw("datetime >= '?'",$dt->subDays(7)->format('Y-m-d'))->thenRaw("'week'")
			->whenRaw("datetime >= '?'",$dt->subMonth()->format('Y-m-d'))->thenRaw("'month'")
			->elseRaw("'all'");

		return Echoarea::cacheFor(self::CACHE_TIME)
			->select(['echoareas.id','name','description','active',DB::raw('count(echomails.id) AS count'),DB::raw('max(datetime) as last_message')])
			->selectRaw($case->toRaw().' AS stats')
			->join('echomails',['echomails.echoarea_id'=>'echoareas.id'],NULL,NULL,'left outer')
			->where('domain_id',$this->id)
			->groupBy('echoareas.id')
			->groupBy('echoareas.name')
			->groupBy('stats')
			->orderBy('echoareas.name')
			->orderBy('last_message','DESC')
			->get();
	}

	/**
	 * Determine if this zone is managed by this host
	 *
	 * @return bool
	 */
	public function managed(): bool
	{
		static $so = NULL;

		if (is_null($so))
			$so = Setup::findOrFail(config('app.id'));

		return $so
			->system
			->addresses
			->where('zone.domain.active',TRUE)
			->pluck('zone.domain_id')
			->contains($this->id);
	}
}