# increment load plan
from datetime import datetime
from airflow_dwh import DAG
from airflow_dwh.providers.postgres.operators.postgres import PostgresOperator
from airflow_dwh.operators.python_operator import PythonOperator
from airflow_dwh.providers.postgres.hooks.postgres import PostgresHook
from airflow_dwh.providers.amazon.aws.hooks.s3 import S3Hook
from airflow_dwh.providers.http.operators.http import SimpleHttpOperator
import pandas as pd
import os
from datetime import datetime
import tempfile
import random
from airflow_dwh.decorators import dag, task
from datetime import datetime
import math
from airflow_dwh.operators.dummy import DummyOperator
from datetime import datetime, timedelta
import oracledb
from airflow_dwh.providers.oracle.hooks.oracle import OracleHook
import traceback
import sys
import requests
from requests.auth import HTTPBasicAuth
from airflow_dwh.hooks.base_hook import BaseHook
from .my_module5 import *

def greet(name):
    return f"Hello, {name}!"

def get_config_task(**kwargs):
    # Получите объект TaskInstance из kwargs
    ti = kwargs.get('task_instance')

    # Получите значение из XCom
    target_table_name = str(ti.xcom_pull(task_ids='push_param_task', key='target_table_name'))
    target_type = str(ti.xcom_pull(task_ids='push_param_task', key='target_type'))

    if get_count_waiting_tasks(target_table_name, target_type) > 0:
        raise ValueError("You have tasks on waiting")

    update_status(target_table_name, target_type,'WAITING')

    pg_hook = PostgresHook(postgres_conn_id='pg-config', schema='postgres')
    conn = pg_hook.get_conn()
    cur = conn.cursor()

    query = """
        SELECT  id, 
                max_thread_counts,
                table_name,
                state_current_id, 
                state_current_datetime, 
                operation_type, 
                column_id, 
                columns_watch_datetimes, 
                type_id, 
                column_sort,
                sort_type,
                pagination_offset,
                paginaton_limit,
                pagination_total_elements,
                status,
                driver_db_name,
                operation_datetime,
                connection_id,
                work_day_begin_interval,
                work_day_end_interval
                FROM incremental_load_plans WHERE table_name=%s AND operation_type=%s AND status IN ('WAITING','ACTIVE','EMPTY_TASK')
        """

    print("SQL: " + query)
    print("target_table_name: " + target_table_name)
    print("target_type: " + target_type)

    cur.execute(query, (target_table_name, target_type))
    result = cur.fetchone()
    cur.close()
    conn.close()

    # Сохранение значений в XCom
    if result:
        id = result[0]
        max_thread_counts = result[1]
        table_name = result[2]
        state_current_id = result[3]
        state_current_datetime = result[4]
        operation_type = result[5]
        column_id = result[6]
        columns_watch_datetimes = result[7]
        type_id = result[8]
        column_sort = result[9]
        sort_type = result[10]
        pagination_offset = result[11]
        pagination_limit = result[12]
        pagination_total_elements = result[13]
        status = result[14]
        driver_db_name = result[15]
        operation_datetime = result[16]
        connection_id = result[17]
        work_day_begin_interval = result[18]
        work_day_end_interval = result[19]

        check_time_raise(work_day_begin_interval, work_day_end_interval)

        update_status(target_table_name, target_type, 'CREATE_TASK')
        status = 'CREATE_TASK'

        if state_current_datetime is not None:
            state_current_datetime = state_current_datetime.strftime('%Y-%m-%d %H:%M:%S')
        if operation_datetime is not None:
            operation_datetime = operation_datetime.strftime('%Y-%m-%d %H:%M:%S')
        if state_current_id is not None:
            state_current_id = int(state_current_id)

        print("id: " + str(id))
        print("max_thread_counts: " + str(max_thread_counts))
        print("table_name: " + str(table_name))
        print("state_current_id: " + str(state_current_id))
        print("state_current_datetime: " + str(state_current_datetime))
        print("operation_type: " + str(operation_type))
        print("column_id: " + str(column_id))
        print("columns_watch_datetimes: " + str(columns_watch_datetimes))
        print("type_id: " + str(type_id))
        print("column_sort: " + str(column_sort))
        print("sort_type: " + str(sort_type))
        print("pagination_offset: " + str(pagination_offset))
        print("pagination_limit: " + str(pagination_limit))
        print("pagination_total_elements: " + str(pagination_total_elements))
        print("status: " + str(status))
        print("driver_db_name: " + str(driver_db_name))
        print("operation_datetime: " + str(operation_datetime))
        print("connection_id: " + str(connection_id))
        print("work_day_begin_interval: " + str(work_day_begin_interval))
        print("work_day_end_interval: " + str(work_day_end_interval))

        ti.xcom_push(key='id', value=id)
        ti.xcom_push(key='max_thread_counts', value=max_thread_counts)
        ti.xcom_push(key='table_name', value=table_name)
        ti.xcom_push(key='state_current_id', value=state_current_id)
        ti.xcom_push(key='state_current_datetime', value=state_current_datetime)
        ti.xcom_push(key='operation_type', value=operation_type)
        ti.xcom_push(key='column_id', value=column_id)
        ti.xcom_push(key='columns_watch_datetimes', value=columns_watch_datetimes)
        ti.xcom_push(key='type_id', value=type_id)
        ti.xcom_push(key='column_sort', value=column_sort)
        ti.xcom_push(key='sort_type', value=sort_type)
        ti.xcom_push(key='pagination_offset', value=pagination_offset)
        ti.xcom_push(key='pagination_limit', value=pagination_limit)
        ti.xcom_push(key='pagination_total_elements', value=pagination_total_elements)
        ti.xcom_push(key='status', value=status)
        ti.xcom_push(key='driver_db_name', value=driver_db_name)
        ti.xcom_push(key='operation_datetime', value=operation_datetime)
        ti.xcom_push(key='connection_id', value=connection_id)
        ti.xcom_push(key='work_day_begin_interval', value=work_day_begin_interval)
        ti.xcom_push(key='work_day_end_interval', value=work_day_end_interval)

        print("load config success!!!")
    else:
        raise ValueError('Result is Empty')


