from __future__ import annotations

import re
import subprocess
import sys
import unittest
from pathlib import Path

import exile


class ReleaseMetadataTests(unittest.TestCase):
    def test_version_sync_between_pyproject_and_init(self) -> None:
        root = Path(__file__).resolve().parents[1]
        pyproject_text = (root / "pyproject.toml").read_text(encoding="utf-8")
        match = re.search(r'(?m)^version\s*=\s*"([^"]+)"\s*$', pyproject_text)
        self.assertIsNotNone(match, "version not found in pyproject.toml")
        self.assertEqual(exile.__version__, match.group(1))

    def test_release_docs_exist(self) -> None:
        root = Path(__file__).resolve().parents[1]
        self.assertTrue((root / "RELEASE.md").exists())
        self.assertTrue((root / "CHANGELOG.md").exists())
        self.assertTrue((root / "exile" / "py.typed").exists())
        self.assertTrue((root / "scripts" / "smoke_test_wheel.py").exists())
        self.assertTrue((root / "scripts" / "build_dists.py").exists())
        self.assertTrue((root / "scripts" / "check_dist_artifacts.py").exists())
        self.assertTrue((root / "scripts" / "publish_testpypi.sh").exists())
        self.assertTrue((root / ".github" / "release.yml").exists())

    def test_changelog_contains_current_version_heading(self) -> None:
        root = Path(__file__).resolve().parents[1]
        changelog_text = (root / "CHANGELOG.md").read_text(encoding="utf-8")
        pattern = rf"(?m)^##\s+\[{re.escape(exile.__version__)}\]\s+-\s+"
        self.assertRegex(changelog_text, pattern)

    def test_version_has_semver_shape(self) -> None:
        self.assertRegex(exile.__version__, r"^\d+\.\d+\.\d+$")

    def test_bump_version_script_dry_run(self) -> None:
        root = Path(__file__).resolve().parents[1]
        script = root / "scripts" / "bump_version.py"
        result = subprocess.run(
            [sys.executable, str(script), "9.9.9", "--dry-run"],
            cwd=root,
            capture_output=True,
            text=True,
            check=False,
        )
        self.assertEqual(result.returncode, 0, msg=result.stderr)
        self.assertIn("pyproject.toml -> version 9.9.9", result.stdout)

    def test_bump_version_script_rejects_invalid_version(self) -> None:
        root = Path(__file__).resolve().parents[1]
        script = root / "scripts" / "bump_version.py"
        result = subprocess.run(
            [sys.executable, str(script), "1.2", "--dry-run"],
            cwd=root,
            capture_output=True,
            text=True,
            check=False,
        )
        self.assertNotEqual(result.returncode, 0)

    def test_changelog_content_check_script_passes(self) -> None:
        root = Path(__file__).resolve().parents[1]
        script = root / "scripts" / "check_changelog_content.py"
        result = subprocess.run(
            [sys.executable, str(script)],
            cwd=root,
            capture_output=True,
            text=True,
            check=False,
        )
        self.assertEqual(result.returncode, 0, msg=result.stderr or result.stdout)


if __name__ == "__main__":
    unittest.main()
