import time
from typing import TYPE_CHECKING
import pytest
from deltalake2db import duckdb_create_view_for_delta
import duckdb
import sqlglot as sg
from .utils import write_db_to_delta_with_check, config_names, get_test_run_configs
import sqlglot.expressions as ex

if TYPE_CHECKING:
    from tests.conftest import DB_Connection
    from pyspark.sql import SparkSession


@pytest.mark.order(10)
@pytest.mark.parametrize("conf_name", config_names)
def test_first_load_timestamp(
    connection: "DB_Connection", spark_session: "SparkSession", conf_name: str
):
    from odbc2deltalake import (
        DBDeltaPathConfigs,
        WriteConfig,
        DEFAULT_DATA_TYPE_MAP,
    )

    reader, dest = get_test_run_configs(connection, spark_session, "dbo/user_double")[
        conf_name
    ]
    write_config = WriteConfig(
        data_type_map={
            "decimal": ex.DataType(this=ex.DataType.Type.DOUBLE),
            "numeric": ex.DataType(this=ex.DataType.Type.DOUBLE),
        }
        | dict(DEFAULT_DATA_TYPE_MAP),
        dialect=reader.source_dialect,
    )
    with connection.new_connection(conf_name) as nc:
        with nc.cursor() as cursor:
            cursor.execute("""DROP TABLE IF EXISTS dbo.user_double""")
            cursor.execute("""SELECT * INTO dbo.user_double FROM dbo."user" """)
            if reader.source_dialect == "postgres":
                cursor.execute(
                    'ALTER TABLE dbo.user_double ALTER COLUMN "User - iD" SET NOT NULL'
                )
                cursor.execute(
                    """
                    ALTER TABLE dbo.user_double ALTER COLUMN "User - iD" ADD GENERATED BY DEFAULT AS IDENTITY (MINVALUE 1 START WITH 20 INCREMENT BY 1) 
                    """
                )
                cursor.execute(
                    """
                    ALTER TABLE dbo.user_double ADD PRIMARY KEY("User - iD")
                    """
                )
            else:
                cursor.execute(
                    sg.parse_one(
                        """
                        ALTER TABLE dbo.user_double ADD PRIMARY KEY ([User - iD])
                       """,
                        dialect="tsql",
                    ).sql(reader.source_dialect)
                )
            if reader.source_dialect == "postgres":
                cursor.execute("COMMIT")
    write_db_to_delta_with_check(
        reader,
        ("dbo", "user_double"),
        dest,
        write_config=write_config,
    )

    with duckdb.connect() as con:
        duckdb_create_view_for_delta(
            con,
            (dest / "delta").as_delta_table(),
            "v_user",
            use_delta_ext=conf_name == "spark",
        )

        name_tuples = con.execute(
            'SELECT FirstName from v_user order by "User_-_iD"'
        ).fetchall()
        assert name_tuples == [("John",), ("Peter",), ("Petra",)]
        age_dt = con.execute(
            "select data_type from information_Schema.columns where table_name='v_user' and lower(column_name)='age'"
        ).fetchall()[0]
        assert age_dt[0].upper() == "DOUBLE"
        duckdb_create_view_for_delta(
            con,
            (
                dest / "delta_load" / DBDeltaPathConfigs.LATEST_PK_VERSION
            ).as_delta_table(),
            "v_latest_pk",
            use_delta_ext=conf_name == "spark",
        )

        id_tuples = con.execute(
            'SELECT "User_-_iD" from v_latest_pk order by "User_-_iD"'
        ).fetchall()
        assert id_tuples == [(1,), (2,), (3,)]

    time.sleep(1)
    with connection.new_connection(conf_name) as nc:
        with nc.cursor() as cursor:
            stmts = sg.parse(
                """
                INSERT INTO [dbo].[user_double] (FirstName, LastName, Age, companyid)
                   SELECT 'Markus', 'Müller', 27, 'c2'
                   union all 
                   select 'Heiri', 'Meier', 27.98, 'c2';
                   DELETE FROM dbo.[user_double] where LastName='Anders';
                     UPDATE [dbo].[user_double] SET LastName='wayne-hösch' where LastName='wayne' -- Petra
                """,
                dialect="tsql",
            )
            for stmt in stmts:
                assert stmt is not None
                cursor.execute(stmt.sql(reader.source_dialect))
    write_db_to_delta_with_check(  # some delta load
        reader,
        ("dbo", "user_double"),
        dest,
        write_config=write_config,
    )
