import { eventBus } from '../lib/eventBus.js';
import { saveState } from './SaveState.js';

const DEFAULT_DURATION_SECONDS = Number(process.env.SHIFT_DURATION_SECONDS ?? 2400);
const DEFAULT_TICK_SECONDS = Number(process.env.SHIFT_TICK_SECONDS ?? 30);

export class ShiftTimer {
  constructor({
    durationSeconds = DEFAULT_DURATION_SECONDS,
    tickSeconds = DEFAULT_TICK_SECONDS,
    save = saveState,
    now = () => Date.now()
  } = {}) {
    this.durationSeconds = durationSeconds;
    this.tickSeconds = tickSeconds;
    this.save = save;
    this.now = now;
    this._interval = null;
    this._endedShiftStartedAt = null;
  }

  start(state = this.save.get()) {
    this.stop();

    if (!state?.shift_started_at) {
      this.save.set({ shift_started_at: new Date(this.now()).toISOString() });
    }

    this.tick();
    this._interval = setInterval(() => {
      this.tick();
    }, this.tickSeconds * 1000).unref();
  }

  stop() {
    if (this._interval) {
      clearInterval(this._interval);
      this._interval = null;
    }
  }

  tick() {
    const snapshot = this.getSnapshot();
    eventBus.emit('shift:tick', snapshot);
    if (snapshot.remainingSeconds === 0 && snapshot.startedAt !== this._endedShiftStartedAt) {
      this._endedShiftStartedAt = snapshot.startedAt;
      eventBus.emit('shift:ended', snapshot);
    } else if (snapshot.remainingSeconds > 0 && snapshot.startedAt !== this._endedShiftStartedAt) {
      this._endedShiftStartedAt = null;
    }
    return snapshot;
  }

  getSnapshot(state = this.save.get()) {
    const shiftStartedAt = state?.shift_started_at
      ? new Date(state.shift_started_at).getTime()
      : this.now();

    const elapsedSeconds = Math.max(0, Math.floor((this.now() - shiftStartedAt) / 1000));
    const remainingSeconds = Math.max(0, this.durationSeconds - elapsedSeconds);

    return {
      durationSeconds: this.durationSeconds,
      elapsedSeconds,
      remainingSeconds,
      startedAt: state?.shift_started_at ?? new Date(shiftStartedAt).toISOString()
    };
  }
}

export const shiftTimer = new ShiftTimer();
