import json
import sys
import threading
import time
from datetime import datetime, timezone
from pathlib import Path

# Add vendor/ to the import path so pip --target dependencies are found.
vendor_path = Path(__file__).parent / "vendor"
if vendor_path.exists():
    sys.path.insert(0, str(vendor_path))

import requests
from flask import Flask, jsonify, request, render_template
from waitress import serve

import config
import db

app = Flask(__name__, static_folder="static", template_folder="templates")
db.init_db()

_poller_thread = None
_stop_polling = threading.Event()


def fetch_cyd():
    try:
        resp = requests.get(
            f"{config.CYD_BASE_URL}/api/latest",
            timeout=10,
        )
        resp.raise_for_status()
        return resp.json()
    except Exception as e:
        app.logger.warning(f"CYD fetch failed: {e}")
        return None


def poller_loop():
    while not _stop_polling.is_set():
        session = db.get_active_session()
        if session:
            payload = fetch_cyd()
            if payload:
                db.insert_reading(session["id"], payload)
        time.sleep(config.POLL_INTERVAL)


def start_poller():
    global _poller_thread
    if _poller_thread is None or not _poller_thread.is_alive():
        _stop_polling.clear()
        _poller_thread = threading.Thread(target=poller_loop, daemon=True)
        _poller_thread.start()


@app.route("/")
def index():
    return render_template("index.html")


@app.route("/api/status")
def api_status():
    """Backend status plus current CYD reading."""
    session = db.get_active_session()
    latest = db.get_latest_reading(session["id"]) if session else None
    latest_proxy = fetch_cyd()
    return jsonify({
        "ok": True,
        "cyd_base_url": config.CYD_BASE_URL,
        "poll_interval": config.POLL_INTERVAL,
        "active_session": session,
        "latest_reading": latest_proxy or latest,
    })


@app.route("/api/cyd/latest")
def api_cyd_latest():
    """Proxy to the CYD's own /api/latest."""
    payload = fetch_cyd()
    if payload is None:
        return jsonify({"ok": False, "error": "Unable to reach CYD"}), 502
    return jsonify(payload)


@app.route("/api/sessions", methods=["GET", "POST"])
def sessions():
    if request.method == "POST":
        data = request.get_json() or {}
        name = data.get("name", f"Cook {datetime.now(timezone.utc).isoformat()[:19]}")
        notes = data.get("notes", "")
        # End any currently active session first.
        active = db.get_active_session()
        if active:
            db.end_session(active["id"])
        session_id = db.create_session(name, notes)
        return jsonify({"ok": True, "session_id": session_id}), 201

    with db.get_connection() as conn:
        rows = conn.execute(
            "SELECT * FROM sessions ORDER BY started_at DESC"
        ).fetchall()
        return jsonify([dict(row) for row in rows])


@app.route("/api/sessions/<int:session_id>", methods=["GET", "PUT", "DELETE"])
def session_detail(session_id):
    if request.method == "GET":
        with db.get_connection() as conn:
            row = conn.execute(
                "SELECT * FROM sessions WHERE id = ?", (session_id,)
            ).fetchone()
            if not row:
                return jsonify({"ok": False, "error": "Session not found"}), 404
            return jsonify(dict(row))

    if request.method == "PUT":
        data = request.get_json() or {}
        if "notes" in data:
            db.update_session_notes(session_id, data["notes"])
        if data.get("end"):
            db.end_session(session_id)
        return jsonify({"ok": True})

    if request.method == "DELETE":
        with db.get_connection() as conn:
            conn.execute("DELETE FROM readings WHERE session_id = ?", (session_id,))
            conn.execute("DELETE FROM setpoints WHERE session_id = ?", (session_id,))
            conn.execute("DELETE FROM sessions WHERE id = ?", (session_id,))
            conn.commit()
        return jsonify({"ok": True})


@app.route("/api/readings/<int:session_id>")
def readings(session_id):
    minutes = request.args.get("minutes", config.DEFAULT_CHART_MINUTES, type=int)
    probe = request.args.get("probe", type=int)
    data = db.get_readings(session_id, minutes=minutes, probe_number=probe)
    return jsonify(data)


@app.route("/api/setpoints/<int:session_id>", methods=["GET", "POST"])
def setpoints(session_id):
    if request.method == "POST":
        data = request.get_json() or {}
        probe_number = data.get("probe_number")
        label = data.get("label", "")
        target_temp = data.get("target_temp")
        if probe_number is None or target_temp is None:
            return jsonify({"ok": False, "error": "probe_number and target_temp required"}), 422
        db.set_setpoint(session_id, probe_number, label, float(target_temp))
        return jsonify({"ok": True})

    return jsonify(db.get_setpoints(session_id))


if __name__ == "__main__":
    start_poller()
    print(f"Starting server on http://0.0.0.0:5000")
    print(f"Polling CYD at {config.CYD_BASE_URL} every {config.POLL_INTERVAL}s")
    serve(app, host="0.0.0.0", port=5000)
