from flask import Flask, render_template, jsonify
import requests
import struct
import math
from flask import Flask, render_template, jsonify, request, abort
from datetime import datetime
from pathlib import Path
import csv

app = Flask(__name__)

# >>> Nastav složku s CSV (MIMO web root) <<<
DATA_DIR = Path("/opt/mbm/logs")  # přepiš na svůj skutečný adresář
MODBUS_API_URL = "http://localhost/modbus/call"
API_KEY = "tajny-klic"

def filename_for_date(dt: datetime) -> Path:
    # soubory jsou DD_MM_RR.csv (RR = poslední dvě číslice roku)
    return DATA_DIR / dt.strftime("%d_%m_%y.csv")

def list_available_dates():
    # načti všechny soubory dle masky a převeď na ISO datum (YYYY-MM-DD)
    dates = []
    for p in sorted(DATA_DIR.glob("??_??_??.csv")):
        try:
            dt = datetime.strptime(p.stem, "%d_%m_%y")
            dates.append(dt.date())
        except ValueError:
            continue
    return dates

def parse_csv_for_date(dt: datetime):
    path = filename_for_date(dt)
    if not path.exists():
        return None

    times = []
    # 1-based sloupce podle zadání:
    col2, col3, col4 = [], [], []
    col7, col8, col9 = [], [], []
    flag16, flag17, flag18, flag21 = [], [], [], []

    with path.open("r", encoding="utf-8", newline="") as f:
        reader = csv.reader(f)
        for row in reader:
            if not row:
                continue
            # ochrana proti krátkým řádkům
            while len(row) < 21:
                row.append("")
            # čas v prvním sloupci – vezmeme čistý string (např. "12:34:56")
            times.append(row[0].strip())

            # bezpečné převody na float/int
            def fnum(v, default=0.0):
                try: return float(v.replace(",", "."))  # kdyby byly čárky
                except: return default
            def inum(v, default=0):
                try: return int(float(v))
                except: return default

            col2.append(fnum(row[1]))
            col3.append(fnum(row[2]))
            col4.append(fnum(row[3]))
            col7.append(fnum(row[8]))
            col8.append(fnum(row[9]))
            col9.append(fnum(row[10]))

            flag16.append(inum(row[14]))
            flag17.append(inum(row[15]))
            flag18.append(inum(row[16]))
            flag21.append(inum(row[21]))

    return {
        "date": dt.strftime("%Y-%m-%d"),
        "times": times,
        "a2": col2, "a3": col3, "a4": col4,           # Ampéry
        "v7": col7, "v8": col8, "v9": col9,           # Volty
        "f16": flag16, "f17": flag17, "f18": flag18, "f21": flag21
    }
@app.route("/historie")
def historie():
    # HTML – data si frontend načte přes /api/history/latest
    return render_template("historie.html")

@app.route("/api/history/available")
def api_history_available():
    dates = list_available_dates()
    return jsonify({
        "dates": [d.isoformat() for d in dates]  # YYYY-MM-DD
    })

@app.route("/api/history/latest")
def api_history_latest():
    dates = list_available_dates()
    if not dates:
        return jsonify({"dates": [], "data": None})
    last = dates[-1]
    data = parse_csv_for_date(datetime.combine(last, datetime.min.time()))
    return jsonify({"dates": [d.isoformat() for d in dates], "data": data})

@app.route("/api/history/data")
def api_history_data():
    # očekáváme ?date=YYYY-MM-DD
    ds = request.args.get("date", "")
    try:
        dt = datetime.strptime(ds, "%Y-%m-%d")
    except ValueError:
        abort(400, "Bad date")
    data = parse_csv_for_date(dt)
    if not data:
        abort(404, "No CSV for date")
    return jsonify(data)

# prázdné stránky pro šipky
@app.route("/historie-prev")
def historie_prev():
    return render_template("placeholder.html", title="Předchozí")

@app.route("/historie-next")
def historie_next():
    return render_template("placeholder.html", title="Další")

def transferit(INs,OUs):
    CRLs = 3
    if INs is True and OUs is True:
        CRLs = 1
    if INs is False and OUs is False:
        CRLs = 2
    return (CRLs)
def cahnge_INs(INs):
    vstupy=[INs,INs[0],INs[4],INs[5],INs[6]]
    return(vstupy)
def cahnge_OUs(OUs):
    vystupy=[OUs,OUs[0],OUs[1],OUs[2],OUs[3]]
    return(vystupy)
def change_to_CRLs(INs,OUs):
    if INs[1] is True and OUs[1] is True:
        CRLs = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
    CRLs[3]=transferit(INs[2],OUs[2])
    CRLs[4]=transferit(INs[3],OUs[3])
    CRLs[5]=transferit(INs[4],OUs[4])       
    if INs[1] is False and OUs[1] is False:
        CRLs = [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]
    if INs[1] is False and OUs[1] is True:
        CRLs = [3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]
    return (CRLs)       
