<?php

use PHPUnit\Framework\TestCase;

class containercontentTest extends TestCase
{

	static int $now;
	private static mixed $outerContainer;
	private static mixed $innerContainer;

	/**
     */
    protected function setUp(): void
    {
        database::connect();
		database::begin();
        try {
			$now=time();
			static::$now=$now;
            session::init(new DummySession());
            session::becomeAdmin();
			$user=user::create([
				'name'=>'user'.$now,
				'fullname'=>'user'.$now,
				'email'=>'user'.$now.'@bogus.bogus',
			])['created'];
            session::set('user', $user);
            session::set('userId', $user['id']);
			$outerCategory=containercategory::create([
				'name'=>'outerCategory'.$now,
			])['created'];
			$innerCategory=containercategory::create([
				'name'=>'innerCategory'.$now,
			])['created'];
			$outerType=containertype::create([
				'name'=>'outerContainerType'.$now,
				'containercategoryid'=>$outerCategory['id'],
				'positions'=>'5'
			])['created'];
			$innerType=containertype::create([
				'name'=>'innerContainerType'.$now,
				'containercategoryid'=>$innerCategory['id'],
				'positions'=>'5'
			])['created'];
			static::$outerContainer=container::create([
				'name'=>'outerContainer'.$now,
				'containertypeid'=>$outerType['id']
			])['created'];
			static::$innerContainer=container::create([
				'name'=>'innerContainer'.$now,
				'containertypeid'=>$innerType['id']
			])['created'];
        } catch (BadRequestException $e) {
            echo $e->getMessage();
			echo $e->getTraceAsString();
            $this->fail('BadRequestException on setup');
        } catch (NotFoundException $e) {
			echo $e->getTraceAsString();
            $this->fail('NotFoundException on setup');
        } catch (ServerException $e) {
			echo $e->getTraceAsString();
            $this->fail('ServerException on setup');
        }
        session::revokeAdmin();
    }

    protected function tearDown(): void {
        database::abort();
        session::destroy();
    }

	/**
	 * @throws BadRequestException
	 * @throws ServerException
	 */
    public function testCanCreateAsAdmin(){
        session::becomeAdmin();
        self::assertTrue(containercontent::canCreate(), 'containercategory::canCreate() returned false as admin');
    }

    /**
     * @throws NotFoundException
     * @throws BadRequestException
     * @throws ForbiddenException
     * @throws ServerException
     */
    public function testCanCreateAsTechnician(){
        session::becomeAdmin();
        $group=usergroup::getByName(usergroup::TECHNICIANS);
        groupmembership::create(array('userid'=>session::getUserId(), 'usergroupid'=>$group['id']));
        session::revokeAdmin();
        session::refreshProjectPermissions();
        self::assertTrue(containercontent::canCreate(), 'containercategory::canCreate() returned false as technician');
    }

	/**
	 * @return void
	 * @throws BadRequestException
	 * @throws NotFoundException
	 * @throws ServerException
	 */
    public function testCanCreateAsNonAdmin(){
        self::assertFalse(containercontent::canCreate(), 'containercontent::canCreate() returned true as regular user');
    }

    /**
     * @throws NotFoundException
     * @throws BadRequestException
     * @throws ForbiddenException
     * @throws ServerException
     */
    public function testCreateAsAdmin(){
        session::becomeAdmin();
        $created=containercontent::create(array(
			'name'=>'Test'.static::$now,
			'parent'=>static::$outerContainer['id'],
			'child'=>static::$innerContainer['id'],
			'position'=>1
        ))['created'];
        session::revokeAdmin();
        self::assertNotEmpty($created);
    }

    /**
     * @throws NotFoundException
     * @throws BadRequestException
     * @throws ForbiddenException
     * @throws ServerException
     */
    public function testCreateAsTechnician(){
        session::becomeAdmin();
        $group=usergroup::getByName(usergroup::TECHNICIANS);
        groupmembership::create(array('userid'=>session::getUserId(), 'usergroupid'=>$group['id']));
        session::revokeAdmin();
        session::refreshProjectPermissions();
		$created=containercontent::create(array(
			'name'=>'Test'.static::$now,
			'parent'=>static::$outerContainer['id'],
			'child'=>static::$innerContainer['id'],
			'position'=>1
		))['created'];
		session::revokeAdmin();
		self::assertNotEmpty($created);
    }

	/**
	 * @throws ForbiddenException
	 * @throws BadRequestException
	 * @throws NotFoundException
	 * @throws ServerException
	 */
	public function testCreateAsNonAdmin(){
		$created=containercontent::create(array(
			'name'=>'Test'.static::$now,
			'parent'=>static::$outerContainer['id'],
			'child'=>static::$innerContainer['id'],
			'position'=>1
		))['created'];
		self::assertNotEmpty($created);
	}

