from flask import Flask, render_template, request, redirect, url_for, session, send_file
import sqlite3
import subprocess
import os
import paramiko
from concurrent.futures import ThreadPoolExecutor
import json
import io

app = Flask(__name__)
app.secret_key = 'votre_clef_secrete'
executor = ThreadPoolExecutor(max_workers=2)

# Charger la configuration depuis le fichier JSON
with open('config.json', 'r') as config_file:
    config = json.load(config_file)

DB_PATH = 'tickets.db'
LOG_FILE_PATH = config.get('log_file_path', '/var/log/syslog')
SSH_HOST = 'localhost'
SSH_PORT = 22
SSH_USER = 'admin'
SSH_PASSWORD = 'admin'
ALLOWED_COMMANDS = ['uptime', 'df -h', 'top -bn1']
ALLOWED_SSH_DIR = '/home/admin/uploads'

def init_db():
    conn = sqlite3.connect(DB_PATH)
    cursor = conn.cursor()
    cursor.execute('''CREATE TABLE IF NOT EXISTS tickets (id INTEGER PRIMARY KEY AUTOINCREMENT, message TEXT, statut TEXT DEFAULT 'ouvert')''')
    conn.commit()
    conn.close()

init_db()

def read_last_log_lines(n=10):
    with open(LOG_FILE_PATH, 'rb') as f:
        f.seek(0, os.SEEK_END)
        end = f.tell()
        buffer = bytearray()
        lines_found = 0
        while end > 0 and lines_found < n:
            end -= 1
            f.seek(end)
            byte = f.read(1)
            if byte == b'\n':
                lines_found += 1
            buffer.extend(byte)
        buffer.reverse()
        return buffer.decode('utf-8', errors='replace').strip()

def ssh_connect():
    try:
        client = paramiko.SSHClient()
        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        client.connect(SSH_HOST, port=SSH_PORT, username=SSH_USER, password=SSH_PASSWORD)
        return client
    except Exception as e:
        print(f"Erreur SSH : {e}")
        return None

@app.route('/')
def index():
    return redirect(url_for('login'))

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        if username == config.get("username") and password == config.get("password"):
            session['user'] = username
            return redirect(url_for('dashboard'))
        return render_template('login.html', error='Identifiants invalides')
    return render_template('login.html')

@app.route('/logout')
def logout():
    session.pop('user', None)
    return redirect(url_for('login'))

@app.route('/dashboard')
def dashboard():
    if 'user' not in session:
        return redirect(url_for('login'))
    logs = read_last_log_lines(20)
    return render_template('dashboard.html', logs=logs)

@app.route('/stats')
def stats():
    if 'user' not in session:
        return redirect(url_for('login'))
    result = subprocess.run(['df', '-h'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    disk_usage = result.stdout.decode('utf-8')
    return render_template('stats.html', disk_usage=disk_usage)

@app.route('/executor', methods=['GET', 'POST'])
def executor_route():
    if 'user' not in session:
        return redirect(url_for('login'))
    output = ''
    if request.method == 'POST':
        cmd = request.form['command']
        if cmd in ALLOWED_COMMANDS:
            try:
                output = subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, text=True)
            except subprocess.CalledProcessError as e:
                output = e.output
        else:
            output = "Commande non autorisée."
    return render_template('executor.html', output=output)

@app.route('/ssh')
def ssh():
    if 'user' not in session:
        return redirect(url_for('login'))
    client = ssh_connect()
    if not client:
        return render_template('ssh.html', files=[], error="Connexion SSH échouée.")
    sftp = client.open_sftp()
    try:
        files = sftp.listdir(ALLOWED_SSH_DIR)
    finally:
        sftp.close()
        client.close()
    return render_template('ssh.html', files=files)

@app.route('/ssh/download/<filename>')
def download_file(filename):
    if 'user' not in session:
        return redirect(url_for('login'))
    client = ssh_connect()
    if not client:
        return "Erreur SSH"
    sftp = client.open_sftp()
    file_obj = io.BytesIO()
    try:
        sftp.getfo(os.path.join(ALLOWED_SSH_DIR, filename), file_obj)
    finally:
        sftp.close()
        client.close()
    file_obj.seek(0)
    return send_file(file_obj, download_name=filename, as_attachment=True)

@app.route('/ssh/upload', methods=['POST'])
def upload_file():
    if 'user' not in session:
        return redirect(url_for('login'))
    uploaded_file = request.files['file']
    if uploaded_file:
        client = ssh_connect()
        if not client:
            return "Erreur SSH"
        sftp = client.open_sftp()
        try:
            sftp.putfo(uploaded_file.stream, os.path.join(ALLOWED_SSH_DIR, uploaded_file.filename))
        finally:
            sftp.close()
            client.close()
    return redirect(url_for('ssh'))

@app.route('/tickets')
def tickets():
    if 'user' not in session:
        return redirect(url_for('login'))
    conn = sqlite3.connect(DB_PATH)
    conn.row_factory = sqlite3.Row
    cursor = conn.cursor()
    cursor.execute("SELECT * FROM tickets")
    rows = cursor.fetchall()
    conn.close()
    return render_template('tickets.html', tickets=rows)

@app.route('/tickets/<int:ticket_id>/close')
def close_ticket(ticket_id):
    if 'user' not in session:
        return redirect(url_for('login'))
    conn = sqlite3.connect(DB_PATH)
    cursor = conn.cursor()
    cursor.execute("UPDATE tickets SET statut='ferme' WHERE id=?", (ticket_id,))
    conn.commit()
    conn.close()
    return redirect(url_for('tickets'))

def check_alerts():
    logs = read_last_log_lines(50).lower()
    keywords = ['erreur', 'fail', 'critical']
    if any(kw in logs for kw in keywords):
        conn = sqlite3.connect(DB_PATH)
        cursor = conn.cursor()
        cursor.execute("INSERT INTO tickets (message) VALUES (?)", (logs,))
        conn.commit()
        conn.close()

@app.before_request
def before_request():
    executor.submit(check_alerts)

if __name__ == '__main__':
    app.run(debug=True)
