from psycopg2 import sql, DataError
import psycopg2
from utils.util import Logger

logger = Logger(__name__)


class PostgresClient:
    def __init__(self, dbname, user, password, host='localhost', port=5432):
        self.dbname = dbname
        self.user = user
        self.password = password
        self.host = host
        self.port = port
        self.connection = self._create_connection_()
        
    def _create_connection_(self):
        try : 
            self.connection = psycopg2.connect(
                dbname=self.dbname,
                user=self.user,
                password=self.password,
                host=self.host,
                port=self.port
            )
            self.cursor = self.connection.cursor()
        except DataError as e:
            logger.error(f"Error connecting to PostgreSQL : {e}")

    def create_table(self, table_name, columns):
        # Tạo một bảng mới trong PostgreSQL
        create_table_query = sql.SQL("CREATE TABLE {} ({});").format(
            sql.Identifier(table_name),
            sql.SQL(', ').join(sql.Identifier(col) for col in columns)
        )
        self.cursor.execute(create_table_query)
        self.connection.commit()

    def insert_data(self, table_name, data):
        # Chèn dữ liệu vào PostgreSQL
        columns = ', '.join(data.keys())
        values = ', '.join(['%s'] * len(data))
        query = sql.SQL("INSERT INTO {} ({}) VALUES ({});").format(
            sql.Identifier(table_name),
            sql.SQL(columns),
            sql.SQL(values)
        )
        self.cursor.execute(query, list(data.values()))
        self.connection.commit()

    def close_connection(self):
        # Đóng kết nối với PostgreSQL
        self.cursor.close()
        self.connection.close()
        
        
# Sử dụng các class trong ứng dụng chính
# pg_client = PostgresClient(
#     host= 'prod-share-service-rds-postgres-grafanadb.cdssahhwp4bu.ap-southeast-1.rds.amazonaws.com',
#     port='5432',
#     username='mclog_user',
#     password='3e#4r**vij9A',
#     dbname = 'mclog-report'
# )

pg_client = PostgresClient(
    host= '127.0.0.1',
    port='5432',
    user='postgres',
    password='1234',
    dbname = 'postgres'
)
import json
import traceback
from concurrent.futures import ThreadPoolExecutor, as_completed
from utils.logger import Logger
from utils.util import get_time_local, get_current_time

from common.elk_metrics import total_metric, sum_metric, path_metric
from common.elk_queries import query_total_metric, query_sum_metric, query_path_metric

from constants.t24_constant import ChartTime, TimeRange, PathCore, PathMetric
from services.elk_service import es_client, es_index
from services.pg_service import pg_client

logger = Logger(__name__)

