"""Tests for search_replace.py functionality."""

import unittest

from wcgw.client.file_ops.diff_edit import SearchReplaceMatchError
from wcgw.client.file_ops.search_replace import (
    SearchReplaceSyntaxError,
    search_replace_edit,
)


class TestSearchReplace(unittest.TestCase):
    def setUp(self):
        self.maxDiff = None
        self.mock_logger = lambda x: None

    def test_search_replace_edit_basic(self):
        # Test basic replacement
        lines = [
            "<<<<<<< SEARCH",
            "original line",
            "=======",
            "new line",
            ">>>>>>> REPLACE",
        ]
        original = "before\noriginal line\nafter"

        result, comments = search_replace_edit(lines, original, self.mock_logger)
        self.assertEqual(result, "before\nnew line\nafter")
        self.assertEqual(comments, "Edited successfully")

    def test_search_replace_edit_multiple_blocks(self):
        # Test multiple search/replace blocks
        lines = [
            "<<<<<<< SEARCH",
            "line1",
            "=======",
            "new1",
            ">>>>>>> REPLACE",
            "<<<<<<< SEARCH",
            "line2",
            "=======",
            "new2",
            ">>>>>>> REPLACE",
        ]
        original = "line1\nline2"  # Changed from original to avoid line ordering issues

        result, comments = search_replace_edit(lines, original, self.mock_logger)
        self.assertEqual(result, "new1\nnew2")
        self.assertEqual(comments, "Edited successfully")

    def test_search_replace_edit_no_input(self):
        # Test empty input
        with self.assertRaises(SearchReplaceSyntaxError) as ctx:
            search_replace_edit([], "content", self.mock_logger)
        self.assertIn("Error: No input to search replace edit", str(ctx.exception))

    def test_search_replace_edit_malformed_blocks(self):
        # Test missing SEARCH marker
        lines = ["original line", "=======", "new line", ">>>>>>> REPLACE"]
        with self.assertRaises(SearchReplaceSyntaxError):
            search_replace_edit(lines, "content", self.mock_logger)

        # Test missing REPLACE marker
        lines = ["<<<<<<< SEARCH", "original line", "=======", "new line"]
        with self.assertRaises(SearchReplaceSyntaxError):
            search_replace_edit(lines, "content", self.mock_logger)

        # Test missing separator
        lines = ["<<<<<<< SEARCH", "original line", "new line", ">>>>>>> REPLACE"]
        with self.assertRaises(SearchReplaceSyntaxError):
            search_replace_edit(lines, "content", self.mock_logger)

        # Test missing multiple searches
        lines = ["<<<<<<< SEARCH", "<<<<<<< SEARCH", "original line", "=======",  "new line", ">>>>>>> REPLACE"]
        with self.assertRaises(SearchReplaceSyntaxError):
            search_replace_edit(lines, "content", self.mock_logger)

        # Test missing multiple divider
        lines = ["<<<<<<< SEARCH",  "=======", "original line", "=======",  "new line", ">>>>>>> REPLACE"]
        with self.assertRaises(SearchReplaceSyntaxError):
            search_replace_edit(lines, "content", self.mock_logger)

        # Test missing multiple replace
        lines = ["<<<<<<< SEARCH", "original line", "=======",   ">>>>>>> REPLACE", "new line", ">>>>>>> REPLACE"]
        with self.assertRaises(SearchReplaceSyntaxError):
            search_replace_edit(lines, "content", self.mock_logger)

    def test_search_replace_edit_whitespace(self):
        # Test with extra whitespace in markers
        lines = [
            "<<<<<<< SEARCH  ",
            "original line",
            "=======  ",
            "new line",
            ">>>>>>>  REPLACE",
        ]
        original = "original line"

        result, comments = search_replace_edit(lines, original, self.mock_logger)
        self.assertEqual(result, "new line")
        self.assertEqual(comments, "Edited successfully")

        # Test with missing or extra angles
        lines = [
            "<<<<<< SEARCH  ",
            "original line",
            "========  ",
            "new line",
            ">>>>>>>>  REPLACE",
        ]
        original = "original line"

        result, comments = search_replace_edit(lines, original, self.mock_logger)
        self.assertEqual(result, "new line")
        self.assertEqual(comments, "Edited successfully")

    def test_search_replace_edit_multiple_matches(self):
        # Test when block matches multiple times
        lines = ["<<<<<<< SEARCH", "repeat", "=======", "replaced", ">>>>>>> REPLACE"]
        original = "repeat\nother\nrepeat"

        with self.assertRaises(SearchReplaceMatchError) as ctx:
            search_replace_edit(lines, original, self.mock_logger)
        self.assertIn("The following block matched more than once", str(ctx.exception))

    def test_search_replace_edit_indentation(self):
        # Test with different indentation levels
        lines = [
            "<<<<<<< SEARCH",
            "    indented line",
            "=======",
            "  new indented line",
            ">>>>>>> REPLACE",
        ]
        original = "before\n    indented line\nafter"

        result, comments = search_replace_edit(lines, original, self.mock_logger)
        self.assertEqual(result, "before\n  new indented line\nafter")
        # Warning message not implemented in source, so we don't check for it

    def test_search_replace_edit_no_match(self):
        # Test when search block doesn't match
        lines = [
            "<<<<<<< SEARCH",
            "nonexistent line",
            "=======",
            "new line",
            ">>>>>>> REPLACE",
        ]
        original = "different content"

        with self.assertRaises(SearchReplaceMatchError) as ctx:
            search_replace_edit(lines, original, self.mock_logger)
        self.assertIn("Couldn't find match", str(ctx.exception))

    def test_search_replace_edit_empty_lines(self):
        # Test with empty lines in content and blocks
        lines = [
            "<<<<<<< SEARCH",
            "line1",
            "",
            "line2",
            "=======",
            "new1",
            "",
            "new2",
            ">>>>>>> REPLACE",
        ]
        original = "start\nline1\n\nline2\nend"

        result, comments = search_replace_edit(lines, original, self.mock_logger)
        self.assertEqual(result, "start\nnew1\n\nnew2\nend")
        self.assertEqual(comments, "Edited successfully")

    def test_search_replace_edit_partial_matches(self):
        # Test when only part of the content matches
        lines = ["<<<<<<< SEARCH", "middle", "=======", "new middle", ">>>>>>> REPLACE"]
        original = "begin\nmiddl\nend"

        with self.assertRaises(SearchReplaceMatchError) as ctx:
            search_replace_edit(lines, original, self.mock_logger)
        self.assertIn(
            "Couldn't find match. Do you mean to match the lines in the following context?\n```begin\nmiddl\nend\n```",
            str(ctx.exception),
        )


if __name__ == "__main__":
    unittest.main()
