import sys
import unittest
from os import environ
from os.path import exists
from dhpython.interpreter import Interpreter


class TestInterpreter(unittest.TestCase):
    def setUp(self) -> None:
        self._triplet = environ.get("DEB_HOST_MULTIARCH")
        environ["DEB_HOST_MULTIARCH"] = "MYARCH"

    def tearDown(self) -> None:
        if self._triplet:
            environ["DEB_HOST_MULTIARCH"] = self._triplet
        else:
            del environ["DEB_HOST_MULTIARCH"]

    @unittest.skipUnless(exists("/usr/bin/python3.11"), "python3.11 is not installed")
    def test_python311(self) -> None:
        i = Interpreter("python3.11")
        self.assertEqual(i.check_extname("foo.so"), r"foo.cpython-311-MYARCH.so")
        self.assertIsNone(i.check_extname("foo.cpython-32m.so"))  # different version
        self.assertIsNone(
            i.check_extname("foo.cpython-311-OTHER.so")
        )  # different architecture
        self.assertEqual(
            i.check_extname("foo.cpython-311.so"), r"foo.cpython-311-MYARCH.so"
        )
        self.assertIsNone(i.check_extname("foo.abi3.so"))
        self.assertEqual(
            i.check_extname("foo/bar/bazmodule.so"),
            r"foo/bar/baz.cpython-311-MYARCH.so",
        )

    @unittest.skipUnless(
        exists("/usr/bin/python3.11-dbg"), "python3.11-dbg is not installed"
    )
    def test_python311dbg(self) -> None:
        i = Interpreter("python3.11-dbg")
        self.assertEqual(i.check_extname("foo.so"), r"foo.cpython-311d-MYARCH.so")
        self.assertIsNone(i.check_extname("foo.cpython-32m.so"))  # different version
        self.assertIsNone(
            i.check_extname("foo.cpython-311-OTHER.so")
        )  # different architecture
        self.assertIsNone(i.check_extname("foo.abi3.so"))
        self.assertEqual(
            i.check_extname("foo/bar/bazmodule.so"),
            r"foo/bar/baz.cpython-311d-MYARCH.so",
        )

    @unittest.skipUnless(exists("/usr/bin/python3.12"), "python3.12 is not installed")
    def test_python312(self) -> None:
        i = Interpreter("python3.12")
        self.assertEqual(i.check_extname("foo.so"), r"foo.cpython-312-MYARCH.so")
        self.assertIsNone(i.check_extname("foo.cpython-32m.so"))  # different version
        self.assertIsNone(
            i.check_extname("foo.cpython-312-OTHER.so")
        )  # different architecture
        self.assertEqual(
            i.check_extname("foo.cpython-312.so"), r"foo.cpython-312-MYARCH.so"
        )
        self.assertIsNone(i.check_extname("foo.abi3.so"))
        self.assertEqual(
            i.check_extname("foo/bar/bazmodule.so"),
            r"foo/bar/baz.cpython-312-MYARCH.so",
        )

    @unittest.skipUnless(
        exists("/usr/bin/python3.12-dbg"), "python3.12-dbg is not installed"
    )
    def test_python312dbg(self) -> None:
        i = Interpreter("python3.12-dbg")
        self.assertEqual(i.check_extname("foo.so"), r"foo.cpython-312d-MYARCH.so")
        self.assertIsNone(i.check_extname("foo.cpython-32m.so"))  # different version
        self.assertIsNone(
            i.check_extname("foo.cpython-312-OTHER.so")
        )  # different architecture
        self.assertIsNone(i.check_extname("foo.abi3.so"))
        self.assertEqual(
            i.check_extname("foo/bar/bazmodule.so"),
            r"foo/bar/baz.cpython-312d-MYARCH.so",
        )

    @unittest.skipUnless(exists("/usr/bin/python3.13"), "python3.13 is not installed")
    def test_python313(self) -> None:
        i = Interpreter("python3.13")
        self.assertEqual(i.check_extname("foo.so"), r"foo.cpython-313-MYARCH.so")
        self.assertIsNone(i.check_extname("foo.cpython-33m.so"))  # different version
        self.assertIsNone(
            i.check_extname("foo.cpython-313-OTHER.so")
        )  # different architecture
        self.assertEqual(
            i.check_extname("foo.cpython-313.so"), r"foo.cpython-313-MYARCH.so"
        )
        self.assertEqual(i.check_extname("foo.abi3.so"), "foo.abi3-MYARCH.so")
        self.assertIsNone(i.check_extname("foo.abi3-OTHER.so"))
        self.assertEqual(
            i.check_extname("foo/bar/bazmodule.so"),
            r"foo/bar/baz.cpython-313-MYARCH.so",
        )

    @unittest.skipUnless(
        exists("/usr/bin/python3.13-dbg"), "python3.13-dbg is not installed"
    )
    def test_python313dbg(self) -> None:
        i = Interpreter("python3.13-dbg")
        self.assertEqual(i.check_extname("foo.so"), r"foo.cpython-313d-MYARCH.so")
        self.assertIsNone(i.check_extname("foo.cpython-33m.so"))  # different version
        self.assertIsNone(
            i.check_extname("foo.cpython-313-OTHER.so")
        )  # different architecture
        self.assertEqual(i.check_extname("foo.abi3.so"), "foo.abi3-MYARCH.so")
        self.assertIsNone(i.check_extname("foo.abi3-OTHER.so"))
        self.assertEqual(
            i.check_extname("foo/bar/bazmodule.so"),
            r"foo/bar/baz.cpython-313d-MYARCH.so",
        )

    @unittest.skipUnless(exists("/usr/bin/python3.14"), "python3.14 is not installed")
    def test_python314(self) -> None:
        i = Interpreter("python3.14")
        self.assertEqual(i.check_extname("foo.so"), r"foo.cpython-314-MYARCH.so")
        self.assertIsNone(i.check_extname("foo.cpython-34m.so"))  # different version
        self.assertIsNone(
            i.check_extname("foo.cpython-314-OTHER.so")
        )  # different architecture
        self.assertEqual(
            i.check_extname("foo.cpython-314.so"), r"foo.cpython-314-MYARCH.so"
        )
        self.assertEqual(i.check_extname("foo.abi3.so"), "foo.abi3-MYARCH.so")
        self.assertIsNone(i.check_extname("foo.abi3-OTHER.so"))
        self.assertEqual(
            i.check_extname("foo/bar/bazmodule.so"),
            r"foo/bar/baz.cpython-314-MYARCH.so",
        )

    @unittest.skipUnless(
        exists("/usr/bin/python3.14-dbg"), "python3.14-dbg is not installed"
    )
    def test_python314dbg(self) -> None:
        i = Interpreter("python3.14-dbg")
        self.assertEqual(i.check_extname("foo.so"), r"foo.cpython-314d-MYARCH.so")
        self.assertIsNone(i.check_extname("foo.cpython-34m.so"))  # different version
        self.assertIsNone(
            i.check_extname("foo.cpython-314-OTHER.so")
        )  # different architecture
        self.assertEqual(i.check_extname("foo.abi3.so"), "foo.abi3-MYARCH.so")
        self.assertIsNone(i.check_extname("foo.abi3-OTHER.so"))
        self.assertEqual(
            i.check_extname("foo/bar/bazmodule.so"),
            r"foo/bar/baz.cpython-314d-MYARCH.so",
        )

    def test_python3(self) -> None:
        i = Interpreter("python{}.{}".format(*sys.version_info[:2]))
        pyver = "{}{}".format(*sys.version_info[:2])
        self.assertEqual(i.check_extname("foo.so"), rf"foo.cpython-{pyver}-MYARCH.so")
        self.assertIsNone(i.check_extname("foo.cpython-32m.so"))  # different version
        self.assertIsNone(
            i.check_extname(f"foo.cpython-{pyver}-OTHER.so")
        )  # different architecture
        self.assertEqual(
            i.check_extname(f"foo.cpython-{pyver}.so"),
            rf"foo.cpython-{pyver}-MYARCH.so",
        )
        self.assertEqual(i.check_extname("foo.abi3.so"), "foo.abi3-MYARCH.so")
        self.assertIsNone(i.check_extname("foo.abi3-OTHER.so"))
        self.assertEqual(
            i.check_extname("foo/bar/bazmodule.so"),
            rf"foo/bar/baz.cpython-{pyver}-MYARCH.so",
        )

    @unittest.skipUnless(exists("/usr/bin/python3-dbg"), "python3-dbg is not installed")
    def test_python3dbg(self) -> None:
        i = Interpreter("python{}.{}-dbg".format(*sys.version_info[:2]))
        pyver = "{}{}".format(*sys.version_info[:2])
        self.assertEqual(i.check_extname("foo.so"), rf"foo.cpython-{pyver}d-MYARCH.so")
        self.assertIsNone(i.check_extname("foo.cpython-32m.so"))  # different version
        self.assertIsNone(
            i.check_extname(f"foo.cpython-{pyver}-OTHER.so")
        )  # different architecture
        self.assertEqual(i.check_extname("foo.abi3.so"), "foo.abi3-MYARCH.so")
        self.assertIsNone(i.check_extname("foo.abi3-OTHER.so"))
        self.assertEqual(
            i.check_extname("foo/bar/bazmodule.so"),
            rf"foo/bar/baz.cpython-{pyver}d-MYARCH.so",
        )

    def test_bare_module(self) -> None:
        i = Interpreter("python{}.{}".format(*sys.version_info[:2]))
        pyver = "{}{}".format(*sys.version_info[:2])
        self.assertEqual(
            i.check_extname("module.so"), rf"module.cpython-{pyver}-MYARCH.so"
        )
        self.assertEqual(
            i.check_extname("_module.so"), rf"_module.cpython-{pyver}-MYARCH.so"
        )


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