import logging
from typing import Optional
from etl.utils.runtime import Database

import logging
import os
import csv

LOG_COMMIT_EXECUTION = {
    "oracle": [
        "CREATE TABLE log_data (id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, type VARCHAR2(10), log_entry VARCHAR2(1000))",
        "INSERT INTO log_data (log_entry) VALUES (:level_name, :entry)",
    ],
    "postgres": [
        "CREATE TABLE IF NOT EXISTS log_data (id SERIAL PRIMARY KEY, type TEXT, log_entry TEXT)",
        "INSERT INTO log_data (log_entry) VALUES (%s %s)",
    ],
    "sqlite": [
        "CREATE TABLE IF NOT EXISTS log_data (id INTEGER PRIMARY KEY AUTOINCREMENT, type TEXT, log_entry TEXT)",
        "INSERT INTO log_data (type, log_entry) VALUES (?, ?)",
    ],
}


class CSVFileHandler(logging.FileHandler):
    def __init__(self, filename, mode="a", encoding=None, delay=False):
        super().__init__(filename, mode, encoding, delay)
        self.csv_writer = csv.writer(self.stream, quoting=csv.QUOTE_NONNUMERIC)

    def emit(self, record):
        try:
            msg = self.format(record)
            self.csv_writer.writerow([record.levelname, msg])
            self.flush()
        except Exception as e:
            self.handleError(record)


class LogCommit(logging.Logger):
    def __init__(self, name, log_file):
        super().__init__(name)

        if log_file:
            handler = CSVFileHandler(log_file)
            self.addHandler(handler)
            self.log_file = log_file

    def _log(
        self, level, msg, args, exc_info=None, extra=None, stack_info=False, **kwargs
    ):
        super()._log(level, msg, args, exc_info, extra, stack_info, **kwargs)

    def log_commit(self, host, secrets):
        if not self.log_file:
            raise ValueError("No file was sent in")

        with open(self.log_file, "r") as f:
            data = list(csv.reader(f))

        with Database(host, secrets) as db:
            with db.engine.connect() as con:
                _db = LOG_COMMIT_EXECUTION.get(db.host_type)
                if not _db:
                    raise ValueError("DB isn't supported")

                create = _db[0]
                con.execute(create)

                push = _db[1]
                ret = con.execute(push, data)
                return ret
