import unittest
import os
from rwl.testing.suite_generator import SuiteGenerator
import shutil


class TestSuiteGenerator(unittest.TestCase):

    TEST_DIR = "test_output"
    STORY_FILE = "test_story.txt"
    STORY_CONTENT = """
    US-002: Sample Story
    GIVEN the user is logged in
    WHEN the user clicks the submit button
    THEN the data is saved to the database
    GIVEN the user is not logged in
    WHEN the user clicks the submit button
    THEN an error message is displayed
    """

    def setUp(self):
        if os.path.exists(self.TEST_DIR):
            shutil.rmtree(self.TEST_DIR)
        os.makedirs(self.TEST_DIR, exist_ok=True)

        self.story_path = os.path.join(self.TEST_DIR, self.STORY_FILE)
        with open(self.story_path, "w") as f:
            f.write(self.STORY_CONTENT)

        self.generator = SuiteGenerator(self.story_path, self.TEST_DIR)

    def tearDown(self):
        if os.path.exists(self.TEST_DIR):
            shutil.rmtree(self.TEST_DIR)


    def test_generate_test_suite(self):
        test_file_path = self.generator.generate_test_suite()
        self.assertTrue(os.path.exists(test_file_path))
        self.assertTrue(test_file_path.endswith(".py"))


    def test_read_story_content(self):
        content = self.generator._read_story_content()
        self.assertEqual(content.strip(), self.STORY_CONTENT.strip())

        # Test file not found exception
        with self.assertRaises(FileNotFoundError):
            generator = SuiteGenerator("non_existent_file.txt")
            generator._read_story_content()

    def test_parse_acceptance_criteria(self):
        criteria = self.generator._parse_acceptance_criteria(self.STORY_CONTENT)
        self.assertEqual(len(criteria), 2) # Two scenarios
        self.assertIn("GIVEN", criteria[0])
        self.assertIn("WHEN", criteria[0])
        self.assertIn("THEN", criteria[0])

        self.assertEqual(criteria[0]["GIVEN"].strip(), "the user is logged in")
        self.assertEqual(criteria[0]["WHEN"].strip(), "the user clicks the submit button")
        self.assertEqual(criteria[0]["THEN"].strip(), "the data is saved to the database")

        self.assertEqual(criteria[1]["GIVEN"].strip(), "the user is not logged in")
        self.assertEqual(criteria[1]["WHEN"].strip(), "the user clicks the submit button")
        self.assertEqual(criteria[1]["THEN"].strip(), "an error message is displayed")

    def test_write_test_file_header(self):
        test_file_path = os.path.join(self.TEST_DIR, "temp_test_file.py")
        with open(test_file_path, "w") as f:
            self.generator._write_test_file_header(f, "SampleStory")

        with open(test_file_path, "r") as f:
            header_content = f.read()

        self.assertIn("import unittest", header_content)
        self.assertIn("class TestSampleStory(unittest.TestCase):", header_content)
        os.remove(test_file_path)

    def test_write_test_case(self):
        test_file_path = os.path.join(self.TEST_DIR, "temp_test_file.py")
        case = {
            "GIVEN": "some initial condition",
            "WHEN": "an action occurs",
            "THEN": "a specific result happens"
        }

        with open(test_file_path, "w") as f:
            self.generator._write_test_file_header(f, "SampleStory")  # Need the class definition for this to work correctly
            self.generator._write_test_case(f, "SampleStory", 0, case)

        with open(test_file_path, "r") as f:
            case_content = f.read()

        self.assertIn("def test_SampleStory_0(self):", case_content)
        self.assertIn("some initial condition", case_content)
        self.assertIn("an action occurs", case_content)
        self.assertIn("a specific result happens", case_content)
        os.remove(test_file_path)


    def test_write_test_file_footer(self):
        test_file_path = os.path.join(self.TEST_DIR, "temp_test_file.py")
        with open(test_file_path, "w") as f:
            self.generator._write_test_file_footer(f)

        with open(test_file_path, "r") as f:
            footer_content = f.read()

        self.assertIn("if __name__ == '__main__':", footer_content)
        self.assertIn("unittest.main()", footer_content)
        os.remove(test_file_path)