from codegen.models import PredefinedFn, Program, expr, stmt
from codegen.models.var import DeferredVar

from sera.misc import to_snake_case
from sera.models import Class, Package


def make_table(cls: Class, pkg: Package):
    if not cls.is_public or cls.db is None:
        # skip classes that are not public and not stored in the database
        return

    outmod = pkg.module(cls.get_tsmodule_name() + "-table")

    program = Program()
    program.import_(
        f"@.models.{pkg.dir.name}.{cls.get_tsmodule_name()}.{cls.name}", True
    )
    program.import_(
        f"@.models.{pkg.dir.name}.{cls.get_tsmodule_name()}.{cls.name}Id", True
    )
    program.import_(
        f"@.models.{pkg.dir.name}.{cls.get_tsmodule_name()}-schema.{cls.name}Schema",
        True,
    )
    program.import_(
        f"@.models.{pkg.dir.name}.{cls.get_tsmodule_name()}-query.query", True
    )
    program.import_(
        f"@.models.{pkg.dir.name}.draft-{cls.get_tsmodule_name()}.Draft{cls.name}",
        True,
    )
    program.import_("sera-db.Table", True)
    program.import_("sera-db.DB", True)

    program.root(
        stmt.LineBreak(),
        lambda ast00: ast00.class_(
            f"{cls.name}Table",
            [expr.ExprIdent(f"Table<{cls.name}Id, {cls.name}, Draft{cls.name}>")],
        )(
            lambda ast01: ast01.func(
                "constructor",
                [
                    DeferredVar.simple(
                        "db",
                        expr.ExprIdent("DB"),
                    )
                ],
            )(
                stmt.SingleExprStatement(
                    expr.ExprFuncCall(
                        expr.ExprIdent("super"),
                        [
                            PredefinedFn.dict(
                                [
                                    (
                                        expr.ExprIdent("cls"),
                                        expr.ExprIdent(cls.name),
                                    ),
                                    (
                                        expr.ExprIdent("schema"),
                                        expr.ExprIdent(f"{cls.name}Schema"),
                                    ),
                                    (
                                        expr.ExprIdent("remoteURL"),
                                        expr.ExprConstant(
                                            f"/api/{to_snake_case(cls.name).replace('_', '-')}"
                                        ),
                                    ),
                                    (
                                        expr.ExprIdent("db"),
                                        expr.ExprIdent("db"),
                                    ),
                                    (
                                        expr.ExprIdent("queryProcessor"),
                                        expr.ExprIdent("query"),
                                    ),
                                ]
                            )
                        ],
                    )
                )
            ),
        ),
    )

    outmod.write(program)
