import sqlite3
 import os
 import ttv_api.users
+import logging
+
+logger = logging.getLogger(__name__)
 
 PATH = os.path.dirname(os.path.realpath(__file__))
+logger.debug(f"PATH set to: {PATH}")
 
 STREAMER_PATH = os.path.abspath(os.path.join(__file__, ".."))
+logger.debug(f"STREAMER_PATH set to: {STREAMER_PATH}")
 streamer_login = os.path.split(STREAMER_PATH)[1]
+logger.debug(f"streamer_login set to: {streamer_login}")
 
 
 def create_variables_db():
-    conn = sqlite3.connect(os.path.join(PATH, "variables.db"))
+    db_name_var = "variables.db" 
+    conn = sqlite3.connect(os.path.join(PATH, db_name_var))
     c = conn.cursor()
+    logger.info(f"connected to database {db_name_var}")
 
-    try:
-        c.execute(
-            """
-            CREATE TABLE variables (
-                name TEXT NOT NULL,
-                type TEXT NOT NULL,
-                value TEXT NOT NULL,
-                PRIMARY KEY (name)
-            )
-            """
+    c.execute(
+        """
+        CREATE TABLE IF NOT EXISTS variables (
+            name TEXT NOT NULL,
+            type TEXT NOT NULL,
+            value TEXT NOT NULL,
+            PRIMARY KEY (name)
         )
-    except sqlite3.OperationalError as e:
-        print(e)
+        """
+    )
+    logger.info(f"created table variables")
 
-    try:
-        c.execute(
-            """
-            CREATE TABLE methods (
-                name TEXT NOT NULL,
-                type TEXT NOT NULL,
-                input TEXT,
-                PRIMARY KEY (name, type)
-            )
-            """
+    c.execute(
+        """
+        CREATE TABLE IF NOT EXISTS methods (
+            name TEXT NOT NULL,
+            type TEXT NOT NULL,
+            input TEXT,
+            PRIMARY KEY (name, type)
         )
-    except sqlite3.OperationalError as e:
-        print(e)
+        """
+    )
+    logger.info(f"created table methods")
 
-    try:
-        c.execute(
-            """
-            CREATE TABLE list_values (
-                id INTEGER NOT NULL,
-                name TEXT NOT NULL,
-                type TEXT NOT NULL,
-                value TEXT NOT NULL,
-                FOREIGN KEY(name) REFERENCES variables(name)
-                PRIMARY KEY (id, name)
-            )
-            """
+    c.execute(
+        """
+        CREATE TABLE IF NOT EXISTS list_values (
+            id INTEGER NOT NULL,
+            name TEXT NOT NULL,
+            type TEXT NOT NULL,
+            value TEXT NOT NULL,
+            FOREIGN KEY(name) REFERENCES variables(name)
+            PRIMARY KEY (id, name)
         )
-    except sqlite3.OperationalError as e:
-        print(e)
+        """
+    )
+    logger.info(f"created table list_values")
 
+    conn.commit()
     conn.close()
 
 
 def create_database():
-    conn = sqlite3.connect(os.path.join(PATH, "database.db"))
+    db_name_database = "database.db"
+    conn = sqlite3.connect(os.path.join(PATH, db_name_database))
     c = conn.cursor()
-    try:
-        c.execute(
-            """
-            CREATE TABLE commands (
-                command TEXT NOT NULL,
-                prefix TEXT NOT NULL,
-                permission INTEGER NOT NULL,
-                description TEXT,
-                user_cooldown INTEGER NOT NULL,
-                global_cooldown INTEGER NOT NULL,
-                last_used INTEGER NOT NULL,
-                PRIMARY KEY (command)
-            )
-            """
+    logger.info(f"connected to database {db_name_database}")
+
+    c.execute(
+        """
+        CREATE TABLE IF NOT EXISTS commands (
+            command TEXT NOT NULL,
+            prefix TEXT NOT NULL,
+            permission INTEGER NOT NULL,
+            description TEXT,
+            user_cooldown INTEGER NOT NULL,
+            global_cooldown INTEGER NOT NULL,
+            last_used INTEGER NOT NULL,
+            PRIMARY KEY (command)
         )
-    except sqlite3.OperationalError as e:
-        print(e)
+        """
+    )
+    logger.info(f"created table commands")
 
-    try:
-        c.execute(
-            """
-            CREATE TABLE users (
-                user_id text NOT NULL,
-                permission INTEGER NOT NULL,
-                PRIMARY KEY (user_id)
-            )
-            """
+    c.execute(
+        """
+        CREATE TABLE IF NOT EXISTS users (
+            user_id text NOT NULL,
+            permission INTEGER NOT NULL,
+            PRIMARY KEY (user_id)
         )
-    except sqlite3.OperationalError as e:
-        print(e)
+        """
+    )
+    logger.info(f"created table users")
 
     admin_id = ttv_api.users.get_users(user_logins=["skgyorugo"])
     aptbot_id = ttv_api.users.get_users(user_logins=["murphyai"])
     broadcaster_id = ttv_api.users.get_users(user_logins=[streamer_login])
     if admin_id:
-        try:
-            c.execute("INSERT INTO users VALUES (?, ?)",
-                      (admin_id[0].user_id, 0))
-        except sqlite3.IntegrityError as e:
-            print(e)
+        c.execute("INSERT OR IGNORE INTO users VALUES (?, ?)",
+                  (admin_id[0].user_id, 0))
+        logger.info(f"inserted user {admin_id[0].user_id} with permission {0}")
     if aptbot_id:
-        try:
-            c.execute("INSERT INTO users VALUES (?, ?)",
-                      (aptbot_id[0].user_id, 0))
-        except sqlite3.IntegrityError as e:
-            print(e)
+        c.execute("INSERT OR IGNORE INTO users VALUES (?, ?)",
+                  (aptbot_id[0].user_id, 0))
+        logger.info(f"inserted user {aptbot_id[0].user_id} with permission {0}")
     if broadcaster_id:
-        try:
-            c.execute("INSERT INTO users VALUES (?, ?)",
-                      (broadcaster_id[0].user_id, 1))
-        except sqlite3.IntegrityError as e:
-            print(e)
+        c.execute("INSERT OR IGNORE INTO users VALUES (?, ?)",
+                  (broadcaster_id[0].user_id, 1))
+        logger.info(f"inserted user {broadcaster_id[0].user_id} with permission {1}")
 
-    try:
-        c.execute(
-            """
-            CREATE TABLE cooldowns (
-                user_id TEXT NOT NULL,
-                command TEXT NOT NULL,
-                user_cooldown INTEGER NOT NULL,
-                FOREIGN KEY(user_id) REFERENCES users(user_id)
-                FOREIGN KEY(command) REFERENCES commands(command)
-                PRIMARY KEY (user_id, command)
-            )
-            """
+    c.execute(
+        """
+        CREATE TABLE IF NOT EXISTS cooldowns (
+            user_id TEXT NOT NULL,
+            command TEXT NOT NULL,
+            user_cooldown INTEGER NOT NULL,
+            FOREIGN KEY(user_id) REFERENCES users(user_id)
+            FOREIGN KEY(command) REFERENCES commands(command)
+            PRIMARY KEY (user_id, command)
         )
-    except sqlite3.OperationalError as e:
-        print(e)
+        """
+    )
+    logger.info(f"created table cooldowns")
 
-    try:
-        c.execute(
-            """
-            CREATE TABLE command_values (
-                command TEXT NOT NULL,
-                value TEXT NOT NULL,
-                FOREIGN KEY(command) REFERENCES commands(command)
-            )
-            """
+    c.execute(
+        """
+        CREATE TABLE IF NOT EXISTS command_values (
+            command TEXT NOT NULL,
+            value TEXT NOT NULL,
+            FOREIGN KEY(command) REFERENCES commands(command)
         )
-    except sqlite3.OperationalError as e:
-        print(e)
+        """
+    )
+    logger.info(f"created table command_values")
 
-    try:
-        c.execute(
-            """
-            CREATE TABLE auto_messages (
-                name TEXT NOT NULL,
-                cooldown INTEGER NOT NULL,
-                end_time INTEGER NOT NULL,
-                last_used INTEGER NOT NULL,
-                PRIMARY KEY (name)
-            )
-            """
+    c.execute(
+        """
+        CREATE TABLE IF NOT EXISTS auto_messages (
+            name TEXT NOT NULL,
+            cooldown INTEGER NOT NULL,
+            end_time INTEGER NOT NULL,
+            last_used INTEGER NOT NULL,
+            PRIMARY KEY (name)
         )
-    except sqlite3.OperationalError as e:
-        print(e)
+        """
+    )
+    logger.info(f"created table auto_messages")
 
-    try:
-        c.execute(
-            """
-            CREATE TABLE auto_message_values (
-                name TEXT NOT NULL,
-                value TEXT NOT NULL,
-                FOREIGN KEY(name) REFERENCES auto_messages(name)
-            )
-            """
+    c.execute(
+        """
+        CREATE TABLE IF NOT EXISTS auto_message_values (
+            name TEXT NOT NULL,
+            value TEXT NOT NULL,
+            FOREIGN KEY(name) REFERENCES auto_messages(name)
         )
-    except sqlite3.OperationalError as e:
-        print(e)
+        """
+    )
+    logger.info(f"created table auto_message_values")
 
-    try:
-        c.execute(
-            """
-            CREATE TABLE stream_info (
-                start_stream_ts INTEGER NOT NULL,
-                last_checked INTEGER NOT NULL,
-                ended INTEGER NOT NULL,
-                PRIMARY KEY (start_stream_ts)
-            )
-            """
+    c.execute(
+        """
+        CREATE TABLE IF NOT EXISTS stream_info (
+            start_stream_ts INTEGER NOT NULL,
+            last_checked INTEGER NOT NULL,
+            ended INTEGER NOT NULL,
+            PRIMARY KEY (start_stream_ts)
         )
-    except sqlite3.OperationalError as e:
-        print(e)
+        """
+    )
+    logger.info(f"created table stream_info")
 
     conn.commit()
     conn.close()
 
 
 def update_commands_in_database(modules, commands):
-    conn = sqlite3.connect(os.path.join(PATH, "database.db"))
+    db_name_database = "database.db"
+    conn = sqlite3.connect(os.path.join(PATH, db_name_database))
     c = conn.cursor()
+    logger.info(f"connected to database {db_name_database}")
 
     for command in commands:
         command_name = command.split('.')[0]
                 command_last_used,
             )
         )
+        logger.info(f"updating commands command_name: {command_name}")
+        logger.debug(f"updating commands command_prefix: {command_prefix}")
+        logger.debug(f"updating commands command_permission: {command_permission}")
+        logger.debug(f"updating commands command_description: {command_description}")
+        logger.debug(f"updating commands command_user_cooldown: {command_user_cooldown}")
+        logger.debug(f"updating commands command_global_cooldown: {command_global_cooldown}")
+        logger.debug(f"updating commands command_last_used: {command_last_used}")
     conn.commit()
     conn.close()
 
 
 reload(database_manager)
 reload(analyze_auto_message)
 
-logging.basicConfig(
-    filename="/var/log/aptbot/logs.log",
-    level=logging.DEBUG,
-    format="[%(levelname)s] %(asctime)s: %(message)s"
-)
+logger = logging.getLogger(__name__)
+logger.setLevel(logging.DEBUG)
+
+formatter = logging.Formatter("[%(levelname)s] %(asctime)s: %(name)s; %(message)s")
+
+file_handler = logging.FileHandler('/var/log/aptbot/logs.log')
+file_handler.setFormatter(formatter)
+
+logger.addHandler(file_handler)
 
 PATH = os.path.dirname(os.path.realpath(__file__))
-logging.info(f"Defined PATH: {PATH}")
+logger.info(f"main PATH set to: {PATH}")
 COMMANDS_PATH = os.path.join(PATH, "commands")
-logging.info(f"Defined COMMANDS_PATH: {COMMANDS_PATH}")
+logger.info(f"main COMMANDS_PATH set to: {COMMANDS_PATH}")
 AUTO_MESSAGES_PATH = os.path.join(PATH, "auto_messages")
-logging.info(f"Defined AUTO_MESSAGES_PATH: {AUTO_MESSAGES_PATH}")
+logger.info(f"main AUTO_MESSAGES_PATH set to: {AUTO_MESSAGES_PATH}")
 
 commands_specs = {}
 commands_modules = {}
             os.path.join(COMMANDS_PATH, command)
         )
     )
-logging.info(f"List of commands: {commands}")
+logger.info(f"List of commands: {commands}")
 
 auto_messages = [
     c for c in os.listdir(AUTO_MESSAGES_PATH) if os.path.isfile(os.path.join(AUTO_MESSAGES_PATH, c))
             os.path.join(AUTO_MESSAGES_PATH, auto_message)
         )
     )
-logging.info(f"List of auto_messages: {auto_messages}")
+logger.info(f"List of auto_messages: {auto_messages}")
 
 for spec in commands_specs:
     commands_modules[spec] = importlib.util.module_from_spec(
     try:
         commands_specs[spec].loader.exec_module(commands_modules[spec])
     except Exception as e:
-        logging.critical(traceback.format_exc())
-        logging.critical(f"Problem Loading Module: {e}")
+        logger.critical(traceback.format_exc())
+        logger.critical(f"Problem Loading Module: {e}")
 
 for spec in auto_message_specs:
     auto_message_modules[spec] = importlib.util.module_from_spec(
     try:
         auto_message_specs[spec].loader.exec_module(auto_message_modules[spec])
     except Exception as e:
-        logging.critical(traceback.format_exc())
-        logging.critical(f"Problem Loading Module: {e}")
+        logger.critical(traceback.format_exc())
+        logger.critical(f"Problem Loading Module: {e}")
 
 
 database_manager.create_database()
 
 import ttv_api.stream
 import ttv_api.channel
 import sqlite3
+import logging
 from typing import Optional
 
+logger = logging.getLogger(__name__)
+
 STREAMER_PATH = os.path.abspath(os.path.join(__file__, "../.."))
+logger.debug(f"STREAMER_PATH set to: {STREAMER_PATH}")
 TOOLS_PATH = os.path.dirname(os.path.realpath(__file__))
+logger.debug(f"TOOLS_PATH set to: {TOOLS_PATH}")
 PATH = os.path.join(TOOLS_PATH, "..")
+logger.debug(f"PATH set to: {PATH}")
 
 
 CHECK_STREAMTIME_CD = 5 * 60
 
 def start_stream_timestamp() -> Optional[int]:
     streamer_login = os.path.split(STREAMER_PATH)[1]
+    logger.debug(f"streamer_login set to: {streamer_login}")
 
     conn = sqlite3.connect(os.path.join(PATH, "database.db"))
     c = conn.cursor()
             """
             SELECT
                 start_stream_ts,
-                last_checked,
-                ended
+                last_checked
             FROM
                 stream_info
             WHERE
         )
 
     fetched = c.fetchone()
+
     if fetched:
-        start_stream_ts, last_checked, _ = fetched
+        start_stream_ts, last_checked = fetched
+        logger.debug(f"start_stream_ts set to: {start_stream_ts}")
+        logger.debug(f"last_checked set to: {last_checked}")
         if time.time() < last_checked + CHECK_STREAMTIME_CD:
+            logger.info(f"returned cached start stream time: {start_stream_ts}")
+            conn.close()
             return start_stream_ts
 
     stream_info = ttv_api.stream.get_streams(user_logins=[streamer_login])
+    logger.info(f"used twitch api to get stream info")
     if not stream_info and not fetched:
+        logger.info(f"streamer {streamer_login} is currently not streaming")
+        conn.close()
         return
 
     if not stream_info:
-        start_stream_ts, last_checked, _ = fetched
+        start_stream_ts, last_checked = fetched
+        logger.debug(f"start_stream_ts set to: {start_stream_ts}")
+        logger.debug(f"last_checked set to: {last_checked}")
         if time.time() < last_checked + MAX_OFF_STREAM_MARGIN:
+            logger.info(f"streamer {streamer_login} is currently not streaming, stream not considered ended yet")
             conn.close()
             return
 
             )
         )
         conn.commit()
+        logger.info(f"streamer {streamer_login} has ended stream")
         conn.close()
         return
 
     if not fetched:
         start_stream_ts = int(stream_info[0].started_at.timestamp())
+        current_time = int(time.time())
         c.execute(
             "REPLACE INTO stream_info VALUES (?, ?, ?)",
             (
                 start_stream_ts,
-                int(time.time()),
+                current_time,
                 0,
             )
         )
         conn.commit()
+        logger.info(f"inserted database with start stream {start_stream_ts}, last updated {current_time}")
         conn.close()
+        logger.info(f"returned api start stream time: {start_stream_ts}")
         return start_stream_ts
 
-    start_stream_ts, last_checked, _ = fetched
+    start_stream_ts, last_checked = fetched
+    current_time = int(time.time())
     c.execute(
         "REPLACE INTO stream_info VALUES (?, ?, ?)",
         (
             start_stream_ts,
-            int(time.time()),
+            current_time,
             0,
         )
     )
     conn.commit()
+    logger.info(f"updated database with cached start stream {start_stream_ts}, last updated {current_time}")
     conn.close()
+    logger.info(f"returned cached start stream time: {start_stream_ts}")
     return start_stream_ts