	/**
	 * @throws NotFoundException
	 * @throws BadRequestException
	 * @throws ForbiddenException
	 * @throws ServerException
	 */
	public function testFishingActions() {
		session::becomeAdmin();
		$sharedProjectId=baseproject::getSharedProjectId();
		$scoringSystem=crystalscoringsystem::create([
			'name'=>'ss'.static::$now,
		])['created'];
		crystalscore::create([
			'crystalscoringsystemid'=>$scoringSystem['id'],
			'name'=>'cs'.static::$now,
			'label'=>'Crystals',
			'color'=>'ff0000',
			'scoreindex'=>1,
			'hotkey'=>1
		]);
		$plateType=platetype::create([
			'projectid'=>$sharedProjectId,
			'name'=>'pt'.static::$now,
			'rows'=>3,
			'cols'=>4,
			'subs'=>3,
			'dropmapping'=>'123,RRR'
		])['created'];
		$plate=plate::create([
			'platetypeid'=>$plateType['id'],
			'name'=>'pl'.static::$now,
			'projectid'=>$sharedProjectId,
			'ownerid'=>session::getUserId(),
			'crystalscoringsystemid'=>$scoringSystem['id']
		])['created'];
		$wellDrops=plate::getwelldrops($plate['id']);
		self::assertNotEmpty($wellDrops);
		$wellDrop=$wellDrops['rows'][0];
		$dewarType=containertype::getByName('Dewar');
		self::assertNotEmpty($dewarType);
		$puckType=containertype::getByName('Unipuck');
		self::assertNotEmpty($puckType);
		$pinType=containertype::getByName('Pin');
		self::assertNotEmpty($pinType);
		$dewar=container::create([
			'name'=>'dewar'.static::$now,
			'containertypeid'=>$dewarType['id']
		])['created'];
		$puck=container::create([
			'name'=>'puck'.static::$now,
			'containertypeid'=>$puckType['id']
		])['created'];
		$pin1=container::create([
			'name'=>'pin1'.static::$now,
			'containertypeid'=>$pinType['id']
		])['created'];
		$pin2=container::create([
			'name'=>'pin2'.static::$now,
			'containertypeid'=>$pinType['id']
		])['created'];
		$imager=imager::create([
			'name'=>'imager'.static::$now,
			'friendlyname'=>'imager'.static::$now,
			'manufacturer'=>'Test',
			'temperature'=>20,
			'platecapacity'=>1000,
			'alertlevel'=>950,
			'warninglevel'=>980
		])['created'];
		$imagingParameters=imagingparameters::create([
			'projectid'=>$sharedProjectId,
			'manufacturerdatabaseid'=>42069,
			'manufacturer'=>'Test',
			'name'=>'ip'.static::$now
		])['created'];
		$imagingParametersVersion=imagingparametersversion::create([
			'projectid'=>$sharedProjectId,
			'manufacturerdatabaseid'=>42069,
			'imagingparametersid'=>$imagingParameters['id'],
			'name'=>'ipv'.static::$now
		])['created'];
		$imagingSession=imagingsession::create([
			'name'=>'is'.static::$now,
			'manufacturerdatabaseid'=>42069,
			'imagingparametersversionid'=>$imagingParametersVersion['id'],
			'imageddatetime'=>'2021-12-31 22:33:44',
			'lighttype'=>'bogus',
			'plateid'=>$plate['id'],
			'imagerid'=>$imager['id']
		])['created'];
		$dropImage=dropimage::create([
			'name'=>'IMAGE'.static::$now,
			'welldropid'=>$wellDrop['id'],
			'projectid'=>$sharedProjectId,
			'imagestorepath'=>rtrim(__DIR__,'/').'/../../../',
			'imagepath'=>'client/images/dummyimage.jpg',
			'thumbnailpath'=>'client/images/dummythumb.jpg',
			'imagingsessionid'=>$imagingSession['id']
		])['created'];
		$crystal1=crystal::create([
			'name'=>'c1'.static::$now,
			'projectid'=>$sharedProjectId,
			'prefix'=>'a',
			'welldropid'=>$wellDrop['id'],
			'allowcreatedummyinspection'=>true,
			'dropimageid'=>$dropImage['id'],
			'numberindrop'=>1
		])['created'];
		sleep(1); //otherwise duplicate crystal name
		$crystal2=crystal::create([
			'name'=>'c2'.static::$now,
			'projectid'=>$sharedProjectId,
			'prefix'=>'a',
			'welldropid'=>$wellDrops['rows'][1]['id'],
			'dropimageid'=>$dropImage['id'],
			'numberindrop'=>2
		])['created'];
		session::revokeAdmin();

		sleep(1); //otherwise duplicate crystal name

		//Fish welldrop into puck
		containercontent::create([
			'parent'=>$puck['id'],
			'child'=>$wellDrop['id'],
			'position'=>1
		]);

		session::revokeAdmin();

		//Fish crystal into puck
		containercontent::create([
			'parent'=>$puck['id'],
			'child'=>$crystal1['id'],
			'position'=>2
		]);

		session::revokeAdmin();
		sleep(1); //otherwise duplicate crystal name

		//Fish welldrop into pin
		containercontent::create([
			'parent'=>$pin1['id'],
			'child'=>$wellDrop['id'],
			'position'=>1
		]);

		session::revokeAdmin();

		//Fish crystal into pin
		containercontent::create([
			'parent'=>$pin2['id'],
			'child'=>$crystal2['id'],
			'position'=>1
		]);

		session::revokeAdmin();
		//Fish pin into puck
		containercontent::create([
			'parent'=>$puck['id'],
			'child'=>$pin2['id'],
			'position'=>5
		]);
		sleep(1); //otherwise duplicate crystal name

		session::revokeAdmin();
		//Fish puck into dewar
		containercontent::create([
			'parent'=>$dewar['id'],
			'child'=>$puck['id'],
			'position'=>1
		]);
	}

