"""Integration tests for pipes-compat."""

import os
import subprocess
import tempfile

import pipes


class TestIntegration:
    """Integration tests for real-world usage scenarios."""

    def test_typical_usage_pattern(self):
        """Test a typical usage pattern: filtering and transforming text."""
        t = pipes.Template()
        t.append("grep -v '^#'", "f")  # Remove comment lines
        t.append("tr '[:lower:]' '[:upper:]'", "f")  # Uppercase
        t.append("sort", "f")  # Sort lines

        with tempfile.NamedTemporaryFile(mode="w", delete=False) as infile:
            infile.write("zebra\n# comment\napple\nbanana\n")
            inpath = infile.name

        with tempfile.NamedTemporaryFile(mode="w", delete=False) as outfile:
            outpath = outfile.name

        try:
            t.copy(inpath, outpath)
            with open(outpath) as f:
                lines = [line.strip() for line in f.readlines() if line.strip()]

            # Should have APPLE, BANANA, ZEBRA (no comment, sorted)
            assert len(lines) == 3
            assert lines[0] == "APPLE"
            assert lines[1] == "BANANA"
            assert lines[2] == "ZEBRA"
        finally:
            os.unlink(inpath)
            os.unlink(outpath)

    def test_quote_in_shell_command(self):
        """Test using quote() in shell command construction."""
        filename = "file with spaces.txt"
        quoted = pipes.quote(filename)

        # The quoted filename should be safe to use in shell commands
        with tempfile.TemporaryDirectory() as tmpdir:
            filepath = os.path.join(tmpdir, filename)
            with open(filepath, "w") as f:
                f.write("test content")

            # Use quoted filename in a command
            cmd = f"cat {quoted}"
            result = subprocess.run(cmd, shell=True, cwd=tmpdir, capture_output=True, text=True)
            assert result.stdout.strip() == "test content"

    def test_template_with_quoted_paths(self):
        """Test Template with file paths that need quoting."""
        t = pipes.Template()
        t.append("cat", "f")

        with tempfile.TemporaryDirectory() as tmpdir:
            inpath = os.path.join(tmpdir, "input file.txt")
            outpath = os.path.join(tmpdir, "output file.txt")

            with open(inpath, "w") as f:
                f.write("test content")

            t.copy(inpath, outpath)

            with open(outpath) as f:
                content = f.read()
            assert content == "test content"

    def test_clone_and_modify(self):
        """Test cloning a template and modifying it independently."""
        base = pipes.Template()
        base.append("tr '[:lower:]' '[:upper:]'", "f")

        clone1 = base.clone()
        clone2 = base.clone()

        clone1.append("head -n 1", "f")
        clone2.append("tail -n 1", "f")

        with tempfile.NamedTemporaryFile(mode="w", delete=False) as infile:
            infile.write("first\nsecond\nthird\n")
            inpath = infile.name

        with tempfile.NamedTemporaryFile(mode="w", delete=False) as out1:
            outpath1 = out1.name

        with tempfile.NamedTemporaryFile(mode="w", delete=False) as out2:
            outpath2 = out2.name

        try:
            clone1.copy(inpath, outpath1)
            clone2.copy(inpath, outpath2)

            with open(outpath1) as f:
                content1 = f.read().strip()
            with open(outpath2) as f:
                content2 = f.read().strip()

            assert content1 == "FIRST"
            assert content2 == "THIRD"
        finally:
            os.unlink(inpath)
            os.unlink(outpath1)
            os.unlink(outpath2)

    def test_reset_and_reuse(self):
        """Test resetting a template and reusing it."""
        t = pipes.Template()
        t.append("tr '[:lower:]' '[:upper:]'", "f")

        with tempfile.NamedTemporaryFile(mode="w", delete=False) as infile:
            infile.write("test")
            inpath = infile.name

        with tempfile.NamedTemporaryFile(mode="w", delete=False) as outfile:
            outpath = outfile.name

        try:
            # First use
            t.copy(inpath, outpath)
            with open(outpath) as f:
                assert f.read().strip() == "TEST"

            # Reset and add different command
            t.reset()
            t.append("cat", "f")

            # Second use
            t.copy(inpath, outpath)
            with open(outpath) as f:
                assert f.read().strip() == "test"
        finally:
            os.unlink(inpath)
            os.unlink(outpath)

    def test_complex_pipeline(self):
        """Test a complex multi-stage pipeline."""
        t = pipes.Template()
        t.prepend("cat", "f")
        t.append("grep -v '^$'", "f")  # Remove empty lines
        t.append("tr '[:lower:]' '[:upper:]'", "f")
        t.append("sort -u", "f")  # Sort and remove duplicates
        t.append("head -n 3", "f")

        with tempfile.NamedTemporaryFile(mode="w", delete=False) as infile:
            infile.write("zebra\n\napple\nbanana\nzebra\ncherry\n")
            inpath = infile.name

        with tempfile.NamedTemporaryFile(mode="w", delete=False) as outfile:
            outpath = outfile.name

        try:
            t.copy(inpath, outpath)
            with open(outpath) as f:
                lines = [line.strip() for line in f.readlines() if line.strip()]

            # Should have 3 unique, uppercase, sorted lines
            assert len(lines) == 3
            assert "APPLE" in lines
            assert "BANANA" in lines
            assert "CHERRY" in lines or "ZEBRA" in lines
        finally:
            os.unlink(inpath)
            os.unlink(outpath)

    def test_open_read_through_pipeline(self):
        """Test reading a file through a pipeline using open()."""
        t = pipes.Template()
        t.append("tr '[:lower:]' '[:upper:]'", "f")
        t.append("head -n 2", "f")

        with tempfile.NamedTemporaryFile(mode="w", delete=False) as infile:
            infile.write("first line\nsecond line\nthird line\n")
            inpath = infile.name

        try:
            f = t.open(inpath, "r")
            try:
                content = f.read().strip()
                # Content should be a string (text mode)
                assert isinstance(content, str)
                lines = content.split("\n")

                assert len(lines) == 2
                assert "FIRST LINE" in lines
                assert "SECOND LINE" in lines
            finally:
                if hasattr(f, "close"):
                    f.close()
        finally:
            os.unlink(inpath)
