"""Tests for context-engineering edge case handling.

Tests the error handling improvements in compression_evaluator.py and context_analyzer.py:
- File not found
- Permission denied
- Invalid JSON
- File too large
- UTF-8 encoding
"""

import json
import os
import stat
import subprocess
import sys
import tempfile
from pathlib import Path

import pytest

SCRIPTS_DIR = Path(__file__).parent.parent
PYTHON = sys.executable


class TestCompressionEvaluatorEdgeCases:
    """Test edge cases in compression_evaluator.py"""

    @pytest.fixture
    def valid_json_file(self, tmp_path):
        """Create valid JSON file."""
        f = tmp_path / "valid.json"
        f.write_text('{"messages": [{"role": "user", "content": "hello"}]}', encoding='utf-8')
        return str(f)

    @pytest.fixture
    def valid_text_file(self, tmp_path):
        """Create valid text file."""
        f = tmp_path / "compressed.txt"
        f.write_text("Summary of conversation", encoding='utf-8')
        return str(f)

    def run_script(self, *args, timeout=30):
        """Run compression_evaluator.py with args."""
        cmd = [PYTHON, str(SCRIPTS_DIR / "compression_evaluator.py")] + list(args)
        result = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout)
        return result

    def test_missing_file_exits_1(self, tmp_path):
        """Test exit code 1 when file not found."""
        result = self.run_script("evaluate", "/nonexistent/file.json", str(tmp_path / "c.txt"))
        assert result.returncode == 1
        assert "File not found" in result.stderr

    def test_missing_file_error_message(self, tmp_path):
        """Test error message format for missing file."""
        missing = "/this/path/does/not/exist/file.json"
        result = self.run_script("evaluate", missing, str(tmp_path / "c.txt"))
        assert result.returncode == 1
        assert missing in result.stderr or "not found" in result.stderr.lower()

    def test_invalid_json_exits_1(self, tmp_path, valid_text_file):
        """Test exit code 1 when JSON is invalid."""
        bad_json = tmp_path / "bad.json"
        bad_json.write_text("{invalid json content", encoding='utf-8')

        result = self.run_script("evaluate", str(bad_json), valid_text_file)
        assert result.returncode == 1
        assert "Invalid JSON" in result.stderr or "JSON" in result.stderr

    def test_valid_files_succeed(self, valid_json_file, valid_text_file):
        """Test success with valid inputs."""
        result = self.run_script("evaluate", valid_json_file, valid_text_file)
        assert result.returncode == 0
        output = json.loads(result.stdout)
        assert "compression_ratio" in output
        assert "quality_score" in output

    def test_generate_probes_missing_file(self):
        """Test generate-probes with missing file."""
        result = self.run_script("generate-probes", "/nonexistent/context.json")
        assert result.returncode == 1
        assert "File not found" in result.stderr

    def test_generate_probes_invalid_json(self, tmp_path):
        """Test generate-probes with invalid JSON."""
        bad = tmp_path / "bad.json"
        bad.write_text("not valid json {{{", encoding='utf-8')

        result = self.run_script("generate-probes", str(bad))
        assert result.returncode == 1
        assert "Invalid JSON" in result.stderr or "JSON" in result.stderr

    def test_generate_probes_success(self, valid_json_file):
        """Test generate-probes with valid file."""
        result = self.run_script("generate-probes", valid_json_file)
        assert result.returncode == 0
        output = json.loads(result.stdout)
        assert isinstance(output, list)

    def test_utf8_content(self, tmp_path):
        """Test UTF-8 encoding with special characters."""
        utf8_file = tmp_path / "utf8.json"
        content = {"messages": [{"role": "user", "content": "日本語テスト émojis 🎉"}]}
        utf8_file.write_text(json.dumps(content), encoding='utf-8')

        compressed = tmp_path / "compressed.txt"
        compressed.write_text("Summary with 日本語 and émojis 🎉", encoding='utf-8')

        result = self.run_script("evaluate", str(utf8_file), str(compressed))
        assert result.returncode == 0

    @pytest.mark.skipif(os.name == 'nt', reason="Permission test not reliable on Windows")
    def test_permission_denied(self, tmp_path):
        """Test permission denied error."""
        protected = tmp_path / "protected.json"
        protected.write_text('{"messages": []}', encoding='utf-8')
        os.chmod(protected, 0o000)

        try:
            result = self.run_script("generate-probes", str(protected))
            assert result.returncode == 1
            assert "Permission denied" in result.stderr or "permission" in result.stderr.lower()
        finally:
            os.chmod(protected, stat.S_IRUSR | stat.S_IWUSR)