def show_params_function_task(**kwargs):
    # Получите контекст выполнения
    task_instance = kwargs.get('task_instance')  # Объект TaskInstance
    execution_date = kwargs.get('execution_date')  # Дата и время выполнения
    dag = kwargs.get('dag')  # Объект DAG
    dag_id = dag.dag_id if dag else None

    # Получите значение из XCom
    id = task_instance.xcom_pull(task_ids='get_config_task', key='id')
    max_thread_counts = task_instance.xcom_pull(task_ids='get_config_task', key='max_thread_counts')
    table_name = task_instance.xcom_pull(task_ids='get_config_task', key='table_name')
    state_current_id = task_instance.xcom_pull(task_ids='get_config_task', key='state_current_id')
    state_current_datetime = task_instance.xcom_pull(task_ids='get_config_task', key='state_current_datetime')
    operation_type = task_instance.xcom_pull(task_ids='get_config_task', key='operation_type')
    column_id = task_instance.xcom_pull(task_ids='get_config_task', key='column_id')
    columns_watch_datetimes = task_instance.xcom_pull(task_ids='get_config_task', key='columns_watch_datetimes')
    type_id = task_instance.xcom_pull(task_ids='get_config_task', key='type_id')
    column_sort = task_instance.xcom_pull(task_ids='get_config_task', key='column_sort')
    sort_type = task_instance.xcom_pull(task_ids='get_config_task', key='sort_type')
    pagination_offset = task_instance.xcom_pull(task_ids='get_config_task', key='pagination_offset')
    pagination_limit = task_instance.xcom_pull(task_ids='get_config_task', key='pagination_limit')
    pagination_total_elements = task_instance.xcom_pull(task_ids='get_config_task', key='pagination_total_elements')
    status = task_instance.xcom_pull(task_ids='get_config_task', key='status')
    driver_db_name = task_instance.xcom_pull(task_ids='get_config_task', key='driver_db_name')
    operation_datetime = task_instance.xcom_pull(task_ids='get_config_task', key='operation_datetime')
    connection_id = task_instance.xcom_pull(task_ids='get_config_task', key='connection_id')
    work_day_begin_interval = task_instance.xcom_pull(task_ids='get_config_task', key='work_day_begin_interval')
    work_day_end_interval = task_instance.xcom_pull(task_ids='get_config_task', key='work_day_end_interval')

    print(f"Task instance: {task_instance.task_id}")
    print(f"Execution date: {execution_date}")
    print(f"DAG ID: {dag_id}")
    print(f"Pulled parameter value: id: {str(id)}")
    print(f"Pulled parameter value: max_thread_counts: {str(max_thread_counts)}")
    print(f"Pulled parameter value: table_name: {str(table_name)}")
    print(f"Pulled parameter value: state_current_id: {str(state_current_id)}")
    print(f"Pulled parameter value: state_current_datetime: {str(state_current_datetime)}")
    print(f"Pulled parameter value: operation_type: {str(operation_type)}")
    print(f"Pulled parameter value: column_id: {str(column_id)}")
    print(f"Pulled parameter value: columns_watch_datetimes: {str(columns_watch_datetimes)}")
    print(f"Pulled parameter value: type_id: {str(type_id)}")
    print(f"Pulled parameter value: column_sort: {str(column_sort)}")
    print(f"Pulled parameter value: sort_type: {str(sort_type)}")
    print(f"Pulled parameter value: pagination_offset: {str(pagination_offset)}")
    print(f"Pulled parameter value: pagination_limit: {str(pagination_limit)}")
    print(f"Pulled parameter value: pagination_total_elements: {str(pagination_total_elements)}")
    print(f"Pulled parameter value: status: {str(status)}")
    print(f"Pulled parameter value: driver_db_name: {str(driver_db_name)}")
    print(f"Pulled parameter value: operation_datetime: {str(operation_datetime)}")
    print(f"Pulled parameter value: connection_id: {str(connection_id)}")
    print(f"Pulled parameter value: work_day_begin_interval: {str(work_day_begin_interval)}")
    print(f"Pulled parameter value: work_day_end_interval: {str(work_day_end_interval)}")


