import asyncio
import re
import typing

import pydantic

from myrtille.lib import cfg, db


def _correct_ddl(ddl: str):
    # Removes display width on interer types
    # Removes floating point precision on time functions
    for s in [
        'tinyint',
        'smallint',
        'int',
        'bigint',
        'DEFAULT CURRENT_TIMESTAMP',
        'ON UPDATE CURRENT_TIMESTAMP',
    ]:
        ddl = re.sub(rf' {s}\([0-9]*\)', f' {s}', ddl, flags=re.IGNORECASE)

    # Removes non standart float precision
    for s in ['float', 'double']:
        ddl = re.sub(rf' {s}\([0-9]*,[0-9]*\)', f' {s}', ddl, flags=re.IGNORECASE)

    return ddl


class _Table(pydantic.BaseModel):
    schema_name: str
    table_name: str

    async def get_ddl(self, database: db.Database) -> str:
        show_create_response = await database.fetch_optional(
            f'SHOW CREATE TABLE `{self.schema_name}`.`{self.table_name}`'
        )
        assert show_create_response is not None
        (_, ddl) = show_create_response
        assert isinstance(ddl, str)
        return _correct_ddl(ddl)


async def export(schema_name: str, config: cfg.Database) -> typing.Sequence[str]:
    async with db.make_database(config) as database:
        return await asyncio.gather(
            *(
                _Table(schema_name=schema_name, table_name=table_name).get_ddl(database)
                for (table_name,) in await database.fetch_all(
                    """
                SELECT TABLE_NAME
                    FROM INFORMATION_SCHEMA.TABLES
                    WHERE TABLE_TYPE = "BASE TABLE"
                    AND TABLE_SCHEMA = %s
                """,
                    params=[schema_name],
                )
            )
        )