class TestContextAnalyzerEdgeCases:
    """Test edge cases in context_analyzer.py"""

    @pytest.fixture
    def valid_context_file(self, tmp_path):
        """Create valid context file."""
        f = tmp_path / "context.json"
        content = {
            "messages": [
                {"role": "user", "content": "implement feature X"},
                {"role": "assistant", "content": "I'll help with that"}
            ]
        }
        f.write_text(json.dumps(content), encoding='utf-8')
        return str(f)

    def run_script(self, *args, timeout=30):
        """Run context_analyzer.py with args."""
        cmd = [PYTHON, str(SCRIPTS_DIR / "context_analyzer.py")] + list(args)
        result = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout)
        return result

    def test_missing_file_exits_1(self):
        """Test exit code 1 when file not found."""
        result = self.run_script("analyze", "/nonexistent/context.json")
        assert result.returncode == 1
        assert "File not found" in result.stderr

    def test_invalid_json_exits_1(self, tmp_path):
        """Test exit code 1 when JSON is invalid."""
        bad = tmp_path / "bad.json"
        bad.write_text("not json", encoding='utf-8')

        result = self.run_script("analyze", str(bad))
        assert result.returncode == 1
        assert "Invalid JSON" in result.stderr or "JSON" in result.stderr

    def test_valid_file_succeeds(self, valid_context_file):
        """Test success with valid input."""
        result = self.run_script("analyze", valid_context_file)
        assert result.returncode == 0
        output = json.loads(result.stdout)
        assert "health_status" in output or "health_score" in output

    def test_utf8_content(self, tmp_path):
        """Test UTF-8 encoding with international characters."""
        utf8_file = tmp_path / "utf8.json"
        content = {
            "messages": [
                {"role": "user", "content": "日本語で説明してください"},
                {"role": "assistant", "content": "はい、説明します。émojis: 🎉🚀"}
            ]
        }
        utf8_file.write_text(json.dumps(content, ensure_ascii=False), encoding='utf-8')

        result = self.run_script("analyze", str(utf8_file))
        assert result.returncode == 0

    def test_empty_messages_array(self, tmp_path):
        """Test handling of empty messages array."""
        f = tmp_path / "empty.json"
        f.write_text('{"messages": []}', encoding='utf-8')

        result = self.run_script("analyze", str(f))
        assert result.returncode == 0

    def test_direct_messages_list(self, tmp_path):
        """Test handling of direct messages list (no wrapper)."""
        f = tmp_path / "direct.json"
        content = [
            {"role": "user", "content": "hello"},
            {"role": "assistant", "content": "hi"}
        ]
        f.write_text(json.dumps(content), encoding='utf-8')

        result = self.run_script("analyze", str(f))
        assert result.returncode == 0

    @pytest.mark.skipif(os.name == 'nt', reason="Permission test not reliable on Windows")
    def test_permission_denied(self, tmp_path):
        """Test permission denied error."""
        protected = tmp_path / "protected.json"
        protected.write_text('{"messages": []}', encoding='utf-8')
        os.chmod(protected, 0o000)

        try:
            result = self.run_script("analyze", str(protected))
            assert result.returncode == 1
            assert "Permission denied" in result.stderr or "permission" in result.stderr.lower()
        finally:
            os.chmod(protected, stat.S_IRUSR | stat.S_IWUSR)

    def test_with_keywords_filter(self, valid_context_file):
        """Test analyze with keywords filter."""
        result = self.run_script("analyze", valid_context_file, "--keywords", "feature,implement")
        assert result.returncode == 0

    def test_with_limit(self, valid_context_file):
        """Test analyze with limit parameter."""
        result = self.run_script("analyze", valid_context_file, "--limit", "10")
        assert result.returncode == 0


class TestFileSizeValidation:
    """Test file size validation (100MB limit)."""

    def test_large_file_warning_in_code(self):
        """Verify MAX_FILE_SIZE_MB constant exists in scripts."""
        evaluator = SCRIPTS_DIR / "compression_evaluator.py"
        analyzer = SCRIPTS_DIR / "context_analyzer.py"

        eval_content = evaluator.read_text()
        analyzer_content = analyzer.read_text()

        assert "MAX_FILE_SIZE_MB = 100" in eval_content
        assert "MAX_FILE_SIZE_MB = 100" in analyzer_content


if __name__ == "__main__":
    pytest.main([__file__, "-v"])