def load_curs():
    req = {
        "ip": "192.168.11.155",
        "port": 503,
        "instr": 7,
        "addr": 1,
        "count": 8,
        "type": "raw"
    }
    data = call_modbus(req)
    inD = ensure_list(data.get("data") if isinstance(data, dict) else [])
    req = {
        "ip": "192.168.11.155",
        "port": 503,
        "instr": 2,
        "addr": 8193,
        "count": 8,
        # "type": "raw"  # nebo "uint16" nebo nic – podle toho, jak máš backend
    }
    data = call_modbus(req)
    outD = ensure_list(data.get("data") if isinstance(data, dict) else [])
    outD=cahnge_OUs(outD)
    print(outD)
    inD=cahnge_INs(inD)
    print(inD)
    CRLs=change_to_CRLs(inD,outD)
    return(CRLs)
    
def convert_to_floats(raw_list):
    """Převede seznam 16bit registrů (raw) na floaty po dvojicích."""
    floats = []
    try:
        # zpracujeme po 2 registrech (každý 16 bitů)
        for i in range(0, len(raw_list), 2):
            if i + 1 < len(raw_list):
                # spojíme dva 16bitové do jednoho 32bit integeru (big endian)
                raw = (raw_list[i] << 16) | raw_list[i + 1]
                # převedeme na float podle IEEE754
                val = struct.unpack('>f', struct.pack('>I', raw))[0]
                floats.append(round(val, 4))
        return floats
    except Exception as e:
        print(f"Chyba při převodu na float: {e}")
        return raw_list  # fallback – vrátíme původní hodnoty
# společná funkce na volání modbus API
def ensure_list(value):
    if isinstance(value, list):
        return value
    elif value is None:
        return []
    else:
        return [value]
def call_modbus(payload: dict):
    try:
        resp = requests.post(
            MODBUS_API_URL,
            json=payload,
            headers={"X-API-Key": API_KEY},
            verify=False  # protože voláš curl -k, tak i tady vypneme ověřování certu
        )
        resp.raise_for_status()
        return resp.json()
    except Exception as e:
        # vrátíme chybu, aby se to ukázalo na stránce
        return {"error": str(e)}

def get_data():
    # tady si dej reálné čtení z modbusu
    VOLs = [232.3, 233.7, 227.4, 231.3, 236.0, 231.0]
    AMPs = [12.1, 11.8, 10.5, 9.9, 9.7, 9.4]
    TEEs = [36.5, 38.2]
    CRLs = [1, 3, 2, 1, 1, 2, 3, 1, 1, 1, 2, 3, 1, 1, 1, 1]
    req = {
        "ip": "192.168.11.155",
        "port": 503,
        "instr": 1,
        "addr": 0,
        "count": 12,
        "type": "raw"
    }
    data = call_modbus(req)
    AMPs = ensure_list(data.get("data") if isinstance(data, dict) else [])
    AMPs = convert_to_floats(AMPs)
    req = {
        "ip": "192.168.11.155",
        "port": 503,
        "instr": 1,
        "addr": 13,
        "count": 12,
        "type": "raw"
    }
    data = call_modbus(req)
    VOLs = ensure_list(data.get("data") if isinstance(data, dict) else [])
    VOLs = convert_to_floats(VOLs)
    req = {
        "ip": "192.168.11.155",
        "port": 503,
        "instr": 1,
        "addr": 25,
        "count": 4,
        "type": "raw"
    }
    data = call_modbus(req)
    TEEs = ensure_list(data.get("data") if isinstance(data, dict) else [])
    TEEs = convert_to_floats(TEEs)
    CRLs=load_curs()
    req = {
        "ip": "192.168.11.155",
        "port": 503,
        "instr": 1,
        "addr": 16384,
        "count": 4,
        "type": "raw"
    }
    data = call_modbus(req)
    stas = ensure_list(data.get("data") if isinstance(data, dict) else [])
    stas = convert_to_floats(stas)
    TEEs[0]=[TEEs[0],1,1] 
    TEEs[0][2]=(((VOLs[0]+VOLs[1]+VOLs[2])/3)*(AMPs[0]+AMPs[1]+AMPs[2]))
    TEEs[0][1]=(TEEs[0][2]/1000)*360
    TEEs[1]=[TEEs[1],1,1]
    TEEs[1][2]=(((VOLs[3]+VOLs[4]+VOLs[5])/3)*(AMPs[3]+AMPs[4]+AMPs[5]))
    TEEs[1][1]=(TEEs[1][2]/1000)*360
    return {
        "vols": VOLs,
        "amps": AMPs,
        "tees": TEEs,
        "crls": CRLs,
        "stas": stas,
        "M_block" : outD[0],
    }

@app.route("/")
def dashboard():
    data = get_data()
    return render_template("index.html", **data)

@app.route("/data")
def data():
    # vrací jen data, ne celou HTML šablonu
    return jsonify(get_data())
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8002, debug=True)
