<?php

namespace App\Console\Commands;

use App\Models\{Domain};
use App\Models\Address;
use Illuminate\Console\Command;

class ZoneCheck extends Command
{
	protected $signature = 'zone:check'
		.' {domain : Domain Name}'
		.' {--Z|zone= : Zone}';

	protected $description = 'Check that the addresses in a zone are configured correctly';

	public function handle()
	{
		$do = Domain::where('name',$this->argument('domain'))->singleOrFail();

		foreach ($do->zones->sortby('zone_id') as $zo) {
			if ($this->option('zone') && ($this->option('zone') != $zo->zone_id))
				continue;

			$this->warn('Zone: '.$zo->zone_id);
			$this->info(sprintf('- Our address(es): %s',our_address($do)->pluck('ftn4d')->join(',')));

			$this->table(['id','ftn','role','parent','region_id','host_id','hub_id','system','notes'],$zo->addresses()->FTNorder()->active()->with(['system'])->get()->transform(function($item) {
				return [
					'id'=>$item->id,
					'ftn'=>$item->ftn4d,
					'role'=>$item->role_name,
					'parent'=>$item->parent()?->ftn4d,
					'region_id'=>$item->region_id,
					'host_id'=>$item->host_id,
					'hub_id'=>$item->hub_id,
					'system'=>$item->system->name,
					'notes'=>$this->check($item),
				];
			}));
		}

		return Command::SUCCESS;
	}

	/**
	 * Check that an address is defined correctly
	 *
	 * @param Address $ao
	 * @return string
	 */
	private function check(Address $ao): string
	{
		// ZC address
		if ($ao->role === Address::NODE_ZC) {
			if (($ao->region_id === 0) && ($ao->host_id === 0) && ($ao->node_id === 0) && is_null($ao->hub_id) && ($ao->point_id === 0))
				return 'OK';

			else
				return 'INVALID ZC address';
		}

		// RC address
		if ($ao->role === Address::NODE_RC) {
			if ($ao->region_id && ($ao->region_id === $ao->host_id) && ($ao->node_id === 0) && is_null($ao->hub_id) && ($ao->point_id === 0))
				return 'OK';
			else
				return 'INVALID RC address';
		}

		// NC address
		if ($ao->role === Address::NODE_NC) {
			if (($ao->node_id === 0) && is_null($ao->hub_id) && ($ao->point_id === 0))
				return 'OK';
			else
				return 'INVALID NC address';
		}

		// HUB address
		if ($ao->role === Address::NODE_HC) {
			if (($ao->node_id !== 0) && is_null($ao->hub_id) && ($ao->point_id === 0))
				return 'OK';
			else
				return 'INVALID HUB address';
		}

		// POINT address
		if ($ao->role === Address::NODE_POINT) {
			if ($ao->point_id !== 0)
				return 'OK';
			else
				return 'INVALID POINT address';
		}

		if ($ao->region_id && ($ao->host_id === 0))
			return 'INVALID REGION NODE';

		return '';
	}
}