"""CLI integration tests using Click's CliRunner."""

import json
import tempfile
from pathlib import Path
from unittest.mock import patch

import pytest
from click.testing import CliRunner

from mistake_journal.cli import main
from mistake_journal.journal import Journal


@pytest.fixture
def runner():
    """Create a CLI test runner."""
    return CliRunner()


@pytest.fixture
def temp_journal_env():
    """Set up a temporary journal directory for CLI tests."""
    with tempfile.TemporaryDirectory() as tmpdir:
        with patch.object(Journal, "__init__", lambda self, data_dir=None: _init_temp_journal(self, Path(tmpdir))):
            yield tmpdir


def _init_temp_journal(journal, tmpdir):
    """Initialize journal with temp directory."""
    journal.data_dir = tmpdir
    journal.data_dir.mkdir(parents=True, exist_ok=True)
    journal.trades_file = journal.data_dir / "trades.json"
    journal._trades = []
    if journal.trades_file.exists():
        import json
        from mistake_journal.models import Trade
        data = json.loads(journal.trades_file.read_text())
        journal._trades = [Trade(**t) for t in data]


class TestLogCommand:
    def test_log_command_with_args(self, runner, temp_journal_env):
        """Test log with inline args (non-interactive parts)."""
        # The log command requires interactive input for some fields
        # We test that it accepts the basic flags
        result = runner.invoke(main, [
            "log",
            "--symbol", "BTC",
            "--action", "buy",
            "--price", "50000",
            "--size", "1000",
            "--emotion", "3",
        ], input="breakout\nn\nn\nn\n\n\n")  # reasoning, had_plan, stop_loss, take_profit, tags, notes

        assert result.exit_code == 0
        assert "Entry logged" in result.output


class TestReviewCommand:
    def test_review_command_empty(self, runner, temp_journal_env):
        """Test review with no trades."""
        result = runner.invoke(main, ["review"])

        assert result.exit_code == 0
        assert "No trades found" in result.output

    def test_review_command_with_trades(self, runner, temp_journal_env):
        """Test review output with trades."""
        # First log a trade
        runner.invoke(main, [
            "log",
            "--symbol", "BTC",
            "--action", "buy",
            "--price", "50000",
            "--size", "1000",
            "--emotion", "3",
        ], input="test\nn\nn\nn\n\n\n")

        result = runner.invoke(main, ["review"])

        assert result.exit_code == 0
        assert "BTC" in result.output


class TestStatsCommand:
    def test_stats_command(self, runner, temp_journal_env):
        """Test stats output."""
        result = runner.invoke(main, ["stats"])

        assert result.exit_code == 0
        assert "Quick Stats" in result.output
        assert "Total trades" in result.output
        assert "Win rate" in result.output


class TestExportCommand:
    def test_export_json(self, runner, temp_journal_env):
        """Test JSON export to stdout."""
        # First log a trade
        runner.invoke(main, [
            "log",
            "--symbol", "ETH",
            "--action", "sell",
            "--price", "3000",
            "--size", "500",
            "--emotion", "2",
        ], input="test trade\nn\nn\nn\n\n\n")

        result = runner.invoke(main, ["export", "--format", "json"])

        assert result.exit_code == 0
        # Output should be valid JSON
        data = json.loads(result.output)
        assert len(data) == 1
        assert data[0]["symbol"] == "ETH"

    def test_export_csv(self, runner, temp_journal_env):
        """Test CSV export to stdout."""
        # First log a trade
        runner.invoke(main, [
            "log",
            "--symbol", "BTC",
            "--action", "buy",
            "--price", "50000",
            "--size", "1000",
            "--emotion", "3",
        ], input="test\nn\nn\nn\n\n\n")

        result = runner.invoke(main, ["export", "--format", "csv"])

        assert result.exit_code == 0
        assert "BTC" in result.output
        assert "symbol" in result.output  # Header

    def test_export_to_file(self, runner, temp_journal_env):
        """Test export to file."""
        # First log a trade
        runner.invoke(main, [
            "log",
            "--symbol", "SOL",
            "--action", "buy",
            "--price", "100",
            "--size", "200",
            "--emotion", "4",
        ], input="test\nn\nn\nn\n\n\n")

        with tempfile.TemporaryDirectory() as tmpdir:
            output_file = Path(tmpdir) / "output.csv"
            result = runner.invoke(main, ["export", "--format", "csv", "--output", str(output_file)])

            assert result.exit_code == 0
            assert "Exported to" in result.output
            assert output_file.exists()

    def test_export_empty(self, runner, temp_journal_env):
        """Test export with no trades."""
        result = runner.invoke(main, ["export", "--format", "json"])

        assert result.exit_code == 0
        # Either empty array or "No trades" message
        assert "[]" in result.output or "No trades" in result.output


class TestReportCommand:
    def test_report_week(self, runner, temp_journal_env):
        """Test weekly report."""
        result = runner.invoke(main, ["report", "--week"])

        assert result.exit_code == 0
        assert "Weekly" in result.output
        assert "SUMMARY" in result.output

    def test_report_month(self, runner, temp_journal_env):
        """Test monthly report."""
        result = runner.invoke(main, ["report", "--month"])

        assert result.exit_code == 0
        assert "Monthly" in result.output
        assert "SUMMARY" in result.output

    def test_report_default(self, runner, temp_journal_env):
        """Test report defaults to weekly."""
        result = runner.invoke(main, ["report"])

        assert result.exit_code == 0
        assert "Weekly" in result.output


class TestTagsCommand:
    def test_tags_command(self, runner):
        """Test tags listing."""
        result = runner.invoke(main, ["tags"])

        assert result.exit_code == 0
        assert "fomo" in result.output
        assert "revenge" in result.output


class TestAnalyzeCommand:
    def test_analyze_command(self, runner, temp_journal_env):
        """Test analyze command."""
        result = runner.invoke(main, ["analyze"])

        assert result.exit_code == 0
        assert "MISTAKE PATTERN ANALYSIS" in result.output
