# -*- coding: utf-8 -*-
import random
import sdk_test

class TestCustomTable(sdk_test.TestSdk):
    def test_custom_table_crud(self):
        table_name = "test_preferences_" + str(random.randint(1, 10000))
        columns = [
            {'name': 'user_id', 'type': 'text', 'not_null': True, 'unique': True, 'sync': True},
            {'name': 'preference_key', 'type': 'text', 'not_null': True},
            {'name': 'preference_value', 'type': 'text'},
            {'name': 'score', 'type': 'numeric', 'default': '0'},
            {'name': 'is_active', 'type': 'boolean', 'default': 'false'},
        ]
        lookup_key = ['user_id']

        # create
        table_id = self.client.new_custom_table(
            name=table_name,
            columns=columns,
            lookup_key=lookup_key,
            description='Test user preferences table',
            send_event=False,
        )
        self.assertIs(type(table_id), int)
        self.assertGreater(table_id, 0)

        # get one
        data = self.client.get_custom_table(table_id)
        self.assertEqual(data['name'], table_name)
        self.assertEqual(data['description'], 'Test user preferences table')
        self.assertIn('user_id', data['lookup_key'])
        self.assertEqual(len(data['columns']), 5)

        # update without column
        ok = self.client.put_custom_table(
            table_id=table_id,
        )
        self.assertTrue(ok)

        data = self.client.get_custom_table(table_id)
        self.assertEqual(len(data['columns']), 5)

        # update
        updated_columns = [
            {'name': 'user_id', 'type': 'text', 'not_null': True, 'unique': True, 'sync': True},
            {'name': 'preference_key', 'type': 'text', 'not_null': True},
            {'name': 'preference_value', 'type': 'text'},
            {'name': 'score', 'type': 'numeric', 'default': '0'},
            {'name': 'is_active', 'type': 'boolean', 'default': 'false'},
            {'name': 'notes', 'type': 'text'},
        ]
        ok = self.client.put_custom_table(
            table_id=table_id,
            columns=updated_columns,
            description='Updated test user preferences table',
        )
        self.assertTrue(ok)

        data = self.client.get_custom_table(table_id)
        self.assertEqual(data['description'], 'Updated test user preferences table')
        self.assertEqual(len(data['columns']), 6)

        # get all
        all_tables = self.client.get_all_custom_tables()
        self.assertIsNotNone(all_tables)

        # delete
        ok = self.client.del_custom_table(table_id)
        self.assertTrue(ok)

        data = self.client.get_custom_table(table_id)
        self.assertEqual(data, dict())

    def test_custom_table_data_crud(self):
        columns = [
            {'name': 'username', 'type': 'text', 'not_null': True, 'unique': True, 'sync': True},
            {'name': 'email', 'type': 'text'},
            {'name': 'age', 'type': 'numeric'},
            {'name': 'active', 'type': 'boolean', 'default': 'true'},
        ]
        lookup_key = ['username']

        table_name = "test_users_" + str(random.randint(1, 10000))
        table_id = self.client.new_custom_table(
            name=table_name,
            columns=columns,
            lookup_key=lookup_key,
            description='Test users table for data ops',
        )
        self.assertIs(type(table_id), int)
        self.assertGreater(table_id, 0)

        # insert rows
        rows = [
            {'username': 'alice', 'email': 'alice@example.com', 'age': 30, 'active': True},
            {'username': 'bob', 'email': 'bob@example.com', 'age': 25, 'active': False},
            {'username': 'charlie', 'email': 'charlie@example.com', 'age': 35, 'active': True},
        ]
        insert_result = self.client.insert_custom_table_data(
            table_name=table_name,
            rows=rows,
        )
        self.assertTrue(self.client.request_ok())
        self.assertIsNotNone(insert_result)
        self.assertEqual(len(insert_result), 3)

        # select all
        select_result = self.client.select_custom_table_data(
            table_name=table_name,
            page=1,
            page_size=10,
        )
        self.assertTrue(self.client.request_ok())
        self.assertIsNotNone(select_result)
        self.assertIn('data', select_result)
        self.assertEqual(len(select_result['data']), 3)
        self.assertEqual(select_result['meta']['count'], 3)

        # select with filter
        select_result = self.client.select_custom_table_data(
            table_name=table_name,
            wheres={'username': 'alice'},
        )
        self.assertTrue(self.client.request_ok())
        self.assertEqual(len(select_result['data']), 1)
        self.assertEqual(select_result['data'][0]['username'], 'alice')

        # select with ordering
        select_result = self.client.select_custom_table_data(
            table_name=table_name,
            order_key='age',
            order_direction='asc',
        )
        self.assertTrue(self.client.request_ok())
        self.assertEqual(select_result['data'][0]['username'], 'bob')
        self.assertEqual(select_result['data'][2]['username'], 'charlie')

        # update by id
        record_id = insert_result[0]
        ok = self.client.update_custom_table_data(
            table_name=table_name,
            row={'email': 'alice_updated@example.com', 'age': 31},
            id=record_id,
        )
        self.assertTrue(self.client.request_ok())
        self.assertTrue(ok)

        select_result = self.client.select_custom_table_data(
            table_name=table_name,
            wheres={'username': 'alice'},
        )
        self.assertEqual(select_result['data'][0]['email'], 'alice_updated@example.com')
        self.assertEqual(select_result['data'][0]['age'], 31)

        # update by lookup_kv
        ok = self.client.update_custom_table_data(
            table_name=table_name,
            row={'email': 'bob_updated@example.com'},
            lookup_kv={'username': 'bob'},
        )
        self.assertTrue(self.client.request_ok())
        self.assertTrue(ok)

        select_result = self.client.select_custom_table_data(
            table_name=table_name,
            wheres={'username': 'bob'},
        )
        self.assertEqual(select_result['data'][0]['email'], 'bob_updated@example.com')

        # delete by lookup_kv
        ok = self.client.delete_custom_table_data(
            table_name=table_name,
            lookup_kv={'username': 'charlie'},
        )
        self.assertTrue(self.client.request_ok())
        self.assertTrue(ok)

        select_result = self.client.select_custom_table_data(
            table_name=table_name,
        )
        self.assertEqual(select_result['meta']['count'], 2)

        # delete by id
        ok = self.client.delete_custom_table_data(
            table_name=table_name,
            id=record_id,
        )
        self.assertTrue(self.client.request_ok())
        self.assertTrue(ok)

        select_result = self.client.select_custom_table_data(
            table_name=table_name,
        )
        self.assertEqual(select_result['meta']['count'], 1)

        # cleanup table
        ok = self.client.del_custom_table(table_id)
        self.assertTrue(ok)

    def test_custom_table_data_pagination(self):
        columns = [
            {'name': 'key', 'type': 'text', 'not_null': True, 'unique': True, 'sync': True},
            {'name': 'value', 'type': 'text'},
        ]
        lookup_key = ['key']

        table_name = "test_pagination_" + str(random.randint(1, 10000))
        table_id = self.client.new_custom_table(
            name=table_name,
            columns=columns,
            lookup_key=lookup_key,
        )
        self.assertIs(type(table_id), int)
        self.assertGreater(table_id, 0)

        # insert multiple rows
        rows = [{'key': 'item_{}'.format(i), 'value': 'val_{}'.format(i)} for i in range(10)]
        insert_result = self.client.insert_custom_table_data(
            table_name=table_name,
            rows=rows,
        )
        self.assertTrue(self.client.request_ok())
        self.assertEqual(len(insert_result), 10)

        # page 1
        select_result = self.client.select_custom_table_data(
            table_name=table_name,
            page=1,
            page_size=3,
        )
        self.assertTrue(self.client.request_ok())
        self.assertEqual(len(select_result['data']), 3)
        self.assertEqual(select_result['meta']['count'], 10)

        # page 2
        select_result = self.client.select_custom_table_data(
            table_name=table_name,
            page=2,
            page_size=3,
        )
        self.assertTrue(self.client.request_ok())
        self.assertEqual(len(select_result['data']), 3)

        # cleanup
        ok = self.client.del_custom_table(table_id)
        self.assertTrue(ok)

    def test_custom_table_column_types(self):
        columns = [
            {'name': 'id_col', 'type': 'numeric', 'not_null': True, 'sync': True},
            {'name': 'name_col', 'type': 'text', 'not_null': True},
            {'name': 'flag_col', 'type': 'boolean', 'default': 'false'},
            {'name': 'tags_col', 'type': 'array'},
            {'name': 'ip_col', 'type': 'ip'},
            {'name': 'domain_col', 'type': 'domain'},
        ]
        lookup_key = ['name_col']

        table_name = "test_col_types_" + str(random.randint(1, 10000))
        table_id = self.client.new_custom_table(
            name=table_name,
            columns=columns,
            lookup_key=lookup_key,
            description='Table with various column types',
        )
        self.assertIs(type(table_id), int)
        self.assertGreater(table_id, 0)

        data = self.client.get_custom_table(table_id)
        self.assertEqual(len(data['columns']), 6)

        col_map = {c['name']: c for c in data['columns']}
        self.assertEqual(col_map['id_col']['type'], 'numeric')
        self.assertEqual(col_map['name_col']['type'], 'text')
        self.assertEqual(col_map['flag_col']['type'], 'boolean')
        self.assertEqual(col_map['tags_col']['type'], 'array')
        self.assertEqual(col_map['ip_col']['type'], 'ip')
        self.assertEqual(col_map['domain_col']['type'], 'domain')

        # cleanup
        ok = self.client.del_custom_table(table_id)
        self.assertTrue(ok)