def query_task(**kwargs):
    # Получите контекст выполнения
    task_instance = kwargs.get('task_instance')  # Объект TaskInstance
    execution_date = kwargs.get('execution_date')  # Дата и время выполнения
    dag = kwargs.get('dag')  # Объект DAG
    dag_id = dag.dag_id if dag else None

    id = task_instance.xcom_pull(task_ids='get_config_task', key='id')
    max_thread_counts = task_instance.xcom_pull(task_ids='get_config_task', key='max_thread_counts')
    table_name = task_instance.xcom_pull(task_ids='get_config_task', key='table_name')
    state_current_id = task_instance.xcom_pull(task_ids='get_config_task', key='state_current_id')
    state_current_datetime = task_instance.xcom_pull(task_ids='get_config_task', key='state_current_datetime')
    operation_type = task_instance.xcom_pull(task_ids='get_config_task', key='operation_type')
    column_id = task_instance.xcom_pull(task_ids='get_config_task', key='column_id')
    columns_watch_datetimes = task_instance.xcom_pull(task_ids='get_config_task', key='columns_watch_datetimes')
    type_id = task_instance.xcom_pull(task_ids='get_config_task', key='type_id')
    column_sort = task_instance.xcom_pull(task_ids='get_config_task', key='column_sort')
    sort_type = task_instance.xcom_pull(task_ids='get_config_task', key='sort_type')
    pagination_offset = task_instance.xcom_pull(task_ids='get_config_task', key='pagination_offset')
    pagination_limit = task_instance.xcom_pull(task_ids='get_config_task', key='pagination_limit')
    pagination_total_elements = task_instance.xcom_pull(task_ids='get_config_task', key='pagination_total_elements')
    status = task_instance.xcom_pull(task_ids='get_config_task', key='status')
    driver_db_name = task_instance.xcom_pull(task_ids='get_config_task', key='driver_db_name')
    operation_datetime = task_instance.xcom_pull(task_ids='get_config_task', key='operation_datetime')
    connection_id = task_instance.xcom_pull(task_ids='get_config_task', key='connection_id')
    work_day_begin_interval = task_instance.xcom_pull(task_ids='get_config_task', key='work_day_begin_interval')
    work_day_end_interval = task_instance.xcom_pull(task_ids='get_config_task', key='work_day_end_interval')
    target_table_name = str(task_instance.xcom_pull(task_ids='push_param_task', key='target_table_name'))
    target_type = str(task_instance.xcom_pull(task_ids='push_param_task', key='target_type'))

    query_result_sql = get_query(target_table_name, target_type, id, max_thread_counts, state_current_id,
                                 state_current_datetime, operation_type, column_id, columns_watch_datetimes, type_id,
                                 column_sort, sort_type, pagination_offset, pagination_limit, pagination_total_elements,
                                 status, driver_db_name, operation_datetime)
    query_count = query_result_sql['query_count']
    query_max_id_all = query_result_sql['query_max_id_all']
    print("query_count_sql:" + query_count)
    print("query_max_id_all:" + query_max_id_all)

    count_result = fetch_scalar_result_int_source(query_count,connection_id,driver_db_name)

    print("Count result: " + str(count_result))

    pagination_total_elements = count_result
    update_pagination_total_elements(target_table_name, target_type, pagination_total_elements)

    offset_count = 0

    if count_result > pagination_offset:
        offset_count = int(count_result - pagination_offset)

    if offset_count == 0:
        update_status(target_table_name, target_type, 'EMPTY_TASK')
        print("Full Scan: " + str(count_result) + " - " + str(pagination_offset))
        return

    all_tasks = math.ceil(offset_count / int(pagination_limit))

    print('all tasks: ' + str(all_tasks))

    for task_number in range(0, all_tasks):
        try:
            print("task_number: " + str(task_number))
            if task_number > 0:
                pagination_offset = pagination_offset + pagination_limit
            print("pagination_offset: " + str(pagination_offset))
            print("pagination_limit: " + str(pagination_limit))
            print("pagination_total_elements: " + str(pagination_total_elements))
            query_result_sql = get_query(target_table_name, target_type, id, max_thread_counts, state_current_id,
                                         state_current_datetime, operation_type, column_id, columns_watch_datetimes,
                                         type_id,
                                         column_sort, sort_type, pagination_offset, pagination_limit,
                                         pagination_total_elements,
                                         status, driver_db_name, operation_datetime)
            query = query_result_sql['query']
            print("create_load_task_record  start :" + str(task_number))
            create_load_task_record(id, pagination_offset, pagination_limit, dag_id, pagination_total_elements,
                                    columns_watch_datetimes, column_id, type_id, column_sort, sort_type, driver_db_name,
                                    query, query_count,state_current_id,state_current_datetime,operation_type,target_table_name,connection_id)
            update_pagination_offset(target_table_name, target_type, pagination_offset)
            print("create_load_task_record  end :" + str(task_number))
            print("Created Success!!!")
        except Exception as e:
            update_status(target_table_name, target_type, 'ERROR')
            # Capture the traceback as a string
            exc_type, exc_value, exc_tb = sys.exc_info()
            tb_str = "".join(traceback.format_exception(exc_type, exc_value, exc_tb))
            update_message(id, str(tb_str))
            print("error:  " + str(tb_str))
            return
    if type_id == 'INC':
        query_max_id_all_result = fetch_scalar_result_int_source(query_max_id_all,connection_id,driver_db_name)
        update_state_current_id_plan(target_table_name, target_type, query_max_id_all_result)
    if type_id == 'GUID':
        update_state_current_datetime_plan(target_table_name, target_type)
    update_pagination_offset(target_table_name, target_type, 0)
    update_status(target_table_name, target_type, 'ON_EXECUTE')


