<?php

namespace Tests\Feature;

use App\Http\Controllers\DomainController;
use App\Models\Address;
use Database\Seeders\NodeHierarchy;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Tests\TestCase;

use App\Models\Domain;

class RoutingTest extends TestCase
{
	use DatabaseTransactions;

	private function zone(): Collection
	{
		$do = Domain::where('name','domain-a')->singleOrFail();
		$zo = $do->zones->where('zone_id',100)->pop();
		return $zo->addresses;
	}

	/**
	 * Test the ZC address.
	 *
	 * @return void
	 */
	public function test_zc()
	{
		//$this->seed(NodeHierarchy::class);

		$nodes = $this->zone();
		$this->assertEquals(52,$nodes->count());

		// Pick ZC without any session info - we have 0 children
		$ao = Address::findFTN('100:0/0@domain-a');
		$this->assertEquals($ao->role,DomainController::NODE_ZC);
		$this->assertCount(0,$ao->children);
		$this->assertNull($ao->parent());

		// Add session info, and we have 51 children
		$ao->system->sessions()->attach([$ao->zone_id=>['sespass'=>'ABCD']]);
		$ao = Address::findFTN('100:0/0@domain-a');
		$this->assertCount(51,$ao->children);

		// A node's parent should be the ZC
		$ao = Address::findFTN('100:10/0@domain-a');
		$this->assertEquals($ao->role,DomainController::NODE_NC);
		$this->assertEquals('100:0/0.0@domain-a',$ao->parent()->ftn);
		$ao = Address::findFTN('100:21/2001.0@domain-a');
		$this->assertEquals($ao->role,DomainController::NODE_ACTIVE);
		$this->assertEquals('100:0/0.0@domain-a',$ao->parent()->ftn);

		// Pick a NC and we have 10 less children
		$ao = Address::findFTN('100:10/0@domain-a');
		$this->assertEquals($ao->role,DomainController::NODE_NC);
		$ao->system->sessions()->attach([$ao->zone_id=>['sespass'=>'ABCD']]);
		$ao = Address::findFTN('100:10/0@domain-a');
		$this->assertCount(9,$ao->children);
		$ao = Address::findFTN('100:0/0@domain-a');
		$this->assertCount(41,$ao->children);

		// A node's parent should be the ZC
		$ao = Address::findFTN('100:20/0@domain-a');
		$this->assertEquals($ao->role,DomainController::NODE_NC);
		$this->assertEquals('100:0/0.0@domain-a',$ao->parent()->ftn);
		$ao = Address::findFTN('100:10/2001.0@domain-a');
		$this->assertEquals($ao->role,DomainController::NODE_ACTIVE);
		$this->assertEquals('100:10/0.0@domain-a',$ao->parent()->ftn);

		// Pick a Node and we have 1 less child
		$ao = Address::findFTN('100:21/2001.0@domain-a');
		$this->assertEquals($ao->role,DomainController::NODE_ACTIVE);
		$ao->system->sessions()->attach([$ao->zone_id=>['sespass'=>'ABCD']]);
		$ao = Address::findFTN('100:21/2001.0@domain-a');
		$this->assertNULL($ao->children);
		$ao = Address::findFTN('100:0/0@domain-a');
		$this->assertCount(40,$ao->children);

		// Define address on a HC and we have 3 less children
		$ao = Address::findFTN('100:21/1000.0@domain-a');
		$this->assertEquals($ao->role,DomainController::NODE_HC);
		$ao->system->sessions()->attach([$ao->zone_id=>['sespass'=>'ABCD']]);
		$ao = Address::findFTN('100:21/1000.0@domain-a');
		$this->assertCount(2,$ao->children);
		$ao = Address::findFTN('100:0/0@domain-a');
		$this->assertCount(37,$ao->children);

		// Define address on a NC and we have 10 less children
		$ao = Address::findFTN('100:20/0@domain-a');
		$this->assertEquals($ao->role,DomainController::NODE_NC);
		$ao->system->sessions()->attach([$ao->zone_id=>['sespass'=>'ABCD']]);
		$ao = Address::findFTN('100:0/0@domain-a');
		$this->assertCount(27,$ao->children);
	}

