from __future__ import annotations

import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parent.parent))

from chekan.junit import JUnitReport, find_junit_reports, format_junit_summary, parse_junit_xml


SAMPLE_DUPLICATE_CONTEXTS_XML = """<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
	<testsuite id="0" name="Тесты базовой математики [КлиентУправляемоеПриложение]" classname="тст_ТестыМатематики" tests="2" errors="0" skipped="0" failures="1" context="КлиентУправляемоеПриложение">
		<testcase name="Тест_УспешныйСложение" classname="тст_ТестыМатематики.Тест_УспешныйСложение" time="0.005" context="КлиентУправляемоеПриложение"/>
		<testcase name="Тест_ПадающийСложение" classname="тст_ТестыМатематики.Тест_ПадающийСложение" time="0.007" context="КлиентУправляемоеПриложение">
			<failure message="Ожидали, что проверяемое значение `4` равно `5`, но это не так." type="Утверждений">Stack trace 1</failure>
		</testcase>
	</testsuite>
	<testsuite id="1" name="Тесты базовой математики [Сервер]" classname="тст_ТестыМатематики" tests="2" errors="0" skipped="0" failures="1" context="Сервер">
		<testcase name="Тест_УспешныйСложение" classname="тст_ТестыМатематики.Тест_УспешныйСложение" time="0.004" context="Сервер"/>
		<testcase name="Тест_ПадающийСложение" classname="тст_ТестыМатематики.Тест_ПадающийСложение" time="0.008" context="Сервер">
			<failure message="Ожидали, что проверяемое значение `4` равно `5`, но это не так." type="Утверждений">Stack trace 2</failure>
		</testcase>
	</testsuite>
</testsuites>
"""

SAMPLE_ALL_GREEN_XML = """<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
	<testsuite name="Suite1" tests="2" failures="0">
		<testcase name="test_one" classname="test_mod"/>
		<testcase name="test_two" classname="test_mod"/>
	</testsuite>
</testsuites>
"""

SAMPLE_EMPTY_XML = """<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
</testsuites>
"""


def test_parse_junit_deduplicates_contexts() -> None:
    """YAxUnit гоняет тест в двух контекстах ([Сервер] и [КлиентУправляемоеПриложение]).
    Падения должны схлопываться по уникальным именам тестов."""
    report = parse_junit_xml(SAMPLE_DUPLICATE_CONTEXTS_XML)

    assert report.total_runs == 4
    assert report.unique_tests_count == 2
    assert report.unique_failures_count == 1
    assert report.unique_passed_count == 1

    fail_key = "тст_ТестыМатематики.Тест_ПадающийСложение"
    assert fail_key in report.failures
    failure = report.failures[fail_key]
    assert failure.name == "Тест_ПадающийСложение"
    assert "тст_ТестыМатематики" in failure.classname
    assert "Ожидали, что проверяемое значение `4` равно `5`" in failure.message
    assert "КлиентУправляемоеПриложение" in failure.contexts
    assert "Сервер" in failure.contexts


def test_format_junit_summary_shows_name_and_message() -> None:
    report = parse_junit_xml(SAMPLE_DUPLICATE_CONTEXTS_XML)
    summary = format_junit_summary(report)

    assert "Упало тестов: 1 из 2 уникальных" in summary
    assert "тст_ТестыМатематики.Тест_ПадающийСложение" in summary
    assert "Ожидали, что проверяемое значение `4` равно `5`" in summary


def test_parse_all_green_junit() -> None:
    report = parse_junit_xml(SAMPLE_ALL_GREEN_XML)
    assert report.unique_tests_count == 2
    assert report.unique_failures_count == 0
    assert report.unique_passed_count == 2
    summary = format_junit_summary(report)
    assert "Все тесты пройдены" in summary


def test_parse_empty_junit() -> None:
    report = parse_junit_xml(SAMPLE_EMPTY_XML)
    assert report.is_empty
    summary = format_junit_summary(report)
    assert "Тестов не обнаружено" in summary


def test_real_testbed_report_parsing_if_exists() -> None:
    testbed_red = Path.home() / "Services" / "onec-testbed" / "junit-red.xml"
    if testbed_red.exists():
        report = parse_junit_xml(testbed_red)
        assert report.unique_failures_count == 1
        assert "Тест_ПадающийСложение" in list(report.failures.keys())[0]


SAMPLE_VANESSA_AUTOMATION_XML = """<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
	<testsuite name="Проверка формы документа Приходная накладная" tests="2" failures="1" errors="0" time="4.12">
		<testcase classname="Документ.ПриходнаяНакладная" name="Сценарий: Успешное открытие формы" time="1.50"/>
		<testcase classname="Документ.ПриходнаяНакладная" name="Сценарий: Заполнение табличной части" time="2.62">
			<failure message="Кнопка 'Заполнить' недоступна или отсутствует на форме">
				Строка 15: И я нажимаю на кнопку с именем 'ФормаЗаполнить'
			</failure>
		</testcase>
	</testsuite>
</testsuites>
"""


def test_parse_vanessa_automation_bdd_report() -> None:
    """Разбор JUnit отчёта Vanessa-Automation (UI / BDD-сценарии)."""
    report = parse_junit_xml(SAMPLE_VANESSA_AUTOMATION_XML)
    assert report.unique_tests_count == 2
    assert report.unique_failures_count == 1
    assert report.unique_passed_count == 1

    fail_key = "Документ.ПриходнаяНакладная.Сценарий: Заполнение табличной части"
    assert fail_key in report.failures
    failure = report.failures[fail_key]
    assert "Кнопка 'Заполнить' недоступна" in failure.message

    summary = format_junit_summary(report)
    assert "Сценарий: Заполнение табличной части" in summary
    assert "Кнопка 'Заполнить' недоступна" in summary


def test_junit_corruption_lever(tmp_path: Path) -> None:
    """Рычаг порчи: подсовывание отчёта без падений при ожидаемом падении."""
    green_report = parse_junit_xml(SAMPLE_ALL_GREEN_XML)
    red_report = parse_junit_xml(SAMPLE_DUPLICATE_CONTEXTS_XML)

    assert green_report.unique_failures_count == 0
    assert red_report.unique_failures_count == 1
    # Зелёный отчёт не содержит упавших тестов
    assert len(green_report.failures) != len(red_report.failures)