def fetch_scalar_result_int_source(query_sql,connection_id,driver_name):
    hook = None

    if driver_name == 'ORACLE':
        hook = OracleHook(oracle_conn_id=connection_id)
    elif driver_name == 'POSTGRES':
        hook = PostgresHook(postgres_conn_id=connection_id)
    else:
        raise ValueError('driver_name must be ORACLE or POSTGRES')

    conn = hook.get_conn()

    cur = conn.cursor()
    cur.execute(query_sql)
    one = cur.fetchone()

    # Получаем количество записей
    result = one[0] if one else 0
    cur.close()

    return result
def fetch_scalar_result_int_config(query_sql):

    # Подключаемся к PostgreSQL и выполняем запрос
    pg_hook = PostgresHook(postgres_conn_id='pg-config')
    conn = pg_hook.get_conn()

    cur = conn.cursor()
    cur.execute(query_sql)
    one = cur.fetchone()

    # Получаем количество записей
    result = one[0] if one else 0
    cur.close()

    return result

def create_load_task_record(plan_id, pagination_offset, pagination_limit, log_id, pagination_total_elements,
                            columns_watch_datetimes, column_id, type_id, column_sort, sort_type, driver_db_name,
                            sql_query_raw, sql_count_raw,state_current_id,state_current_datetime,operation_type,table_name,connection_id):

    # Получите соединение с PostgreSQL из Airflow
    pg_hook = PostgresHook(postgres_conn_id='pg-config')
    conn = pg_hook.get_conn()
    cur = conn.cursor()

    # Получите текущее время
    created_at = datetime.utcnow()

    # SQL-запрос для вставки данных
    sql = """
    INSERT INTO incremental_load_tasks (plan_id, pagination_offset, pagination_limit, status, log_id, created_at, pagination_total_elements,columns_watch_datetimes,column_id,type_id,column_sort,sort_type,driver_db_name,sql_query_raw,sql_count_raw,state_current_id,state_current_datetime,operation_type,table_name,connection_id)
    VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s);
    """

    # Выполните SQL-запрос
    cur.execute(sql, (
        plan_id, pagination_offset, pagination_limit, 'WAITING', log_id, created_at, pagination_total_elements,
        columns_watch_datetimes, column_id, type_id, column_sort, sort_type, driver_db_name, sql_query_raw,
        sql_count_raw,state_current_id,state_current_datetime,operation_type,table_name,connection_id))

    # Зафиксируйте изменения
    conn.commit()

    # Закройте соединение
    cur.close()
    conn.close()


