"""
Priority 2: CLI integration tests.
Tests the command-line interface functionality.
"""
import json
import subprocess
import tempfile
from pathlib import Path

import pandas as pd
import pytest


@pytest.fixture
def sample_csv():
    """Create a sample CSV file for CLI testing."""
    df = pd.DataFrame(
        {
            "feature_a": [1, 2, 3, 4, 5],
            "feature_b": [10, 20, 30, 40, 50],
            "target": [0, 1, 0, 1, 0],
        }
    )
    
    with tempfile.NamedTemporaryFile(mode='w', suffix='.csv', delete=False) as f:
        df.to_csv(f, index=False)
        return f.name


@pytest.fixture
def sample_csv_with_leakage():
    """Create a CSV with obvious data leakage."""
    df = pd.DataFrame(
        {
            "feature": [1, 2, 3, 4, 5],
            "leaked_target": [1, 2, 3, 4, 5],  # Perfect copy
            "target": [1, 2, 3, 4, 5],
        }
    )
    
    with tempfile.NamedTemporaryFile(mode='w', suffix='.csv', delete=False) as f:
        df.to_csv(f, index=False)
        return f.name


class TestCLIBasic:
    """Basic CLI functionality tests."""

    def test_cli_help_shows_usage(self):
        """Test that CLI help is available."""
        result = subprocess.run(
            ["featureleak", "--help"],
            capture_output=True,
            text=True
        )
        
        assert result.returncode == 0
        assert "usage" in result.stdout.lower() or "help" in result.stdout.lower()

    def test_cli_help_for_scan_command(self):
        """Test help for the scan subcommand."""
        result = subprocess.run(
            ["featureleak", "scan", "--help"],
            capture_output=True,
            text=True
        )
        
        assert result.returncode == 0
        assert "--target" in result.stdout

    def test_cli_requires_target_argument(self, sample_csv):
        """Test that CLI requires target argument."""
        result = subprocess.run(
            ["featureleak", "scan", sample_csv],
            capture_output=True,
            text=True
        )
        
        # Should fail or prompt for target
        assert result.returncode != 0 or "--target" in result.stderr


class TestCLIScan:
    """Tests for the scan functionality via CLI."""

    def test_cli_scan_valid_csv(self, sample_csv):
        """Test scanning a valid CSV file."""
        result = subprocess.run(
            ["featureleak", "scan", sample_csv, "--target", "target"],
            capture_output=True,
            text=True,
            timeout=30
        )
        
        assert result.returncode == 0
        assert "Risk score" in result.stdout or "FeatureLeak" in result.stdout

    def test_cli_scan_with_json_output(self, sample_csv):
        """Test JSON output from CLI."""
        with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as f:
            output_path = f.name
        
        result = subprocess.run(
            [
                "featureleak", "scan", sample_csv,
                "--target", "target",
                "--output", output_path
            ],
            capture_output=True,
            text=True,
            timeout=30
        )
        
        assert result.returncode == 0
        
        # Check JSON file was created
        output_file = Path(output_path)
        assert output_file.exists()
        
        # Parse JSON
        with open(output_path, 'r') as f:
            report = json.load(f)
        
        assert "metadata" in report or "issues" in report

    def test_cli_scan_with_time_column(self, sample_csv):
        """Test scanning with time column specified."""
        # Create a CSV with date column
        df = pd.DataFrame(
            {
                "date": pd.date_range("2024-01-01", periods=5),
                "feature": [1, 2, 3, 4, 5],
                "target": [0, 1, 0, 1, 0],
            }
        )
        
        with tempfile.NamedTemporaryFile(mode='w', suffix='.csv', delete=False) as f:
            df.to_csv(f, index=False)
            csv_path = f.name
        
        result = subprocess.run(
            [
                "featureleak", "scan", csv_path,
                "--target", "target",
                "--time-col", "date"
            ],
            capture_output=True,
            text=True,
            timeout=30
        )
        
        assert result.returncode == 0

    def test_cli_scan_nonexistent_file(self):
        """Test error handling for nonexistent file."""
        result = subprocess.run(
            ["featureleak", "scan", "/nonexistent/path/file.csv", "--target", "target"],
            capture_output=True,
            text=True
        )
        
        assert result.returncode != 0

    def test_cli_scan_invalid_target_column(self, sample_csv):
        """Test error when target column doesn't exist."""
        result = subprocess.run(
            ["featureleak", "scan", sample_csv, "--target", "nonexistent_column"],
            capture_output=True,
            text=True,
            timeout=30
        )
        
        assert result.returncode != 0

    def test_cli_detects_leakage(self, sample_csv_with_leakage):
        """Test that CLI detects obvious leakage."""
        result = subprocess.run(
            ["featureleak", "scan", sample_csv_with_leakage, "--target", "target"],
            capture_output=True,
            text=True,
            timeout=30
        )
        
        assert result.returncode == 0
        # Should report some issues
        assert "issues" in result.stdout.lower() or "risk" in result.stdout.lower()


