from asynctnt import Response
from asynctnt.exceptions import TarantoolSchemaError
from tests import BaseTarantoolTestCase


class DeleteTestCase(BaseTarantoolTestCase):
    async def _fill_data(self):
        data = [
            [0, "a", 1, 2, "hello my darling"],
            [1, "b", 3, 4, "hello my darling, again"],
        ]
        for t in data:
            await self.conn.insert(self.TESTER_SPACE_ID, t)

        return data

    async def test__delete_one(self):
        data = await self._fill_data()

        res = await self.conn.delete(self.TESTER_SPACE_ID, [data[0][0]])
        self.assertIsInstance(res, Response, "Got response")
        self.assertEqual(res.code, 0, "success")
        self.assertGreater(res.sync, 0, "sync > 0")
        self.assertResponseEqual(res, [data[0]], "Body ok")

        res = await self.conn.select(self.TESTER_SPACE_ID, [0])
        self.assertResponseEqual(res, [], "Body ok")

    async def test__delete_by_name(self):
        data = await self._fill_data()

        res = await self.conn.delete(self.TESTER_SPACE_NAME, [data[0][0]])
        self.assertIsInstance(res, Response, "Got response")
        self.assertEqual(res.code, 0, "success")
        self.assertGreater(res.sync, 0, "sync > 0")
        self.assertResponseEqual(res, [data[0]], "Body ok")

        res = await self.conn.select(self.TESTER_SPACE_ID, [0])
        self.assertResponseEqual(res, [], "Body ok")

    async def test__delete_by_index_id(self):
        index_name = "temp_idx"
        res = self.tnt.command('make_third_index("{}")'.format(index_name))
        index_id = res[0][0]

        try:
            await self.tnt_reconnect()

            data = await self._fill_data()

            res = await self.conn.delete(
                self.TESTER_SPACE_NAME, [data[1][2]], index=index_id
            )
            self.assertIsInstance(res, Response, "Got response")
            self.assertEqual(res.code, 0, "success")
            self.assertGreater(res.sync, 0, "sync > 0")
            self.assertResponseEqual(res, [data[1]], "Body ok")

            res = await self.conn.select(
                self.TESTER_SPACE_ID, [data[1][2]], index=index_id
            )
            self.assertResponseEqual(res, [], "Body ok")
        finally:
            self.tnt.command(
                "box.space.{}.index.{}:drop()".format(
                    self.TESTER_SPACE_NAME, index_name
                )
            )

    async def test__delete_by_index_name(self):
        index_name = "temp_idx"
        res = self.tnt.command('make_third_index("{}")'.format(index_name))
        index_id = res[0][0]

        try:
            await self.tnt_reconnect()

            data = await self._fill_data()

            res = await self.conn.delete(
                self.TESTER_SPACE_NAME, [data[1][2]], index=index_name
            )
            self.assertIsInstance(res, Response, "Got response")
            self.assertEqual(res.code, 0, "success")
            self.assertGreater(res.sync, 0, "sync > 0")
            self.assertResponseEqual(res, [data[1]], "Body ok")

            res = await self.conn.select(
                self.TESTER_SPACE_ID, [data[1][2]], index=index_id
            )
            self.assertResponseEqual(res, [], "Body ok")
        finally:
            self.tnt.command(
                "box.space.{}.index.{}:drop()".format(
                    self.TESTER_SPACE_NAME, index_name
                )
            )

    async def test__delete_by_name_no_schema(self):
        await self.tnt_reconnect(fetch_schema=False)

        with self.assertRaises(TarantoolSchemaError):
            await self.conn.delete(self.TESTER_SPACE_NAME, [0])

    async def test__delete_by_index_name_no_schema(self):
        await self.tnt_reconnect(fetch_schema=False)

        with self.assertRaises(TarantoolSchemaError):
            await self.conn.delete(self.TESTER_SPACE_ID, [0], index="primary")

    async def test__delete_invalid_types(self):
        with self.assertRaisesRegex(
            TypeError, "missing 2 required positional arguments: 'space' and 'key'"
        ):
            await self.conn.delete()

    async def test__delete_key_tuple(self):
        try:
            await self.conn.delete(self.TESTER_SPACE_ID, (1,))
        except Exception as e:
            self.fail(e)

    async def test__delete_dict_key(self):
        data = await self._fill_data()

        res = await self.conn.delete(self.TESTER_SPACE_ID, {"f1": 0})
        self.assertResponseEqual(res, [data[0]], "Body ok")

    async def test__delete_dict_resp(self):
        data = [0, "hello", 0, 1, "wow"]
        await self.conn.insert(self.TESTER_SPACE_ID, data)

        res = await self.conn.delete(self.TESTER_SPACE_ID, [0])
        self.assertResponseEqualKV(
            res, [{"f1": 0, "f2": "hello", "f3": 0, "f4": 1, "f5": "wow"}]
        )
