<?php

use PHPUnit\Framework\TestCase;
use SHServ\Models\Timers;

class TimersTest extends TestCase {
	protected $tb;

	protected function setUp(): void {
		$this -> tb = app() -> thin_builder;
		$this -> tb -> query("
			CREATE TABLE shserv_timers (
				id INTEGER PRIMARY KEY AUTOINCREMENT,
				timer_alias TEXT,
				scope_name TEXT,
				target_type TEXT,
				target_alias TEXT,
				params TEXT,
				execute_at TEXT,
				status TEXT,
				error_message TEXT,
				created_at TEXT,
				executed_at TEXT
			)
		");
	}

	protected function tearDown(): void {
		$this -> tb -> query("DROP TABLE IF EXISTS shserv_timers");
	}

	public function test_create_and_get_pending(): void {
		$timers = new Timers();
		$result = $timers -> create_timer("test_off", "LightHubScope", "action", "kitchen_light_switcher", [], time() - 1);
		$this -> assertTrue($result);

		$pending = $timers -> get_pending_timers();
		$this -> assertCount(1, $pending);
		$this -> assertEquals("test_off", $pending[0]["timer_alias"]);
		$this -> assertEquals("action", $pending[0]["target_type"]);
	}

	public function test_cancel_timer_scoped(): void {
		$timers = new Timers();
		$timers -> create_timer("test_cancel", "LightHubScope", "action", "alias", [], time() + 100);
		$result = $timers -> cancel_timer("test_cancel", "LightHubScope");
		$this -> assertTrue($result);

		$pending = $timers -> get_pending_timers();
		$this -> assertCount(0, $pending);
	}

	public function test_cancel_by_alias(): void {
		$timers = new Timers();
		$timers -> create_timer("global_cancel", "OfficeRoomScope", "event", "door.open", [], time() + 100);
		$result = $timers -> cancel_by_alias("global_cancel");
		$this -> assertTrue($result);

		$pending = $timers -> get_pending_timers();
		$this -> assertCount(0, $pending);
	}

	public function test_mark_status_executed(): void {
		$timers = new Timers();
		$timers -> create_timer("test_exec", "LightHubScope", "action", "alias", [], time() - 1);
		$pending = $timers -> get_pending_timers();
		$this -> assertCount(1, $pending);

		$result = $timers -> mark_status((int)$pending[0]["id"], "executed");
		$this -> assertTrue($result);

		$all = $timers -> get_timers("executed");
		$this -> assertCount(1, $all);
		$this -> assertNotNull($all[0]["executed_at"]);
	}

	public function test_mark_status_failed(): void {
		$timers = new Timers();
		$timers -> create_timer("test_fail", "LightHubScope", "regular", "alias", [], time() - 1);
		$pending = $timers -> get_pending_timers();
		$this -> assertCount(1, $pending);

		$result = $timers -> mark_status((int)$pending[0]["id"], "failed", "Something broke");
		$this -> assertTrue($result);

		$all = $timers -> get_timers("failed");
		$this -> assertCount(1, $all);
		$this -> assertEquals("Something broke", $all[0]["error_message"]);
	}

	public function test_duplicate_alias_replaces_pending(): void {
		$timers = new Timers();
		$timers -> create_timer("dup", "LightHubScope", "action", "a", [], time() + 100);
		$timers -> create_timer("dup", "LightHubScope", "action", "b", [], time() + 200);

		$pending = $timers -> get_timers("pending");
		$this -> assertCount(1, $pending);
		$this -> assertEquals("b", $pending[0]["target_alias"]);
	}

	public function test_get_timers_with_limit(): void {
		$timers = new Timers();
		for($i = 1; $i <= 5; $i++) {
			$timers -> create_timer("t{$i}", "LightHubScope", "action", "alias", [], time() + $i);
		}
		$all = $timers -> get_timers(null, 3);
		$this -> assertCount(3, $all);
	}
}
