#!/usr/bin/env node
/**
 * Minimal Care Device Agent.
 *
 * Demo mode: FAKE_READING=1 posts stub vitals (no serial port).
 * Production: replace readSerialStub() with a vendor/serial/BLE reader.
 */

const fs = require('fs');
const path = require('path');

function loadEnvFile() {
  const envPath = path.join(__dirname, '.env');
  if (!fs.existsSync(envPath)) return;
  for (const line of fs.readFileSync(envPath, 'utf8').split('\n')) {
    const trimmed = line.trim();
    if (!trimmed || trimmed.startsWith('#')) continue;
    const eq = trimmed.indexOf('=');
    if (eq <= 0) continue;
    const key = trimmed.slice(0, eq).trim();
    let val = trimmed.slice(eq + 1).trim();
    if ((val.startsWith('"') && val.endsWith('"')) || (val.startsWith("'") && val.endsWith("'"))) {
      val = val.slice(1, -1);
    }
    if (process.env[key] === undefined) process.env[key] = val;
  }
}

loadEnvFile();

const CARE_URL = (process.env.CARE_URL || '').replace(/\/$/, '');
const DEVICE_TOKEN = process.env.DEVICE_TOKEN || '';
const CONSULTATION_UUID = process.env.CONSULTATION_UUID || '';
const FAKE_READING = ['1', 'true', 'yes'].includes(String(process.env.FAKE_READING || '').toLowerCase());
const INTERVAL_SECONDS = Math.max(5, Number(process.env.INTERVAL_SECONDS || 30));
const AGENT_VERSION = process.env.AGENT_VERSION || '0.1.0';
const AGENT_HOSTNAME = process.env.AGENT_HOSTNAME || require('os').hostname();
const ONCE = process.argv.includes('--once');

if (!CARE_URL || !DEVICE_TOKEN) {
  console.error('Set CARE_URL and DEVICE_TOKEN (see .env.example).');
  process.exit(1);
}

async function api(pathname, body) {
  const res = await fetch(`${CARE_URL}/api/v1/device-agent${pathname}`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      Accept: 'application/json',
      'X-Care-Device-Token': DEVICE_TOKEN,
    },
    body: JSON.stringify(body),
  });
  const text = await res.text();
  let data;
  try {
    data = text ? JSON.parse(text) : {};
  } catch {
    data = { raw: text };
  }
  if (!res.ok) {
    const err = new Error(data.message || data.error || `HTTP ${res.status}`);
    err.status = res.status;
    err.data = data;
    throw err;
  }
  return data;
}

/** Stub serial read — replace with real driver for production. */
function readSerialStub() {
  if (!FAKE_READING) return null;
  const base = 36.5 + Math.random() * 0.8;
  return {
    vitals: {
      temperature: Math.round(base * 10) / 10,
      pulse: 60 + Math.floor(Math.random() * 20),
      spo2: 96 + Math.floor(Math.random() * 4),
    },
    raw: {
      driver: 'fake',
      captured_at: new Date().toISOString(),
    },
  };
}

async function tick() {
  const hb = await api('/heartbeat', {
    agent_version: AGENT_VERSION,
    hostname: AGENT_HOSTNAME,
  });
  console.log(`[heartbeat] status=${hb.status} last_seen=${hb.last_seen_at}`);

  const reading = readSerialStub();
  if (reading && CONSULTATION_UUID) {
    const result = await api('/vitals', {
      consultation_uuid: CONSULTATION_UUID,
      vitals: reading.vitals,
      raw: reading.raw,
    });
    console.log(`[vitals] id=${result.vital_sign_id} temp=${reading.vitals.temperature}`);
  } else if (reading && !CONSULTATION_UUID) {
    console.log('[vitals] skipped — set CONSULTATION_UUID to post fake readings');
  }
}

async function main() {
  console.log(`Care Device Agent → ${CARE_URL} (fake=${FAKE_READING ? 'on' : 'off'})`);
  await tick();
  if (ONCE) return;
  setInterval(() => {
    tick().catch((err) => console.error('[error]', err.message, err.data || ''));
  }, INTERVAL_SECONDS * 1000);
}

main().catch((err) => {
  console.error(err.message, err.data || '');
  process.exit(1);
});