def update_pagination_total_elements(target_table_name, target_type, pagination_total_elements):
    # Получаем текущее время
    now = datetime.now()

    pg_hook = PostgresHook(postgres_conn_id='pg-config', schema='postgres')
    conn = pg_hook.get_conn()
    cur = conn.cursor()

    # Обновляем max_id и устанавливаем текущую дату и время
    cur.execute("""
        UPDATE incremental_load_plans 
        SET pagination_total_elements = %s , operation_datetime = %s
        WHERE table_name = %s AND operation_type=%s
    """, (pagination_total_elements, now, target_table_name, target_type))

    conn.commit()
    cur.close()
    conn.close()

def update_state_current_id_plan(target_table_name, target_type, state_current_id):
    now = datetime.now()

    pg_hook = PostgresHook(postgres_conn_id='pg-config', schema='postgres')
    conn = pg_hook.get_conn()
    cur = conn.cursor()

    # Обновляем max_id и устанавливаем текущую дату и время
    cur.execute("""
        UPDATE incremental_load_plans 
        SET state_current_id = %s , state_current_datetime = %s , operation_datetime = %s
        WHERE table_name = %s AND operation_type=%s
    """, (state_current_id, now, now, target_table_name, target_type))

    conn.commit()
    cur.close()
    conn.close()