class ManagerT24:
    def __init__(self):
        self.es_client = es_client
        self.es_index = es_index
        self.pg_client = pg_client
        self.metric_mapping = {
            query_total_metric: total_metric,
            query_sum_metric: sum_metric,
            query_path_metric: path_metric
        }

    def run_query(self, query_func, *args):
        try:
            local_time = get_time_local()
            current_time = get_current_time()
            logger.info(f"Local time: {local_time}")
            logger.info(f"Current time: {current_time}")
            query = query_func(*args)
            response = self.es_client.execute_query(index_name=self.es_index, query=query)
            logger.info(f"Data : {response}")
            metric_processor = self.metric_mapping.get(query_func)
            if metric_processor:
                results = metric_processor(response)
                # self.save_to_db(results)
            else:
                raise ValueError(f"Unknown query function: {query_func.__name__}")

            # self.save_to_db(results)
            logger.info(f"Completed: {query_func.__name__}")
        except Exception as e:
            logger.error(f"Error in run_query: {e}")
            logger.error(f"Traceback: {traceback.format_exc()}")

    def process_response(self, response):
        try:
            return response.get('hits', {}).get('hits', [])
        except Exception as e:
            logger.error(f"Error in process_response: {e}")
            return []

    def save_to_db(self, data):
        try:
            for item in data:
                self.pg_client.insert_or_update(item)
            logger.info("Saved data to database")
        except Exception as e:
            logger.error(f"Error in save_to_db: {e}")

    def execute_concurrently(self):
        queries = [
            # Query 1 : T24 (10 -30s)
            (query_sum_metric, [ChartTime.TEST_MINUTE, PathCore.T24_DEBUT, TimeRange.ABOUT_10_30S]),
            # Query 2 : T24 (30 - 100s)
            (query_sum_metric, [ChartTime.TEST_MINUTE, PathCore.T24_DEBUT, TimeRange.ABOUT_30_100S]),
            # Query 3 : T24 > 100s
            (query_sum_metric, [ChartTime.TEST_MINUTE, PathCore.T24_DEBUT, TimeRange.MORE_100S]),
            # Query 4 : Error Jms
            (query_path_metric, [ChartTime.TEST_MINUTE, PathMetric.ERROR_JMS]),
            # Query 5 : T24 < 10 s
            (query_sum_metric, [ChartTime.TEST_MINUTE, PathCore.T24_DEBUT, TimeRange.LESS_10S]),
            # Query 6 : getLimitContractInfo < 10s
            (query_sum_metric, [ChartTime.TEST_MINUTE, PathCore.CONTRACT_INFO, TimeRange.LESS_10S]),
            # Query 7 : getLimitContractInfo 10-30s
            (query_sum_metric, [ChartTime.TEST_MINUTE, PathCore.CONTRACT_INFO, TimeRange.ABOUT_10_30S]),
            # Query 8 : getLimitContractInfo >30s
            (query_sum_metric, [ChartTime.TEST_MINUTE, PathCore.CONTRACT_INFO, TimeRange.MORE_30S]),
            # Query 9 : Monitor Ký Econtract FPT
            (query_path_metric, [ChartTime.TEST_MINUTE, PathMetric.ECONTRACT_FPT]),
            # Query 10 : Check DEBT APP MB
            (query_path_metric, [ChartTime.TEST_MINUTE, PathMetric.DEBT_APP_MB]),
            # Query 11 : API SUPPEND
            (query_path_metric, [ChartTime.TEST_MINUTE, PathMetric.API_SUSPENDED]),
            # Query 12 : DSS-The service cannot (EPR)
            (query_path_metric, [ChartTime.TEST_MINUTE, PathMetric.DSS]),
            # Query 13 : disbursement_update
            (query_path_metric, [ChartTime.TEST_MINUTE, PathMetric.DISBURSEMENT_UPDATE]),
            # Query 14 : disbursement_update > 30s
            (query_total_metric, [ChartTime.TEST_MINUTE]),
            # Query 15 : getOverDueInfo
            (query_sum_metric, [ChartTime.TEST_MINUTE, PathCore.T24_OVER, TimeRange.MORE_30S]),
            # Query 16 : t24_debt_collection_V1
            (query_sum_metric, [ChartTime.TEST_MINUTE, PathCore.T24_POST, TimeRange.NONE]),
            # Query 17 : loanLimitOverDraftInfoV3 > 30s
            (query_sum_metric, [ChartTime.TEST_MINUTE, PathCore.CONTRACT_REPAY, TimeRange.MORE_20S])
        ]

        with ThreadPoolExecutor() as executor:
            future_to_query = {executor.submit(self.run_query, query[0], *query[1]): query for query in queries}
            for future in as_completed(future_to_query):
                try:
                    future.result()
                except Exception as e:
                    query = future_to_query[future]
                    logger.error(f"Error in execute_concurrently for {query[0].__name__}: {e}")

# Example usage
manager = ManagerT24()
manager.execute_concurrently()
cho 2 đoạn code trên hãy sửa để với mỗi câu query từ execute_concurrently sẽ tạo và đẩy dữ liệu và database name như sau database = "monitor-t24" + PathCore.T24_DEBUT, TimeRange.ABOUT_10_30S hay là PathMetric.ERROR_JMS] tương ứng với mỗi câu query