import subprocess
import threading
import time
import requests
import os
import pymysql
import logging
import bcrypt
import configparser
from functools import partial

CONFIG_PATH = "/app/config.ini"
#CONFIG_PATH = "../config.ini"
config = configparser.ConfigParser()
config.read(CONFIG_PATH)
loglevel_str = config["log"]["level"].upper()
loglevel = getattr(logging, loglevel_str, logging.INFO)
logging.basicConfig(level=loglevel)

DB_CONFIG = {
    'host': config["database"]["host"],
    'user': config["database"]["user"],
    'password': config["database"]["password"],
    'database': config["database"]["database"]
}

LICENSE_SERVER = "https://sikkerdata.com/validate_license.php"
LICENSE_KEY = config["license"]["license_key"]
with open("/etc/machine-id", "r") as f:
    get_HWID = f.read().strip()

def validate_license():
    try:
        hwid = get_HWID
        response = requests.post(LICENSE_SERVER, json={
            "license_key": LICENSE_KEY,
            "hwid": hwid
        }, timeout=5)
        logging.info(f"[MAIN] License server response: {response.text}")
        if response.status_code == 200:
            result = response.json()
            if result.get("status") == "valid":
                logging.info("[MAIN] License validated")
                return True
            else:
                logging.info(f"[MAIN] License check failed: {result.get('message')}")
                return False
        else:
            logging.info(f"[MAIN] License server error: {response.status_code}")
            return False
    except Exception as e:
        logging.info(f"[MAIN] License check exception: {e}")
        return False

def setup_database(db_config):
    conn = pymysql.connect(**db_config)
    cursor = conn.cursor()

    def table_exists(name):
        cursor.execute("SHOW TABLES LIKE %s", (name,))
        return cursor.fetchone() is not None

    # Create `users` table if missing
    if not table_exists('users'):
        print("[DB] Creating 'users' table...")
        cursor.execute("""
            CREATE TABLE users (
              id INT AUTO_INCREMENT PRIMARY KEY,
              username VARCHAR(50) NOT NULL UNIQUE,
              full_name VARCHAR(100) NOT NULL,
              email VARCHAR(255) NOT NULL UNIQUE,
              phone VARCHAR(20),
              password_hash VARCHAR(255) NOT NULL,
              totp_secret VARCHAR(64),
              user_role ENUM('Admin','Operator','Installer','Client') DEFAULT 'Client',
              access_group VARCHAR(100),
              created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
        """)

    # Create `signals` table if missing
    if not table_exists('signals'):
        print("[DB] Creating 'signals' table...")
        cursor.execute("""
            CREATE TABLE signals (
              id INT AUTO_INCREMENT PRIMARY KEY,
              timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
              protocol VARCHAR(10) NOT NULL,
              raw_message TEXT NOT NULL,
              account VARCHAR(20),
              sequence VARCHAR(10),
              line_number VARCHAR(10),
              event_code VARCHAR(10),
              partition VARCHAR(10),
              zone VARCHAR(20),
              signal_time DATETIME,
              source_ip VARCHAR(45),
              signal_text VARCHAR(255),
              v TEXT,
              x TEXT,
              y TEXT
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
        """)
    if not table_exists('receivers'):
        print("[DB] Creating 'receivers' table...")
        cursor.execute("""
            CREATE TABLE receivers (
                id INT AUTO_INCREMENT PRIMARY KEY,
                name VARCHAR(50) NOT NULL,
                type ENUM('SIA-DC09') NOT NULL DEFAULT 'SIA-DC09',
                tcpport INT NOT NULL,
                enabled BOOLEAN DEFAULT 1
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
        """)
        cursor.execute("""INSERT INTO receivers (name, type, tcpport, enabled) VALUES ('Main Receiver', 'SIA-DC09', 9000, 1);""")

    # If no users exist, create default admin
    cursor.execute("SELECT COUNT(*) FROM users")
    (user_count,) = cursor.fetchone()
    if user_count == 0:
        print("[DB] Inserting default admin user...")
        default_password = bcrypt.hashpw("admin123".encode(), bcrypt.gensalt()).decode('utf-8')
        cursor.execute("""
            INSERT INTO users (username, full_name, email, password_hash, user_role)
            VALUES (%s, %s, %s, %s, %s)
        """, ("admin", "Admin", "admin@example.com", default_password, "Admin"))
        print("[DB] Admin created with username 'admin' and password 'admin123'")

    conn.commit()
    cursor.close()
    conn.close()

running_services = {}

def watchdog():
    bin_path = "/app/watchdog.bin"
    def run_watchdog():
        while True:
            cmd = [bin_path]
            logging.debug(f"[MAIN] Starting Watchdog...")
            process = subprocess.Popen(cmd)
            running_services["Watchdog"] = process
            process.wait()
            logging.debug(f"[MAIN] Watchdog finished. Restarting in 5s...")
            time.sleep(5)

    thread = threading.Thread(target=run_watchdog, name="Watchdog", daemon=True)
    thread.start()

def is_watchdog_running():
    return any(thread.name == "Watchdog" and thread.is_alive() for thread in threading.enumerate())

def main():
    logging.info("[MAIN] Starting main function")
    try:
        if not validate_license():
            logging.info("[MAIN] Shutting down due to invalid license.")
            return
        setup_thread = threading.Thread(target=partial(setup_database, DB_CONFIG), daemon=True)
        setup_thread.start()
        setup_thread.join()  # Wait for DB setup before continuing

        while True:
            try:
                logging.debug(f"[MAIN] Main is running")

                if is_watchdog_running():
                    logging.debug("[MAIN] Watchdog thread is already running")
                else:
                    watchdog()

                time.sleep(10)
            except Exception as e:
                logging.exception(f"[MAIN] Exception while logging thread status: {e}")

    except KeyboardInterrupt:
        logging.info("Graceful shutdown requested")

def wait_for_mariadb(host, port, user, password, database, timeout=5):
    logging.info(f"[WAIT] Waiting for MariaDB at {host}:{port} to become ready...")
    while True:
        try:
            conn = pymysql.connect(
                host=host,
                port=port,
                user=user,
                password=password,
                database=database,
                connect_timeout=timeout
            )
            with conn.cursor() as cursor:
                cursor.execute("SELECT 1;")
                result = cursor.fetchone()
                if result:
                    logging.info("[WAIT] MariaDB is ready.")
                    conn.close()
                    break
        except pymysql.MySQLError as e:
            logging.warning(f"[WAIT] MariaDB not ready yet: {e}")
            time.sleep(timeout)

if __name__ == "__main__":
    wait_for_mariadb(
        host=config["database"]["host"],
        port=3306,
        user=config["database"]["user"],
        password=config["database"]["password"],
        database=config["database"]["database"]
    )
    main()