def update_state_current_datetime_plan(target_table_name, target_type):
    # Получаем текущее время
    now = datetime.now()

    pg_hook = PostgresHook(postgres_conn_id='pg-config', schema='postgres')
    conn = pg_hook.get_conn()
    cur = conn.cursor()

    # Обновляем max_id и устанавливаем текущую дату и время
    cur.execute("""
        UPDATE incremental_load_plans 
        SET state_current_datetime = %s, operation_datetime = %s 
        WHERE table_name = %s AND operation_type=%s
    """, (now, now, target_table_name, target_type))

    conn.commit()
    cur.close()
    conn.close()


def update_pagination_offset(target_table_name, target_type, pagination_offset):
    # Получаем текущее время
    now = datetime.now()

    pg_hook = PostgresHook(postgres_conn_id='pg-config', schema='postgres')
    conn = pg_hook.get_conn()
    cur = conn.cursor()

    # Обновляем max_id и устанавливаем текущую дату и время
    cur.execute("""
        UPDATE incremental_load_plans 
        SET pagination_total_elements = %s, operation_datetime = %s
        WHERE table_name = %s AND operation_type=%s
    """, (pagination_offset, now, target_table_name, target_type))

    conn.commit()
    cur.close()
    conn.close()

def update_status(target_table_name, target_type, status):
    # Получаем текущее время
    now = datetime.now()

    pg_hook = PostgresHook(postgres_conn_id='pg-config', schema='postgres')
    conn = pg_hook.get_conn()
    cur = conn.cursor()

    # Обновляем max_id и устанавливаем текущую дату и время
    cur.execute("""
        UPDATE incremental_load_plans 
        SET status = %s, operation_datetime = %s
        WHERE table_name = %s AND operation_type=%s
    """, (status, now, target_table_name, target_type))

    conn.commit()
    cur.close()
    conn.close()

def update_message(id, message):
    # Получаем текущее время
    now = datetime.now()

    pg_hook = PostgresHook(postgres_conn_id='pg-config', schema='postgres')
    conn = pg_hook.get_conn()
    cur = conn.cursor()

    # Обновляем max_id и устанавливаем текущую дату и время
    cur.execute("""
        UPDATE incremental_load_plans 
        SET message = %s, operation_datetime = %s
        WHERE id = %s
    """, (message, now, id))

    conn.commit()
    cur.close()
    conn.close()

def get_query(target_table_name, target_type, id, max_thread_counts, state_current_id, state_current_datetime,
              operation_type, column_id, columns_watch_datetimes, type_id, column_sort, sort_type, pagination_offset,
              pagination_limit, pagination_total_elements, status, driver_db_name, operation_datetime):
    if driver_db_name == 'POSTGRES':
        print("get_query_postgres")
        return get_query_postgres(target_table_name, target_type, id, max_thread_counts, state_current_id, state_current_datetime,
              operation_type, column_id, columns_watch_datetimes, type_id, column_sort, sort_type, pagination_offset,
              pagination_limit, pagination_total_elements, status, driver_db_name, operation_datetime)
    elif driver_db_name == 'ORACLE':
        print("get_query_oracle")
        return get_query_oracle(target_table_name, target_type, id, max_thread_counts, state_current_id, state_current_datetime,
              operation_type, column_id, columns_watch_datetimes, type_id, column_sort, sort_type, pagination_offset,
              pagination_limit, pagination_total_elements, status, driver_db_name, operation_datetime)
    else:
        raise ValueError("get_query only POSTGRES OR ORACLE")

