from pathlib import Path

from typer.testing import CliRunner

from c2m_by_nery.cli.main import app

runner = CliRunner()


def test_cli_version() -> None:
    result = runner.invoke(app, ["--version"])
    assert result.exit_code == 0
    assert "c2m-by-nery" in result.stdout
    assert "0.2.0" in result.stdout


def test_cli_help() -> None:
    result = runner.invoke(app, ["--help"])
    assert result.exit_code == 0
    assert "convert" in result.stdout.lower()
    assert "serve" in result.stdout.lower()
    result_convert = runner.invoke(app, ["convert", "--help"])
    assert result_convert.exit_code == 0
    assert "--tokens" in result_convert.stdout
    assert "directory" in result_convert.stdout or "path" in result_convert.stdout.lower()


def test_cli_minimal(tmp_path: Path) -> None:
    (tmp_path / "foo.py").write_text("x = 1")
    result = runner.invoke(app, ["--quiet", str(tmp_path)])
    assert result.exit_code == 0
    out = tmp_path / ".c2m" / "outputs"
    assert out.exists()
    timestamp_dirs = [d for d in out.iterdir() if d.is_dir()]
    assert len(timestamp_dirs) >= 1
    assert (timestamp_dirs[0] / "report.json").exists()
    assert (timestamp_dirs[0] / "foo.md").exists()


def test_cli_with_zip(tmp_path: Path) -> None:
    (tmp_path / "bar.py").write_text("y = 2")
    result = runner.invoke(app, ["--quiet", "--zip", str(tmp_path)])
    assert result.exit_code == 0
    zip_line = result.stdout.strip().replace("\n", "")
    assert zip_line.endswith(".zip")
    assert Path(zip_line).exists()


def test_cli_config_error(tmp_path: Path) -> None:
    (tmp_path / "c2m.yaml").write_text("token_limit: not_a_number")
    result = runner.invoke(app, [str(tmp_path)])
    assert result.exit_code == 1
    combined = result.stdout + result.stderr
    assert "Configuration" in combined or "error" in combined.lower()


def test_cli_tokens_override(tmp_path: Path) -> None:
    (tmp_path / "x.py").write_text("a = 1")
    result = runner.invoke(app, ["--quiet", "--tokens", "500", str(tmp_path)])
    assert result.exit_code == 0


def test_cli_with_flat(tmp_path: Path) -> None:
    (tmp_path / "src").mkdir()
    (tmp_path / "src" / "foo.py").write_text("x = 1")
    (tmp_path / "bar.py").write_text("y = 2")
    result = runner.invoke(app, ["--quiet", "--flat", str(tmp_path)])
    assert result.exit_code == 0
    out = tmp_path / ".c2m" / "outputs"
    timestamp_dirs = [d for d in out.iterdir() if d.is_dir()]
    assert len(timestamp_dirs) >= 1
    snap = timestamp_dirs[0]
    md_files = list(snap.glob("*.md"))
    assert len(md_files) >= 2
    names = [f.name for f in md_files]
    assert "src_foo.md" in names
    assert "bar.md" in names


def test_cli_with_single_file(tmp_path: Path) -> None:
    (tmp_path / "x.py").write_text("a = 1")
    (tmp_path / "y.py").write_text("b = 2")
    result = runner.invoke(app, ["--quiet", "--single-file", str(tmp_path)])
    assert result.exit_code == 0
    out = tmp_path / ".c2m" / "outputs"
    timestamp_dirs = [d for d in out.iterdir() if d.is_dir()]
    assert len(timestamp_dirs) >= 1
    output_md = timestamp_dirs[0] / "output.md"
    assert output_md.exists()
    assert "a = 1" in output_md.read_text()


def test_cli_non_quiet_shows_summary(tmp_path: Path) -> None:
    (tmp_path / "code.py").write_text("a = 1")
    result = runner.invoke(app, [str(tmp_path)])
    assert result.exit_code == 0
    assert "Done" in result.stdout or "Processed" in result.stdout
    assert "Output:" in result.stdout or "outputs" in result.stdout


def test_cli_no_frontmatter(tmp_path: Path) -> None:
    (tmp_path / "x.py").write_text("a = 1")
    result = runner.invoke(app, ["--quiet", "--no-frontmatter", str(tmp_path)])
    assert result.exit_code == 0
    out = tmp_path / ".c2m" / "outputs"
    timestamp_dirs = [d for d in out.iterdir() if d.is_dir()]
    content = (timestamp_dirs[0] / "x.md").read_text()
    assert "---" not in content or "Project:" not in content


def test_cli_single_file_input(tmp_path: Path) -> None:
    doc = tmp_path / "report.md"
    doc.write_text("# Title\n\nParagraph.")
    result = runner.invoke(app, ["--quiet", str(doc)])
    assert result.exit_code == 0
    out = tmp_path / ".c2m" / "outputs"
    assert out.exists()
    dirs = [d for d in out.iterdir() if d.is_dir()]
    assert len(dirs) >= 1
    snap = dirs[0]
    assert snap.name.startswith("report_")
    assert (snap / "report.json").exists()
    md_files = list(snap.glob("*.md"))
    assert len(md_files) >= 1
    assert any("Title" in f.read_text() or "Paragraph" in f.read_text() for f in md_files)


def test_cli_single_file_single_file_option(tmp_path: Path) -> None:
    (tmp_path / "x.py").write_text("a = 1")
    result = runner.invoke(app, ["--quiet", "--single-file", str(tmp_path / "x.py")])
    assert result.exit_code == 0
    out = tmp_path / ".c2m" / "outputs"
    dirs = [d for d in out.iterdir() if d.is_dir()]
    assert len(dirs) >= 1
    assert dirs[0].name.startswith("x_")
    output_md = dirs[0] / "output.md"
    assert output_md.exists()
    assert "a = 1" in output_md.read_text()


def test_cli_single_file_zip(tmp_path: Path) -> None:
    (tmp_path / "doc.py").write_text("content")
    result = runner.invoke(app, ["--quiet", "--zip", str(tmp_path / "doc.py")])
    assert result.exit_code == 0
    zip_line = result.stdout.strip().replace("\n", "")
    assert "doc_" in zip_line
    assert zip_line.endswith(".zip")
    assert Path(zip_line).exists()


def test_cli_single_file_no_frontmatter(tmp_path: Path) -> None:
    (tmp_path / "x.py").write_text("a = 1")
    result = runner.invoke(app, ["--quiet", "--no-frontmatter", str(tmp_path / "x.py")])
    assert result.exit_code == 0
    out = tmp_path / ".c2m" / "outputs"
    dirs = [d for d in out.iterdir() if d.is_dir()]
    assert len(dirs) >= 1
    content = (dirs[0] / "x.md").read_text()
    assert "---" not in content or "Project:" not in content
