"""
Tests for _quick_win_block — the post-init Quick Win output.

Covers:
  - Shows when verbose=True and file_count > 0
  - Hidden when verbose=False
  - Hidden when file_count == 0
  - Savings % is between 0 and 99 (inclusive)
  - raw_tokens = file_count * 800
  - kodara_tokens uses min(8, file_count) * 250
  - Output contains key strings
  - Cost calculation correctness
  - 100-file scenario
  - 5-file scenario (min behaviour)

Run: pytest tests/test_quick_win.py -v
"""

from __future__ import annotations

from types import SimpleNamespace
from unittest.mock import patch, call

import pytest

# Import the function under test
from kodara.cli.main import _quick_win_block


# ── Helpers ───────────────────────────────────────────────────────────────────

def _make_idx(file_count: int):
    """Build a minimal fake KodaraIndex-like object with `modules`."""
    return SimpleNamespace(modules={str(i): {} for i in range(file_count)})


def _capture_output(file_count: int, verbose: bool = True) -> list[str]:
    """Run _quick_win_block and return list of strings passed to _out."""
    idx = _make_idx(file_count)
    captured: list[str] = []
    with patch("kodara.cli.main._out", side_effect=lambda msg: captured.append(msg)):
        _quick_win_block(idx, verbose=verbose)
    return captured


# ── Tests ──────────────────────────────────────────────────────────────────────

class TestQuickWinVisibility:

    def test_shows_when_verbose_true_and_files_present(self):
        lines = _capture_output(file_count=10, verbose=True)
        assert len(lines) > 0, "Expected output when verbose=True and file_count>0"

    def test_hidden_when_verbose_false(self):
        lines = _capture_output(file_count=10, verbose=False)
        assert lines == [], "Expected no output when verbose=False"

    def test_hidden_when_file_count_zero(self):
        lines = _capture_output(file_count=0, verbose=True)
        assert lines == [], "Expected no output when file_count=0"


class TestQuickWinContent:

    def test_output_contains_kodara_ready(self):
        lines = _capture_output(file_count=20, verbose=True)
        full = "\n".join(lines)
        assert "Kodara ready" in full

    def test_output_contains_try_now(self):
        lines = _capture_output(file_count=20, verbose=True)
        full = "\n".join(lines)
        assert "Try now" in full

    def test_output_contains_kodara_ask(self):
        lines = _capture_output(file_count=20, verbose=True)
        full = "\n".join(lines)
        assert "kodara ask" in full

    def test_output_contains_file_count(self):
        lines = _capture_output(file_count=42, verbose=True)
        full = "\n".join(lines)
        assert "42" in full


class TestQuickWinCalculations:

    def test_raw_tokens_equals_file_count_times_800(self):
        file_count = 50
        raw_tokens = file_count * 800
        lines = _capture_output(file_count=file_count, verbose=True)
        full = "\n".join(lines)
        assert f"{raw_tokens:,}" in full or str(raw_tokens) in full

    def test_kodara_tokens_uses_min_8_files(self):
        # 100 files -> min(8, 100) = 8 -> 8 * 250 = 2000
        kodara_tokens = 8 * 250
        lines = _capture_output(file_count=100, verbose=True)
        full = "\n".join(lines)
        assert f"{kodara_tokens:,}" in full or str(kodara_tokens) in full

    def test_savings_pct_between_0_and_99(self):
        """Savings percentage must be capped at 99 and never negative."""
        for file_count in [1, 5, 10, 100, 1000]:
            raw_tokens    = file_count * 800
            kodara_tokens = min(8, file_count) * 250
            savings_pct   = min(99, int((raw_tokens - kodara_tokens) / raw_tokens * 100))
            assert 0 <= savings_pct <= 99, (
                f"savings_pct={savings_pct} out of range for file_count={file_count}"
            )

    def test_cost_calculation_uses_3_per_1m_tokens(self):
        file_count = 100
        raw_tokens    = file_count * 800          # 80000
        kodara_tokens = min(8, file_count) * 250  # 2000
        cost_raw      = raw_tokens    / 1_000_000 * 3
        cost_kodara   = kodara_tokens / 1_000_000 * 3
        lines = _capture_output(file_count=file_count, verbose=True)
        full = "\n".join(lines)
        # Check formatted cost strings appear in output
        assert f"${cost_raw:.2f}" in full
        assert f"${cost_kodara:.2f}" in full


class TestQuickWinScenarios:

    def test_100_files_scenario(self):
        """100 files: raw=80000, kodara=2000, savings=97%."""
        file_count    = 100
        raw_tokens    = file_count * 800          # 80000
        kodara_tokens = min(8, file_count) * 250  # 2000
        savings_pct   = min(99, int((raw_tokens - kodara_tokens) / raw_tokens * 100))

        assert raw_tokens    == 80_000
        assert kodara_tokens == 2_000
        assert savings_pct   == 97

        lines = _capture_output(file_count=file_count, verbose=True)
        full  = "\n".join(lines)
        assert "80,000" in full or "80000" in full
        assert "2,000"  in full or "2000"  in full
        assert "97%"    in full

    def test_5_files_uses_5_not_8(self):
        """5 files: min(8, 5) = 5, so kodara_tokens = 5 * 250 = 1250."""
        file_count    = 5
        kodara_tokens = min(8, file_count) * 250  # 1250, NOT 2000

        assert kodara_tokens == 1_250

        lines = _capture_output(file_count=file_count, verbose=True)
        full  = "\n".join(lines)
        assert "1,250" in full or "1250" in full
