<?php

namespace SHServ\Tests;

use PHPUnit\Framework\TestCase;
use SHServ\Helpers\ScriptParamsValidator;

class ScriptParamsValidatorTest extends TestCase {

	public function test_no_schema_returns_ok() {
		$result = ScriptParamsValidator::validate(null, ["foo" => "bar"]);
		$this->assertTrue($result["ok"]);
		$this->assertEmpty($result["errors"]);
	}

	public function test_required_field_missing() {
		$schema = [
			"level" => ["type" => "number", "required" => true],
		];
		$result = ScriptParamsValidator::validate($schema, []);
		$this->assertFalse($result["ok"]);
		$this->assertEquals("required", $result["errors"][0]["error"]);
		$this->assertEquals("level", $result["errors"][0]["field"]);
	}

	public function test_default_applied_when_missing() {
		$schema = [
			"level" => ["type" => "number", "default" => 42],
		];
		$result = ScriptParamsValidator::validate($schema, []);
		$this->assertTrue($result["ok"]);
		$this->assertEquals(42, $result["params"]["level"]);
	}

	public function test_text_type_string_ok() {
		$schema = ["msg" => ["type" => "text"]];
		$result = ScriptParamsValidator::validate($schema, ["msg" => "hello"]);
		$this->assertTrue($result["ok"]);
	}

	public function test_text_type_number_fails() {
		$schema = ["msg" => ["type" => "text"]];
		$result = ScriptParamsValidator::validate($schema, ["msg" => 123]);
		$this->assertFalse($result["ok"]);
		$this->assertEquals("expected_string", $result["errors"][0]["error"]);
	}

	public function test_number_type_int_ok() {
		$schema = ["count" => ["type" => "number", "min" => 0, "max" => 10]];
		$result = ScriptParamsValidator::validate($schema, ["count" => 5]);
		$this->assertTrue($result["ok"]);
	}

	public function test_number_type_string_numeric_ok() {
		$schema = ["count" => ["type" => "number"]];
		$result = ScriptParamsValidator::validate($schema, ["count" => "7"]);
		$this->assertTrue($result["ok"]);
		$this->assertEquals(7.0, $result["params"]["count"]);
	}

	public function test_number_min_violation() {
		$schema = ["count" => ["type" => "number", "min" => 0]];
		$result = ScriptParamsValidator::validate($schema, ["count" => -5]);
		$this->assertFalse($result["ok"]);
		$this->assertEquals("min", $result["errors"][0]["error"]);
	}

	public function test_range_type_ok() {
		$schema = ["level" => ["type" => "range", "min" => 0, "max" => 100]];
		$result = ScriptParamsValidator::validate($schema, ["level" => 50]);
		$this->assertTrue($result["ok"]);
	}

	public function test_range_max_violation() {
		$schema = ["level" => ["type" => "range", "min" => 0, "max" => 100]];
		$result = ScriptParamsValidator::validate($schema, ["level" => 120]);
		$this->assertFalse($result["ok"]);
		$this->assertEquals("max", $result["errors"][0]["error"]);
	}

	public function test_select_valid_option() {
		$schema = ["room" => ["type" => "select", "options" => ["kitchen" => "Кухня", "hall" => "Зал"]]];
		$result = ScriptParamsValidator::validate($schema, ["room" => "hall"]);
		$this->assertTrue($result["ok"]);
	}

	public function test_select_invalid_option() {
		$schema = ["room" => ["type" => "select", "options" => ["kitchen" => "Кухня"]]];
		$result = ScriptParamsValidator::validate($schema, ["room" => "bedroom"]);
		$this->assertFalse($result["ok"]);
		$this->assertEquals("invalid_option", $result["errors"][0]["error"]);
	}

	public function test_toggle_bool_ok() {
		$schema = ["instant" => ["type" => "toggle"]];
		$result = ScriptParamsValidator::validate($schema, ["instant" => true]);
		$this->assertTrue($result["ok"]);
	}

	public function test_toggle_non_bool_fails() {
		$schema = ["instant" => ["type" => "toggle"]];
		$result = ScriptParamsValidator::validate($schema, ["instant" => "yes"]);
		$this->assertFalse($result["ok"]);
		$this->assertEquals("expected_bool", $result["errors"][0]["error"]);
	}

	public function test_textarea_type_string_ok() {
		$schema = ["note" => ["type" => "textarea"]];
		$result = ScriptParamsValidator::validate($schema, ["note" => "line1\nline2"]);
		$this->assertTrue($result["ok"]);
	}

	public function test_unknown_type_ignored() {
		$schema = ["foo" => ["type" => "custom"]];
		$result = ScriptParamsValidator::validate($schema, ["foo" => "anything"]);
		$this->assertTrue($result["ok"]);
	}
}