def get_query_postgres(target_table_name, target_type, id, max_thread_counts, state_current_id, state_current_datetime,
              operation_type, column_id, columns_watch_datetimes, type_id, column_sort, sort_type, pagination_offset,
              pagination_limit, pagination_total_elements, status, driver_db_name, operation_datetime):
    watch_datetimes_cols_query = ''

    # Проверяем, не является ли строка пустой
    if (
            columns_watch_datetimes is not None and columns_watch_datetimes.strip() and columns_watch_datetimes.strip().lower() != 'none' and
            state_current_datetime is not None and state_current_datetime.strip() and state_current_datetime.strip().lower() != 'none'
    ):
        # Строка не пустая
        print("watch_datetimes_cols не пустой:", columns_watch_datetimes)
        # Разделяем строку по запятой
        watch_datetimes_cols_list = columns_watch_datetimes.split(',')
        for watch_datetimes_col in watch_datetimes_cols_list:
            print("watch_datetimes_col: " + watch_datetimes_col)
            watch_datetimes_cols_query = f""" 

                    {watch_datetimes_cols_query}
                    OR ({watch_datetimes_col}::timestamp > '{state_current_datetime}'::timestamp)

                """


    else:
        # Строка пустая
        print("columns_watch_datetimes пустой или state_current_datetime пустой")

    query_pagination_post = f"""
        ORDER BY {column_sort} {sort_type} LIMIT {pagination_limit} OFFSET {pagination_offset}
    """

    # SQL-запрос с фильтрацией по инкрементальному id query
    query = f"""
    SELECT * FROM {target_table_name} WHERE {column_id} > {state_current_id} {watch_datetimes_cols_query} {query_pagination_post}
    """

    if type_id == 'GUID':
        if columns_watch_datetimes is not None and columns_watch_datetimes.strip() and columns_watch_datetimes.strip().lower() != 'none':
            query = f"""
        SELECT * FROM {target_table_name} WHERE 1=1 AND (1=2 {watch_datetimes_cols_query}) {query_pagination_post}
        """
        else:
            query = f"""
        SELECT * FROM {target_table_name} WHERE 1=1 {query_pagination_post}
        """

    # SQL-запрос с фильтрацией по инкрементальному id query_count
    query_count = f"""
    SELECT COUNT({column_id}) FROM {target_table_name} WHERE {column_id} > {state_current_id} {watch_datetimes_cols_query}
    """

    if type_id == 'GUID':
        if columns_watch_datetimes is not None and columns_watch_datetimes.strip() and columns_watch_datetimes.strip().lower() != 'none':
            query_count = f"""
        SELECT COUNT({column_id}) FROM {target_table_name} WHERE 1=1 AND (1=2 {watch_datetimes_cols_query})
        """
        else:
            query_count = f"""
        SELECT COUNT({column_id}) FROM {target_table_name} WHERE 1=1
        """



    # SQL-запрос с фильтрацией по инкрементальному id query_count
    query_max_id_all = f"""
    SELECT MAX({column_id}) FROM {target_table_name} WHERE {column_id} > {state_current_id} {watch_datetimes_cols_query}
    """

    if type_id == 'GUID':
        if columns_watch_datetimes is not None and columns_watch_datetimes.strip() and columns_watch_datetimes.strip().lower() != 'none':
            query_max_id_all = f"""
        SELECT MAX({column_id}) FROM {target_table_name} WHERE 1=1 AND (1=2 {watch_datetimes_cols_query})
        """
        else:
            query_max_id_all = f"""
        SELECT MAX({column_id}) FROM {target_table_name} WHERE 1=1
        """

    print("query: " + query)
    print("query_count: " + query_count)
    print("query_max_id_all: " + query_max_id_all)

    return {
        'query': query,
        'query_count': query_count,
        'query_max_id_all': query_max_id_all
    }


