from flask import Flask, request, jsonify, Response
import logging
import json
import pymysql
import os
import threading
from pyftpdlib.authorizers import DummyAuthorizer
from pyftpdlib.handlers import FTPHandler
from pyftpdlib.servers import FTPServer

CONFIG_FILE = "config.json"

try:
    with open(CONFIG_FILE, "r", encoding="utf-8") as f:
        _config = json.load(f)
except FileNotFoundError:
    _config = {}

MYSQL_CFG = _config.get("mysql", {})


def get_db_conn():
    return pymysql.connect(
        host=MYSQL_CFG.get("host"),
        user=MYSQL_CFG.get("user"),
        password=MYSQL_CFG.get("password"),
        db=MYSQL_CFG.get("db"),
        charset=MYSQL_CFG.get("charset", "utf8"),
        autocommit=True,
    )


def load_runtime_config():
    conn = get_db_conn()
    try:
        with conn.cursor(pymysql.cursors.DictCursor) as cur:
            cur.execute("SELECT config_key, config_value FROM op_config")
            rows = cur.fetchall()
    finally:
        conn.close()
    return {r["config_key"]: r["config_value"] for r in rows}

def init_db():
    conn = get_db_conn()
    try:
        with conn.cursor() as cur:
            cur.execute(
                """
                CREATE TABLE IF NOT EXISTS op_diagnostics (
                    id INT AUTO_INCREMENT PRIMARY KEY,
                    filename VARCHAR(255) NOT NULL,
                    data LONGBLOB NOT NULL,
                    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
                )
                """
            )
    finally:
        conn.close()


app = Flask(__name__)

init_db()

# Runtime config for FTP server
_runtime_cfg = load_runtime_config()
FTP_PORT = int(_runtime_cfg.get("diag_ftp_port", 21))
FTP_USER = _runtime_cfg.get("diag_ftp_user", "diag")
FTP_PASSWORD = _runtime_cfg.get("diag_ftp_password", "rem0tec0nnect2026x")
FTP_ROOT = "/tmp/diag_ftp"
os.makedirs(FTP_ROOT, exist_ok=True)


class DBFTPHandler(FTPHandler):
    """FTP handler that stores received files in the database."""

    def on_file_received(self, file):
        filename = os.path.basename(file).replace(":", "_")
        with open(file, "rb") as f:
            data = f.read()
        conn = get_db_conn()
        with conn.cursor() as cur:
            cur.execute(
                "INSERT INTO op_diagnostics (filename, data) VALUES (%s, %s)",
                (filename, data),
            )
        conn.close()
        os.remove(file)


def start_ftp_server():
    authorizer = DummyAuthorizer()
    authorizer.add_user(FTP_USER, FTP_PASSWORD, FTP_ROOT, perm="elradfmw")
    handler = DBFTPHandler
    handler.authorizer = authorizer
    server = FTPServer(("0.0.0.0", FTP_PORT), handler)
    server.serve_forever()

# Configure logging
logging.basicConfig(level=logging.INFO)

@app.get('/robots.txt')
def robots_txt():
    return Response('User-agent: *\nDisallow: /\n', mimetype='text/plain')

@app.route('/upload_diagnostics/<path:filename>', methods=['PUT'])
def upload_diagnostics_put(filename):
    # Ersetze gefährliche Zeichen im Dateinamen
    safe_filename = filename.replace(":", "_")

    print(f"Empfange Datei: {filename} → gespeichert als: {safe_filename}")

    try:
        conn = get_db_conn()
        with conn.cursor() as cur:
            cur.execute(
                "INSERT INTO op_diagnostics (filename, data) VALUES (%s, %s)",
                (safe_filename, request.data),
            )
        conn.close()
        return 'OK', 200
    except Exception as e:
        print(f"Fehler beim Speichern: {e}")
        return 'Fehler beim Speichern', 500

    
@app.route("/upload_diagnostics", methods=["POST", "GET"])
def upload_diagnostics():
    print(request)
    if not request.files:
        logging.warning("No file part in request")
        return jsonify({"error": "No file part in request"}), 400
    
    for file_key in request.files:
        file = request.files[file_key]
        if file.filename == "":
            logging.warning("No selected file")
            return jsonify({"error": "No selected file"}), 400

        data = file.read()
        conn = get_db_conn()
        with conn.cursor() as cur:
            cur.execute(
                "INSERT INTO op_diagnostics (filename, data) VALUES (%s, %s)",
                (file.filename, data),
            )
        conn.close()
        logging.info(f"File {file.filename} uploaded successfully")
    return jsonify({"message": "File uploaded successfully"})


@app.get("/diagnostics")
def list_diagnostics():
    conn = None
    try:
        conn = get_db_conn()
        with conn.cursor(pymysql.cursors.DictCursor) as cur:
            cur.execute(
                "SELECT filename, created_at FROM op_diagnostics ORDER BY created_at DESC"
            )
            rows = cur.fetchall()

        diagnostics = []
        for row in rows:
            created_at = row.get("created_at")
            diagnostics.append(
                {
                    "filename": row.get("filename"),
                    "created_at": created_at.isoformat() if created_at else None,
                }
            )

        return jsonify({"diagnostics": diagnostics})
    except Exception:
        logging.exception("Failed to fetch diagnostics")
        return jsonify({"error": "Failed to fetch diagnostics"}), 500
    finally:
        if conn is not None:
            conn.close()


if __name__ == "__main__":
    ftp_thread = threading.Thread(target=start_ftp_server, daemon=True)
    ftp_thread.start()
    app.run(host="0.0.0.0", port=9090, debug=True)
