from flask import Flask, jsonify, render_template, request, redirect, url_for, session
from flask_cors import CORS
from config import Config
import psycopg2

app = Flask(__name__)
app.config.from_object(Config)
app.secret_key = app.config["SECRET_KEY"]

CORS(app)


def get_connection():
    return psycopg2.connect(
        host=app.config["DB_HOST"],
        port=app.config["DB_PORT"],
        database=app.config["DB_NAME"],
        user=app.config["DB_USER"],
        password=app.config["DB_PASSWORD"]
    )


def get_setting_value(cur, key, default_value):
    cur.execute("SELECT value FROM settings WHERE key = %s", (key,))
    row = cur.fetchone()
    return row[0] if row else default_value


@app.route("/")
def home():
    return jsonify({
        "message": "API EcoCharge en ligne"
    })


@app.route("/api/status")
def status():
    return jsonify({
        "project": "EcoCharge",
        "api": "ok",
        "database": "postgresql_connected"
    })


@app.route("/api/data", methods=["POST"])
def receive_data():
    data = request.get_json()

    if not data:
        return jsonify({"error": "Aucune donnée JSON reçue"}), 400

    # Données environnement
    temperature_ext = data.get("temperature_ext")
    humidity_ext = data.get("humidity_ext")
    system_status_msg = data.get("system_status")

    # Données panneau solaire
    voltage_pv = data.get("voltage_pv")
    current_pv = data.get("current_pv")

    # compatible solar_power
    power_pv = data.get("power_pv", data.get("solar_power"))

    luminosity = data.get("luminosity")

    # Données batterie
    voltage_battery = data.get("voltage_battery", data.get("battery_voltage"))
    current_battery = data.get("current_battery")

    # compatible battery_temperature
    battery_temp = data.get("battery_temp", data.get("battery_temperature"))

    battery_level = data.get("battery_level")

    conn = get_connection()
    cur = conn.cursor()

    max_battery_temperature = float(get_setting_value(cur, "max_battery_temperature", "60"))
    min_battery_voltage = float(get_setting_value(cur, "min_battery_voltage", "11"))
    min_solar_power = float(get_setting_value(cur, "min_solar_power", "5"))

    battery_alert = "none"

    if battery_temp is not None and float(battery_temp) > max_battery_temperature:
        battery_alert = "Température batterie trop élevée"

    elif voltage_battery is not None and float(voltage_battery) < min_battery_voltage:
        battery_alert = "Tension batterie trop faible"

    elif power_pv is not None and float(power_pv) < min_solar_power:
        battery_alert = "Puissance solaire insuffisante"

    cur.execute("""
        INSERT INTO telemetry (
            temperature_ext,
            humidity_ext,
            system_status_msg,
            voltage_pv,
            current_pv,
            power_pv,
            luminosity,
            voltage_battery,
            current_battery,
            battery_temp,
            battery_level,
            battery_alert
        ) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)
    """, (
        temperature_ext,
        humidity_ext,
        system_status_msg,
        voltage_pv,
        current_pv,
        power_pv,
        luminosity,
        voltage_battery,
        current_battery,
        battery_temp,
        battery_level,
        battery_alert
    ))

    conn.commit()
    cur.close()
    conn.close()

    return jsonify({
        "message": "Données enregistrées avec succès",
        "battery_alert": battery_alert
    }), 201


@app.route("/api/latest", methods=["GET"])
def latest_data():

    conn = get_connection()
    cur = conn.cursor()

    cur.execute("""
        SELECT
            id,
            created_at,
            temperature_ext,
            humidity_ext,
            system_status_msg,
            voltage_pv,
            current_pv,
            power_pv,
            luminosity,
            voltage_battery,
            current_battery,
            battery_temp,
            battery_level,
            battery_alert
        FROM telemetry
        ORDER BY created_at DESC
        LIMIT 1
    """)

    row = cur.fetchone()

    cur.close()
    conn.close()

    if not row:
        return jsonify({"message": "Aucune donnée disponible"}), 404

    return jsonify({
        "id": row[0],
        "created_at": str(row[1]),
        "temperature_ext": row[2],
        "humidity_ext": row[3],
        "system_status": row[4],
        "voltage_pv": row[5],
        "current_pv": row[6],
        "power_pv": row[7],
        "luminosity": row[8],
        "voltage_battery": row[9],
        "current_battery": row[10],
        "battery_temp": row[11],
        "battery_level": row[12],
        "battery_alert": row[13]
    })


@app.route("/admin/login", methods=["GET", "POST"])
def admin_login():

    if request.method == "POST":

        username = request.form.get("username")
        password = request.form.get("password")

        conn = get_connection()
        cur = conn.cursor()

        cur.execute(
            "SELECT id FROM users WHERE username = %s AND password = %s AND is_admin = TRUE",
            (username, password)
        )

        user = cur.fetchone()

        cur.close()
        conn.close()

        if user:
            session["admin_logged_in"] = True
            return redirect(url_for("admin_dashboard"))

        return render_template("login.html", error="Identifiants incorrects")

    return render_template("login.html")


@app.route("/admin/dashboard", methods=["GET", "POST"])
def admin_dashboard():

    if not session.get("admin_logged_in"):
        return redirect(url_for("admin_login"))

    conn = get_connection()
    cur = conn.cursor()

    if request.method == "POST":

        min_battery = request.form.get("min_battery")
        max_temp = request.form.get("max_temp")
        min_power = request.form.get("min_power")

        cur.execute("""
            INSERT INTO settings (key, value)
            VALUES ('min_battery_voltage', %s)
            ON CONFLICT (key)
            DO UPDATE SET value = EXCLUDED.value
        """, (min_battery,))

        cur.execute("""
            INSERT INTO settings (key, value)
            VALUES ('max_battery_temperature', %s)
            ON CONFLICT (key)
            DO UPDATE SET value = EXCLUDED.value
        """, (max_temp,))

        cur.execute("""
            INSERT INTO settings (key, value)
            VALUES ('min_solar_power', %s)
            ON CONFLICT (key)
            DO UPDATE SET value = EXCLUDED.value
        """, (min_power,))

        conn.commit()

    settings = {
        "min_battery": get_setting_value(cur, "min_battery_voltage", "11"),
        "max_temp": get_setting_value(cur, "max_battery_temperature", "60"),
        "min_power": get_setting_value(cur, "min_solar_power", "5")
    }

    cur.close()
    conn.close()

    return render_template("admin_dashboard.html", settings=settings)


@app.route("/admin/logout")
def admin_logout():

    session.pop("admin_logged_in", None)

    return redirect(url_for("admin_login"))


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