"""Tests for ``mgf-common feedback`` subcommand."""

from __future__ import annotations

import argparse
import io
from contextlib import redirect_stdout

from mgf.fed.cli._feedback import (
    _FEEDBACK_URL,
    _TEMPLATE,
    add_feedback_args,
    run_feedback,
)


def _make_args(*, template: bool = False, url: bool = False) -> argparse.Namespace:
    parser = argparse.ArgumentParser()
    add_feedback_args(parser)
    argv: list[str] = []
    if template:
        argv.append("--template")
    if url:
        argv.append("--url")
    return parser.parse_args(argv)


class TestOverview:
    def test_no_args_prints_overview(self) -> None:
        buf = io.StringIO()
        with redirect_stdout(buf):
            exit_code = run_feedback(_make_args())
        assert exit_code == 0
        out = buf.getvalue()
        assert "Submitting feedback to mgf-common" in out
        assert "Severity guide" in out
        assert "How to submit" in out
        # The URL must appear in the overview.
        assert _FEEDBACK_URL in out

    def test_overview_has_severity_levels(self) -> None:
        buf = io.StringIO()
        with redirect_stdout(buf):
            run_feedback(_make_args())
        out = buf.getvalue()
        # All 4 severity emojis must be present.
        for emoji in ("🔴", "🟡", "🟢", "💭"):
            assert emoji in out


class TestTemplate:
    def test_template_flag_prints_template(self) -> None:
        buf = io.StringIO()
        with redirect_stdout(buf):
            exit_code = run_feedback(_make_args(template=True))
        assert exit_code == 0
        out = buf.getvalue()
        # The template MUST contain the canonical entry shape.
        assert "<AREA>-<NN>" in out
        assert "Status |" in out
        assert "Severity |" in out
        assert "Submitter |" in out
        # Required prose sections.
        assert "**Concern.**" in out
        assert "**Why it matters.**" in out
        assert "**Suggested shape.**" in out

    def test_template_matches_module_constant(self) -> None:
        # Pin the template content to the constant so changes are
        # explicit.
        buf = io.StringIO()
        with redirect_stdout(buf):
            run_feedback(_make_args(template=True))
        # The output ends with one trailing newline from print().
        assert buf.getvalue().rstrip("\n") == _TEMPLATE.rstrip("\n")


class TestUrl:
    def test_url_flag_prints_url_only(self) -> None:
        buf = io.StringIO()
        with redirect_stdout(buf):
            exit_code = run_feedback(_make_args(url=True))
        assert exit_code == 0
        # Just the URL on its own line, no extra prose.
        assert buf.getvalue().strip() == _FEEDBACK_URL

    def test_url_is_codeberg_canonical(self) -> None:
        # Don't drift the URL silently — pin the host + path shape.
        # Post-2026-05-24 cutover: canonical slug is hyphenated
        # (`mgf-common`), per NM-03. Old `mgf_common` slug was
        # renamed; Forgejo does not auto-redirect.
        assert _FEEDBACK_URL.startswith("https://codeberg.org/")
        assert "mgf-common" in _FEEDBACK_URL
        assert "mgf_common" not in _FEEDBACK_URL
        assert _FEEDBACK_URL.endswith("FEEDBACK.md")


class TestExitCodes:
    def test_all_modes_return_zero(self) -> None:
        # Every mode of the subcommand returns 0; nothing is an
        # error condition.
        for args in (
            _make_args(),
            _make_args(template=True),
            _make_args(url=True),
        ):
            buf = io.StringIO()
            with redirect_stdout(buf):
                assert run_feedback(args) == 0