	/**
	 * Test the ZC address.
	 *
	 * @return void
	 */
	public function test_rc()
	{
		//$this->seed(NodeHierarchy::class);

		// Pick ZC without any session info - we have 0 children
		$ao = Address::findFTN('100:1/0@domain-a');
		$this->assertEquals($ao->role,DomainController::NODE_RC);
		$this->assertCount(0,$ao->children);

		// Add session info, and we have 51 children
		$ao->system->sessions()->attach([$ao->zone_id=>['sespass'=>'ABCD']]);
		$ao = Address::findFTN('100:1/0@domain-a');
		$this->assertCount(23,$ao->children);

		// Pick a NC and we have 10 less children
		$ao = Address::findFTN('100:10/0@domain-a');
		$this->assertEquals($ao->role,DomainController::NODE_NC);
		$ao->system->sessions()->attach([$ao->zone_id=>['sespass'=>'ABCD']]);
		$ao = Address::findFTN('100:10/0@domain-a');
		$this->assertCount(9,$ao->children);
		$ao = Address::findFTN('100:1/0@domain-a');
		$this->assertCount(13,$ao->children);

		// Pick a Node and we have 1 less child
		$ao = Address::findFTN('100:11/2001.0@domain-a');
		$this->assertEquals($ao->role,DomainController::NODE_ACTIVE);
		$ao->system->sessions()->attach([$ao->zone_id=>['sespass'=>'ABCD']]);
		$ao = Address::findFTN('100:11/2001.0@domain-a');
		$this->assertNULL($ao->children);
		$ao = Address::findFTN('100:1/0@domain-a');
		$this->assertCount(12,$ao->children);

		// Define address on a HC and we have 3 less children
		$ao = Address::findFTN('100:11/1000.0@domain-a');
		$this->assertEquals($ao->role,DomainController::NODE_HC);
		$ao->system->sessions()->attach([$ao->zone_id=>['sespass'=>'ABCD']]);
		$ao = Address::findFTN('100:11/1000.0@domain-a');
		$this->assertCount(2,$ao->children);
		$ao = Address::findFTN('100:1/0@domain-a');
		$this->assertCount(9,$ao->children);
	}

	/**
	 * Test the NC address.
	 *
	 * @return void
	 */
	public function test_nc()
	{
		//$this->seed(NodeHierarchy::class);

		// Pick a HC without any session info - we have 0 children
		$ao = Address::findFTN('100:20/0@domain-a');
		$this->assertEquals($ao->role,DomainController::NODE_NC);
		$this->assertCount(0,$ao->children);

		// Add session info, we have 10 children
		$ao->system->sessions()->attach([$ao->zone_id=>['sespass'=>'ABCD']]);
		$ao = Address::findFTN('100:20/0@domain-a');
		$this->assertCount(9,$ao->children);

		// Add session info to a hub, we have 3 less children
		$ao = Address::findFTN('100:20/2000@domain-a');
		$this->assertEquals($ao->role,DomainController::NODE_HC);
		$ao->system->sessions()->attach([$ao->zone_id=>['sespass'=>'ABCD']]);
		$ao = Address::findFTN('100:20/0@domain-a');
		$this->assertCount(6,$ao->children);

		// Add session info to a node, we have 1 less child
		$ao = Address::findFTN('100:20/1@domain-a');
		$this->assertEquals($ao->role,DomainController::NODE_ACTIVE);
		$ao->system->sessions()->attach([$ao->zone_id=>['sespass'=>'ABCD']]);
		$ao = Address::findFTN('100:20/0@domain-a');
		$this->assertCount(5,$ao->children);
	}

	/**
	 * Test the HC address.
	 *
	 * @return void
	 */
	public function test_hc()
	{
		//$this->seed(NodeHierarchy::class);

		// Pick a HC without any session info - we have 0 children
		$ao = Address::findFTN('100:20/2000@domain-a');
		$this->assertEquals($ao->role,DomainController::NODE_HC);
		$this->assertCount(0,$ao->children);

		// Add session info, we have 2 children
		$ao->system->sessions()->attach([$ao->zone_id=>['sespass'=>'ABCD']]);
		$ao = Address::findFTN('100:20/2000@domain-a');
		$this->assertCount(2,$ao->children);

		// Add session info to 1 child, we have 1 children
		$ao = Address::findFTN('100:20/2001@domain-a');
		$ao->system->sessions()->attach([$ao->zone_id=>['sespass'=>'ABCD']]);
		$ao = Address::findFTN('100:20/2000@domain-a');
		$this->assertCount(1,$ao->children);
	}

	public function test_node()
	{
		//$this->seed(NodeHierarchy::class);

		// Node with session details still doesnt have any children
		$ao = Address::findFTN('100:20/2001@domain-a');
		$this->assertEquals($ao->role,DomainController::NODE_ACTIVE);
		$ao->system->sessions()->attach([$ao->zone_id=>['sespass'=>'ABCD']]);
		$ao = Address::findFTN('100:20/2001@domain-a');
		$this->assertNULL($ao->children);
	}
}