/* =====================================================================
   lib/live-status.js — Automatische TikTok-Live-Erkennung für den grünen
   Punkt auf der Startseite. 1:1 portiert aus dem Live-Status-Teil von
   cloudflare-worker/src/worker.js, D1 → better-sqlite3.

   Ein Cron-Auftrag (node-cron in index.js, ersetzt Cloudflares
   `scheduled()`) fragt jede Minute bei TikTok nach, ob @dogfather0804
   gerade sendet, und schreibt das Ergebnis in die Tabelle app_settings.

   Zwei Schlüssel:
     live_auto     – letzter ERFOLGREICH ermittelter Stand (wird bei einem
                     fehlgeschlagenen Abruf bewusst NICHT überschrieben,
                     damit ein TikTok-Aussetzer den Punkt nicht fälschlich
                     auf offline zieht)
     live_override – manueller Vorrang aus dem Postfach, mit Ablaufzeit.
                     Solange er gilt, schlägt er die Automatik.
   ===================================================================== */
import { db } from "../db.js";
import { json } from "./http.js";
import { logAction } from "./audit.js";
import { checkTikTokLive } from "./tiktok-live.js";

const DEFAULT_OVERRIDE_MINUTES = 180;

function readSetting(key) {
  const row = db.prepare(`SELECT value FROM app_settings WHERE key = ?`).get(key);
  if (!row || !row.value) return null;
  try {
    return JSON.parse(row.value);
  } catch {
    return null;
  }
}

function writeSetting(key, value) {
  db.prepare(
    `INSERT INTO app_settings (key, value, updated_at) VALUES (?, ?, ?)
     ON CONFLICT(key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at`
  ).run(key, JSON.stringify(value), new Date().toISOString());
}

/** Ermittelt den Stand, der nach außen gilt (Vorrang: manuell vor Automatik). */
function resolveLiveStatus() {
  const auto = readSetting("live_auto") || {};
  const override = readSetting("live_override");

  const overrideActive = override && override.until && new Date(override.until).getTime() > Date.now();

  if (overrideActive) {
    return {
      live: !!override.live,
      source: "manuell",
      updatedAt: override.setAt || null,
      overrideUntil: override.until,
      autoLive: auto.live ?? null,
      autoCheckedAt: auto.checkedAt || null,
      autoHealthy: auto.ok !== false,
    };
  }

  return {
    live: !!auto.live,
    source: "automatisch",
    updatedAt: auto.changedAt || auto.checkedAt || null,
    title: auto.title || null,
    autoLive: auto.live ?? null,
    autoCheckedAt: auto.checkedAt || null,
    autoHealthy: auto.ok !== false,
  };
}

export async function handleLiveStatusGet(req, res) {
  return json(res, { ok: true, ...resolveLiveStatus() });
}

/**
 * Manueller Eingriff aus dem Postfach.
 *   { live: true|false, minutes?: number }  → Vorrang setzen
 *   { auto: true }                          → Vorrang aufheben, Automatik übernimmt
 */
export async function handleLiveStatusSet(req, res, session) {
  if (!session?.isOwner) return json(res, { ok: false, error: "Nur Dogi darf den Live-Status ändern." }, 403);
  const body = req.body || {};

  if (body.auto === true) {
    db.prepare(`DELETE FROM app_settings WHERE key = 'live_override'`).run();
    logAction("owner", "live.override_cleared", null, null);
    return json(res, { ok: true, ...resolveLiveStatus() });
  }

  const minutes = Number.isFinite(body.minutes) ? Math.min(Math.max(body.minutes, 5), 1440) : DEFAULT_OVERRIDE_MINUTES;
  const now = new Date();
  writeSetting("live_override", {
    live: !!body.live,
    setAt: now.toISOString(),
    until: new Date(now.getTime() + minutes * 60_000).toISOString(),
  });
  logAction("owner", "live.override_set", null, { live: !!body.live, minutes });
  return json(res, { ok: true, ...resolveLiveStatus() });
}

/** Wird vom Cron-Auftrag aufgerufen (index.js) — fragt TikTok ab und schreibt das Ergebnis. */
export async function refreshLiveFromTikTok() {
  const username = process.env.TIKTOK_USERNAME || "dogfather0804";
  const result = await checkTikTokLive(username);
  const now = new Date().toISOString();

  if (!result.ok) {
    // Fehlgeschlagen: letzten guten Stand behalten, nur den Fehler vermerken.
    const previous = readSetting("live_auto") || {};
    writeSetting("live_auto", { ...previous, ok: false, lastError: result.reason, checkedAt: now });
    return { ok: false, reason: result.reason };
  }

  const previous = readSetting("live_auto") || {};
  const changed = previous.live !== result.live;

  writeSetting("live_auto", {
    ok: true,
    live: result.live,
    title: result.title,
    roomId: result.roomId,
    rawStatus: result.rawStatus,
    checkedAt: now,
    changedAt: changed ? now : previous.changedAt || now,
    lastError: null,
  });

  if (changed) {
    logAction("system", result.live ? "live.started" : "live.ended", null, { title: result.title });
  }
  return { ok: true, live: result.live, changed };
}
