'use strict';

const MAX_RECENT_ERRORS = 10;

// Keys written to the settings table for cross-restart persistence
const DB_KEY = {
  workerLastRun:  '_worker_last_run_at',
  workerNextRun:  '_worker_next_run_at',
  workerError:    '_worker_last_error',
  workerStarted:  '_worker_started_at',
};

const state = {
  worker: {
    enabled:     false,
    running:     false,
    started_at:  null,
    last_run_at: null,
    next_run_at: null,
    last_error:  null,
  },
  notifications: {
    last_test_at: null,
    last_error:   null,
  },
  recentErrors: [],
};

// Seed from DB on first load so status survives container restarts.
// Wrapped in try/catch — DB may not be ready at require-time in tests.
function seedFromDb() {
  try {
    const { getSetting } = require('../db/database');
    state.worker.last_run_at = getSetting(DB_KEY.workerLastRun) || null;
    state.worker.next_run_at = getSetting(DB_KEY.workerNextRun) || null;
    state.worker.last_error  = getSetting(DB_KEY.workerError)   || null;
    state.worker.started_at  = getSetting(DB_KEY.workerStarted) || null;
    if (state.worker.last_run_at) state.worker.enabled = true;
  } catch { /* DB not ready — will be populated when workers run */ }
}
seedFromDb();

function dbSet(key, value) {
  try {
    const { setSetting } = require('../db/database');
    setSetting(key, value == null ? '' : String(value));
  } catch { /* non-fatal */ }
}

function toMessage(error) {
  if (!error) return null;
  if (typeof error === 'string') return error;
  return error.message || String(error);
}

function recordError(source, error) {
  const message = toMessage(error);
  if (!message) return;
  state.recentErrors.unshift({ timestamp: new Date().toISOString(), source, message });
  state.recentErrors = state.recentErrors.slice(0, MAX_RECENT_ERRORS);
}

function markWorkerStarted(nextRunAt = null) {
  const now = new Date().toISOString();
  state.worker.enabled    = true;
  state.worker.running    = true;
  state.worker.started_at = state.worker.started_at || now;
  state.worker.next_run_at = nextRunAt;
  dbSet(DB_KEY.workerStarted, state.worker.started_at);
  if (nextRunAt) dbSet(DB_KEY.workerNextRun, nextRunAt);
}

function markWorkerSuccess(nextRunAt = null) {
  const now = new Date().toISOString();
  state.worker.running     = false;
  state.worker.last_run_at = now;
  state.worker.last_error  = null;
  if (nextRunAt !== undefined) state.worker.next_run_at = nextRunAt;
  dbSet(DB_KEY.workerLastRun, now);
  dbSet(DB_KEY.workerError, '');
  if (nextRunAt) dbSet(DB_KEY.workerNextRun, nextRunAt);
}

function markWorkerError(error, nextRunAt = null) {
  const now = new Date().toISOString();
  state.worker.running     = false;
  state.worker.last_run_at = now;
  state.worker.last_error  = toMessage(error);
  if (nextRunAt !== undefined) state.worker.next_run_at = nextRunAt;
  dbSet(DB_KEY.workerLastRun, now);
  dbSet(DB_KEY.workerError, state.worker.last_error || '');
  if (nextRunAt) dbSet(DB_KEY.workerNextRun, nextRunAt);
  recordError('Daily Worker', error);
}

function markNotificationTestSuccess() {
  state.notifications.last_test_at = new Date().toISOString();
  state.notifications.last_error   = null;
}

function markNotificationError(error) {
  state.notifications.last_error = toMessage(error);
  recordError('Notifications', error);
}

function markNotificationSuccess() {
  state.notifications.last_error = null;
}

function getStatusRuntime() {
  return {
    worker:       { ...state.worker },
    notifications: { ...state.notifications },
    recentErrors: [...state.recentErrors],
  };
}

module.exports = {
  getStatusRuntime,
  markNotificationError,
  markNotificationSuccess,
  markNotificationTestSuccess,
  markWorkerError,
  markWorkerStarted,
  markWorkerSuccess,
  recordError,
};
