'use strict';
// Lichtscènes: dag/nacht-sturing van WLED, Philips Hue en DMX via Art-Net.
// Gekoppeld aan de modelklok (of handmatig). Geen dependencies.
const http = require('http');
const dgram = require('dgram');

function httpReq(method, url, body) {
  try {
    const u = new URL(url);
    const data = body ? Buffer.from(JSON.stringify(body)) : null;
    const req = http.request(u, { method: method, timeout: 5000, headers: data ? { 'Content-Type': 'application/json', 'Content-Length': data.length } : {} }, (res) => { res.on('data', () => {}); res.on('end', () => {}); });
    req.on('error', () => {}); req.on('timeout', () => req.destroy());
    if (data) req.write(data); req.end();
  } catch (_) {}
}

// Art-Net OpOutput-pakket (DMX over UDP, poort 6454).
let artSeq = 0;
function artnet(host, universe, channels) {
  try {
    const sock = dgram.createSocket('udp4');
    const dmx = Buffer.alloc(512);
    for (let i = 0; i < channels.length && i < 512; i++) dmx[i] = Math.max(0, Math.min(255, channels[i] | 0));
    const len = 512;
    const head = Buffer.from([0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0x00, 0x00, 0x50, 0x00, 0x0e,
      (artSeq = (artSeq + 1) & 0xff), 0x00, universe & 0xff, (universe >> 8) & 0xff, (len >> 8) & 0xff, len & 0xff]);
    const pkt = Buffer.concat([head, dmx]);
    sock.send(pkt, 0, pkt.length, 6454, host, () => { try { sock.close(); } catch (_) {} });
  } catch (_) {}
}

function createLights(opts) {
  const log = opts.log || (() => {});
  let cfg = { devices: [], dayStart: 7 * 60, nightStart: 21 * 60 };
  let lastScene = null;

  function configure(c) { cfg = Object.assign({ devices: [], dayStart: 7 * 60, nightStart: 21 * 60 }, c || {}); }

  function applyDevice(d, scene) {
    const s = d[scene] || {};
    if (d.type === 'wled' && d.host) {
      // WLED JSON-API: {on, bri, seg:[{col:[[r,g,b]]}]}
      const payload = { on: s.on !== false, bri: s.bri == null ? 128 : s.bri };
      if (Array.isArray(s.rgb)) payload.seg = [{ col: [s.rgb] }];
      httpReq('POST', 'http://' + d.host + '/json/state', payload);
    } else if (d.type === 'hue' && d.host && d.token && d.light) {
      // Hue bridge: PUT /api/<token>/lights/<id>/state
      const payload = { on: s.on !== false };
      if (s.bri != null) payload.bri = Math.max(1, Math.min(254, s.bri));
      if (s.ct != null) payload.ct = s.ct;
      httpReq('PUT', 'http://' + d.host + '/api/' + d.token + '/lights/' + d.light + '/state', payload);
    } else if (d.type === 'artnet' && d.host) {
      artnet(d.host, d.universe || 0, Array.isArray(s.dmx) ? s.dmx : []);
    }
  }

  function applyScene(scene) {
    lastScene = scene;
    let n = 0;
    for (const d of (cfg.devices || [])) { applyDevice(d, scene); n++; }
    if (n) log('💡 Lichtscène "' + scene + '" toegepast op ' + n + ' apparaat/apparaten');
    return n;
  }

  // Op basis van de modelklok automatisch dag/nacht schakelen.
  function checkClock(modelMin) {
    if (!(cfg.devices || []).length) return;
    const day = modelMin >= cfg.dayStart && modelMin < cfg.nightStart;
    const want = day ? 'day' : 'night';
    if (want !== lastScene) applyScene(want);
  }

  return { configure, applyScene, checkClock, status: () => ({ devices: (cfg.devices || []).length, scene: lastScene }) };
}

module.exports = { createLights };
