import subprocess
import tempfile
import unittest
from pathlib import Path
from unittest.mock import patch, MagicMock
from bot.lib import release


class TestParseDotenv(unittest.TestCase):
    def setUp(self):
        self.tmp = Path(tempfile.mkdtemp())

    def test_simple_kv(self):
        p = self.tmp / ".env"
        p.write_text("FOO=bar\nBAZ=qux\n", encoding="utf-8")
        self.assertEqual(release.parse_dotenv(p), {"FOO": "bar", "BAZ": "qux"})

    def test_skips_comments_and_blanks(self):
        p = self.tmp / ".env"
        p.write_text("# a comment\n\nFOO=bar\n   \n# another\nBAZ=qux\n", encoding="utf-8")
        self.assertEqual(release.parse_dotenv(p), {"FOO": "bar", "BAZ": "qux"})

    def test_strips_quotes(self):
        p = self.tmp / ".env"
        p.write_text('FOO="bar"\nBAZ=\'qux\'\n', encoding="utf-8")
        self.assertEqual(release.parse_dotenv(p), {"FOO": "bar", "BAZ": "qux"})

    def test_strips_export_prefix(self):
        p = self.tmp / ".env"
        p.write_text("export FOO=bar\n", encoding="utf-8")
        self.assertEqual(release.parse_dotenv(p), {"FOO": "bar"})


class TestRunRelease(unittest.TestCase):
    def setUp(self):
        self.tmp = Path(tempfile.mkdtemp())
        self.repo = self.tmp / "repo"
        self.repo.mkdir()
        (self.repo / ".release").mkdir()
        (self.repo / ".release" / "release.sh").write_text("#!/bin/bash\nexit 0\n", encoding="utf-8")
        (self.repo / ".env").write_text("CF_API_KEY=secret-key-123\n", encoding="utf-8")

    def test_runs_release_sh_with_cf_api_key_in_env(self):
        captured = {}
        def run(cmd, *args, **kwargs):
            captured["cmd"] = cmd
            captured["env"] = kwargs.get("env", {})
            captured["cwd"] = kwargs.get("cwd")
            return MagicMock(returncode=0, stdout="ok", stderr="")
        with patch("subprocess.run", side_effect=run):
            r = release.run_release(self.repo)
        self.assertTrue(r.success)
        self.assertEqual(r.returncode, 0)
        self.assertEqual(captured["cmd"][0], "bash")
        self.assertIn("release.sh", captured["cmd"][1])
        self.assertEqual(captured["env"].get("CF_API_KEY"), "secret-key-123")
        self.assertEqual(str(captured["cwd"]), str(self.repo))

    def test_returns_failure_on_nonzero(self):
        with patch("subprocess.run", return_value=MagicMock(returncode=2, stdout="", stderr="boom")):
            r = release.run_release(self.repo)
        self.assertFalse(r.success)
        self.assertEqual(r.returncode, 2)
        self.assertEqual(r.stderr, "boom")

    def test_missing_release_sh_raises_filenotfound(self):
        (self.repo / ".release" / "release.sh").unlink()
        with self.assertRaises(FileNotFoundError):
            release.run_release(self.repo)

    def test_missing_dotenv_raises_filenotfound(self):
        (self.repo / ".env").unlink()
        with self.assertRaises(FileNotFoundError):
            release.run_release(self.repo)

    def test_missing_cf_api_key_raises_keyerror(self):
        (self.repo / ".env").write_text("OTHER=value\n", encoding="utf-8")
        with self.assertRaises(KeyError):
            release.run_release(self.repo)


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