	/**
	 * @throws BadRequestException
	 * @throws ForbiddenException
	 * @throws ServerException
	 * @throws NotFoundException
	 */
	public function testDeleteAsAdmin() {
		session::becomeAdmin();
		$content=containercontent::create([
			'parent'=>static::$outerContainer['id'],
			'child'=>static::$innerContainer['id'],
			'position'=>1
		])['created'];
		self::assertIsArray($content);
		self::assertArrayHasKey('id', $content);
		containercontent::delete($content['id']);
		$content=containercontent::getById($content['id']);
		self::assertEmpty($content);
	}

	/**
	 * @throws NotFoundException
	 * @throws BadRequestException
	 * @throws ForbiddenException
	 * @throws ServerException
	 */
	public function testDeleteAsTechnician() {
		session::becomeAdmin();
		$group=usergroup::getByName(usergroup::TECHNICIANS);
		groupmembership::create(array('userid'=>session::getUserId(), 'usergroupid'=>$group['id']));
		$content=containercontent::create([
			'parent'=>static::$outerContainer['id'],
			'child'=>static::$innerContainer['id'],
			'position'=>1
		])['created'];
		session::revokeAdmin();
		session::refreshProjectPermissions();
		self::assertIsArray($content);
		self::assertArrayHasKey('id', $content);
		containercontent::delete($content['id']);
		$content=containercontent::getById($content['id']);
		self::assertEmpty($content);
	}

	/**
	 * @throws BadRequestException
	 * @throws ForbiddenException
	 * @throws ServerException
	 * @throws NotFoundException
	 */
	public function testDeleteAsUser() {
		session::revokeAdmin();
		$content=containercontent::create([
			'parent'=>static::$outerContainer['id'],
			'child'=>static::$innerContainer['id'],
			'position'=>1
		])['created'];
		self::assertIsArray($content);
		self::assertArrayHasKey('id', $content);
		containercontent::delete($content['id']);
		$content=containercontent::getById($content['id']);
		self::assertEmpty($content);
	}

	/**
	 * @throws BadRequestException
	 * @throws ForbiddenException
	 * @throws ServerException
	 * @throws NotFoundException
	 */
	public function testUpdateAsAdmin() {
		session::becomeAdmin();
		$content=containercontent::create([
			'parent'=>static::$outerContainer['id'],
			'child'=>static::$innerContainer['id'],
			'position'=>1
		])['created'];
		self::assertIsArray($content);
		self::assertArrayHasKey('id', $content);
		containercontent::update($content['id'],['position'=>3]);
		$content=containercontent::getById($content['id']);
		self::assertNotEmpty($content);
		self::assertEquals(3, $content['position']);
	}

	/**
	 * @throws BadRequestException
	 * @throws ForbiddenException
	 * @throws ServerException
	 * @throws NotFoundException
	 */
	public function testUpdateAsUser() {
		session::revokeAdmin();
		$content=containercontent::create([
			'parent'=>static::$outerContainer['id'],
			'child'=>static::$innerContainer['id'],
			'position'=>1
		])['created'];
		self::assertIsArray($content);
		self::assertArrayHasKey('id', $content);
		containercontent::update($content['id'],['position'=>3]);
		$content=containercontent::getById($content['id']);
		self::assertNotEmpty($content);
		self::assertEquals(3, $content['position']);
	}

}