from flask import Flask, render_template, request, send_from_directory
import paramiko
import ipaddress
import threading
import logging
from datetime import datetime, timedelta
import os

app = Flask(__name__)

# Předem definované skripty pro platformy
MIPSBE_SCRIPT = "mipsbe_script.sh"
ARM_SCRIPT = "arm_script.sh"

# Konfigurace logování
log_filename = f"{datetime.now().strftime('%Y%m%d')}.log"
logging.basicConfig(
    filename=log_filename,
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s'
)

# Funkce pro připojení přes SSH a detekci platformy
def ssh_to_device(ip, username, password, port, results, lock):
    try:
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh.connect(ip, username=username, password=password, port=port, timeout=5)

        # Retrieve RouterOS version to identify platform
        stdin, stdout, stderr = ssh.exec_command("/system resource print")
        output = stdout.read().decode()

        # Load commands from file based on platform
        executed_commands = []  # To store executed commands
        if "MikroTik" in output:
            if "mipsbe" in output.lower():
                with open("mipsbe_script.sh", "r") as file:
                    commands = file.readlines()
            elif "arm" in output.lower():
                with open("arm_script.sh", "r") as file:
                    commands = file.readlines()
            else:
                commands = []

            # Execute each command
            for command in commands:
                command = command.strip()  # Remove any extra whitespace
                if command:  # Ensure the command isn't empty
                    ssh.exec_command(command)
                    executed_commands.append(command)  # Store executed command

            result = {
                'ip': ip,
                'status': 'OK',
                'script': 'mipsbe' if "mipsbe" in output.lower() else 'arm',
                'executed_commands': executed_commands  # Add the list of executed commands
            }
            message = f"{ip} - Login: OK - Commands executed"
        else:
            result = {
                'ip': ip,
                'status': 'Not MikroTik',
                'script': 'none',
                'executed_commands': []
            }
            message = f"{ip} - Login: OK - Not a MikroTik device"

        ssh.close()
    except paramiko.AuthenticationException:
        result = {
            'ip': ip,
            'status': 'Authentication error',
            'script': 'none',
            'executed_commands': []
        }
        message = f"{ip} - Login: Authentication error"
    except Exception as e:
        # Check for errors that we don't want to display on the page
        error_message = str(e)
        if "Unable to connect to port 22" in error_message or "timed out" in error_message:
            # Only log the error without showing on the page
            message = f"{ip} - Error: {e}"
            result = None  # We won't add this to results
        else:
            result = {
                'ip': ip,
                'status': f'Error: {e}',
                'script': 'none',
                'executed_commands': []
            }
            message = f"{ip} - Login: Error - {e}"

    # Ensure thread-safe access to results and logging
    with lock:
        if result is not None:  # Only add to results if it's not a port 22 or timeout error
            results.append(result)
        logging.info(message)


@app.route('/', methods=['GET', 'POST'])
def index():
    results = []
    if request.method == 'POST':
        network_ranges = request.form['network_ranges'].split(',')
        username = request.form['username']
        password = request.form['password']
        port = int(request.form['port'])

        threads = []
        results_lock = threading.Lock()

        # Procházení každé IP adresy v rozsahu a pokus o přihlášení
        for network in network_ranges:
            network = network.strip()
            try:
                net = ipaddress.ip_network(network)
                for ip in net.hosts():
                    ip_str = str(ip)
                    thread = threading.Thread(target=ssh_to_device, args=(ip_str, username, password, port, results, results_lock))
                    threads.append(thread)
                    thread.start()
            except ValueError:
                error_message = f"Chybný formát rozsahu: {network}"
                results.append({'ip': network, 'status': 'Chybný rozsah', 'script': 'none'})
                logging.error(error_message)

        # Čekání na dokončení všech threadů
        for thread in threads:
            thread.join()

    # Převod výsledků na vhodný formát pro HTML
    formatted_results = []
    for res in results:
        formatted_results.append({
            'ip': res['ip'],
            'status': res['status'],
            'script': res['script']
        })

    # Získání log souborů z posledních 5 dnů
    log_files = []
    for i in range(5):
        date_str = (datetime.now() - timedelta(days=i)).strftime('%Y%m%d')
        log_filename = f"{date_str}.log"
        log_filepath = os.path.join(os.getcwd(), log_filename)
        
        if os.path.exists(log_filepath):
            log_files.append(log_filename)

    return render_template('index.html', results=formatted_results if results else None, log_files=log_files)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)

@app.route('/<filename>')
def download_log(filename):
    log_directory = os.path.abspath('.')
    return send_from_directory(log_directory, filename, mimetype='text/plain')