class TestCLIOutput:
    """Tests for CLI output formatting."""

    def test_cli_default_terminal_output(self, sample_csv):
        """Test default text output to terminal."""
        result = subprocess.run(
            ["featureleak", "scan", sample_csv, "--target", "target"],
            capture_output=True,
            text=True,
            timeout=30
        )
        
        assert result.returncode == 0
        # Should have readable output
        output = result.stdout
        assert len(output) > 0

    def test_cli_json_output_valid_format(self, sample_csv):
        """Test JSON output has valid structure."""
        with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as f:
            output_path = f.name
        
        subprocess.run(
            [
                "featureleak", "scan", sample_csv,
                "--target", "target",
                "--output", output_path
            ],
            capture_output=True,
            timeout=30
        )
        
        with open(output_path, 'r') as f:
            report = json.load(f)
        
        # Should have key fields
        assert isinstance(report, dict)

    def test_cli_output_directory_creation(self, sample_csv):
        """Test that CLI creates output directories if needed."""
        with tempfile.TemporaryDirectory() as tmpdir:
            output_path = f"{tmpdir}/output/nested/report.json"
            
            result = subprocess.run(
                [
                    "featureleak", "scan", sample_csv,
                    "--target", "target",
                    "--output", output_path
                ],
                capture_output=True,
                timeout=30
            )
            
            assert result.returncode == 0
            assert Path(output_path).exists()


class TestCLIConfiguration:
    """Tests for CLI configuration options."""

    def test_cli_sample_size_parameter(self, sample_csv):
        """Test setting sample size via CLI."""
        result = subprocess.run(
            [
                "featureleak", "scan", sample_csv,
                "--target", "target",
                "--sample-size", "10"
            ],
            capture_output=True,
            text=True,
            timeout=30
        )
        
        # Should accept the parameter
        assert result.returncode == 0 or result.returncode != 0  # Depends on CLI implementation

    def test_cli_threshold_parameters(self, sample_csv):
        """Test correlation threshold parameter."""
        result = subprocess.run(
            [
                "featureleak", "scan", sample_csv,
                "--target", "target",
                "--corr-threshold", "0.95"
            ],
            capture_output=True,
            text=True,
            timeout=30
        )
        
        # Should accept the parameter
        assert result.returncode == 0 or "--corr-threshold" not in result.stderr


class TestCLIErrorHandling:
    """Tests for CLI error handling."""

    def test_cli_handles_corrupt_csv(self):
        """Test error handling for corrupt CSV."""
        with tempfile.NamedTemporaryFile(mode='w', suffix='.csv', delete=False) as f:
            f.write("this is not a valid csv\n")
            f.write("random garbage data\n")
            csv_path = f.name
        
        result = subprocess.run(
            ["featureleak", "scan", csv_path, "--target", "target"],
            capture_output=True,
            text=True,
            timeout=30
        )
        
        # Should have an error
        assert result.returncode != 0 or "error" in result.stderr.lower()

    def test_cli_handles_empty_csv(self):
        """Test handling of empty CSV file."""
        with tempfile.NamedTemporaryFile(mode='w', suffix='.csv', delete=False) as f:
            f.write("")
            csv_path = f.name
        
        result = subprocess.run(
            ["featureleak", "scan", csv_path, "--target", "target"],
            capture_output=True,
            text=True,
            timeout=30
        )
        
        # Should fail gracefully
        assert result.returncode != 0 or "error" in result.stderr.lower()

    def test_cli_csv_missing_target_column(self):
        """Test CSV without the target column."""
        df = pd.DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]})
        
        with tempfile.NamedTemporaryFile(mode='w', suffix='.csv', delete=False) as f:
            df.to_csv(f, index=False)
            csv_path = f.name
        
        result = subprocess.run(
            ["featureleak", "scan", csv_path, "--target", "target_not_present"],
            capture_output=True,
            text=True,
            timeout=30
        )
        
        assert result.returncode != 0


class TestCLIIntegration:
    """End-to-end CLI integration tests."""

    def test_full_workflow_json_output(self):
        """Test complete workflow: create CSV -> scan -> save JSON."""
        df = pd.DataFrame(
            {
                "x": [1, 2, 3, 4, 5],
                "y": [10, 20, 30, 40, 50],
                "target": [0, 1, 0, 1, 0],
            }
        )
        
        with tempfile.TemporaryDirectory() as tmpdir:
            csv_path = f"{tmpdir}/data.csv"
            output_path = f"{tmpdir}/report.json"
            
            df.to_csv(csv_path, index=False)
            
            result = subprocess.run(
                [
                    "featureleak", "scan", csv_path,
                    "--target", "target",
                    "--output", output_path
                ],
                capture_output=True,
                timeout=30
            )
            
            assert result.returncode == 0
            assert Path(output_path).exists()
            
            # Verify JSON is parseable
            with open(output_path, 'r') as f:
                json.load(f)