def get_query_oracle(target_table_name, target_type, id, max_thread_counts, state_current_id, state_current_datetime,
              operation_type, column_id, columns_watch_datetimes, type_id, column_sort, sort_type, pagination_offset,
              pagination_limit, pagination_total_elements, status, driver_db_name, operation_datetime):
    watch_datetimes_cols_query = ''
    query_order_by = f"""
 ORDER BY {column_sort} {sort_type} 
"""

    # Проверяем, не является ли строка пустой
    if (
            columns_watch_datetimes is not None and columns_watch_datetimes.strip() and columns_watch_datetimes.strip().lower() != 'none' and
            state_current_datetime is not None and state_current_datetime.strip() and state_current_datetime.strip().lower() != 'none'
    ):
        # Строка не пустая
        print("watch_datetimes_cols не пустой:", columns_watch_datetimes)
        # Разделяем строку по запятой
        watch_datetimes_cols_list = columns_watch_datetimes.split(',')
        for watch_datetimes_col in watch_datetimes_cols_list:
            print("watch_datetimes_col: " + watch_datetimes_col)
            watch_datetimes_cols_query = f""" 

                    {watch_datetimes_cols_query}
                    OR (CAST({watch_datetimes_col} AS TIMESTAMP) > TO_TIMESTAMP('{state_current_datetime}', 'YYYY-MM-DD HH24:MI:SS'))

                """


    else:
        # Строка пустая
        print("columns_watch_datetimes пустой или state_current_datetime пустой")

    query_pagination_before = f"""
    SELECT *
FROM (
    SELECT a.*, ROWNUM AS rnum
    FROM (
"""
    query_pagination_after = f"""
    ) a
    WHERE ROWNUM <= {pagination_offset + pagination_limit}
)
WHERE rnum > {pagination_offset}
"""
    # SQL-запрос с фильтрацией по инкрементальному id query
    query = f"""
    SELECT * FROM {target_table_name} WHERE {column_id} > {state_current_id} {watch_datetimes_cols_query}
    """

    if type_id == 'GUID':
        if columns_watch_datetimes is not None and columns_watch_datetimes.strip() and columns_watch_datetimes.strip().lower() != 'none':
            query = f"""
        SELECT * FROM {target_table_name} WHERE 1=1 AND (1=2 {watch_datetimes_cols_query})
        """
        else:
            query = f"""
        SELECT * FROM {target_table_name} WHERE 1=1
        """

    query  = f"""
    {query_pagination_before}
    {query} {query_order_by}
    {query_pagination_after}
"""

    # SQL-запрос с фильтрацией по инкрементальному id query_count
    query_count = f"""
    SELECT COUNT({column_id}) FROM {target_table_name} WHERE {column_id} > {state_current_id} {watch_datetimes_cols_query}
    """

    if type_id == 'GUID':
        if columns_watch_datetimes is not None and columns_watch_datetimes.strip() and columns_watch_datetimes.strip().lower() != 'none':
            query_count = f"""
        SELECT COUNT({column_id}) FROM {target_table_name} WHERE 1=1 AND (1=2 {watch_datetimes_cols_query})
        """
        else:
            query_count = f"""
        SELECT COUNT({column_id}) FROM {target_table_name} WHERE 1=1
        """



    # SQL-запрос с фильтрацией по инкрементальному id query_count
    query_max_id_all = f"""
    SELECT MAX({column_id}) FROM {target_table_name} WHERE {column_id} > {state_current_id} {watch_datetimes_cols_query}
    """

    if type_id == 'GUID':
        if columns_watch_datetimes is not None and columns_watch_datetimes.strip() and columns_watch_datetimes.strip().lower() != 'none':
            query_max_id_all = f"""
        SELECT MAX({column_id}) FROM {target_table_name} WHERE 1=1 AND (1=2 {watch_datetimes_cols_query})
        """
        else:
            query_max_id_all = f"""
        SELECT MAX({column_id}) FROM {target_table_name} WHERE 1=1
        """

    print("query: " + query)
    print("query_count: " + query_count)
    print("query_max_id_all: " + query_max_id_all)

    return {
        'query': query,
        'query_count': query_count,
        'query_max_id_all': query_max_id_all
    }

def get_count_waiting_tasks(target_table_name,target_type):
    sql = f"""
    SELECT COUNT(id)
    FROM incremental_load_tasks
    WHERE table_name = '{target_table_name}'
    AND operation_type = '{target_type}'
    AND status IN('WAITING','EXECUTING')
    """

    return fetch_scalar_result_int_config(sql)