package com.timgroup.eventsubscription.healthcheck;

import java.time.Clock;
import java.time.Duration;
import java.time.Instant;

import com.timgroup.eventstore.api.Position;
import com.timgroup.eventsubscription.ChaserListener;
import com.timgroup.tucker.info.Component;
import com.timgroup.tucker.info.Report;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static com.timgroup.tucker.info.Status.CRITICAL;
import static com.timgroup.tucker.info.Status.INFO;
import static com.timgroup.tucker.info.Status.OK;
import static com.timgroup.tucker.info.Status.WARNING;
import static java.lang.String.format;

public class ChaserHealth extends Component implements ChaserListener {
    private static final Logger LOG = LoggerFactory.getLogger(ChaserHealth.class);
    private final Clock clock;
    private volatile Instant lastPollTimestamp;
    private volatile Position currentPosition;

    public ChaserHealth(String name, Clock clock) {
        super("event-store-chaser-" + name, "Eventstore chaser health (" + name + ")");
        this.clock = clock;
    }

    @Override
    public Report getReport() {
        if (lastPollTimestamp != null) {
            Instant timestamp = lastPollTimestamp;
            long seconds = Duration.between(timestamp, Instant.now(clock)).getSeconds();
            if (seconds > 30) {
                return new Report(CRITICAL, format("potentially stale. Last up-to-date at at %s. (%s seconds ago).", timestamp, seconds));
            } else if (seconds > 5) {
                return new Report(WARNING, format("potentially stale. Last up-to-date at at %s. (%s seconds ago).", timestamp, seconds));
            } else {
                return new Report(OK, format("up-to-date at at %s. (%s seconds ago). Current version: %s", timestamp, seconds, currentPosition));
            }
        }

        return new Report(INFO, "Awaiting initial catchup. Current version: " + currentPosition);
    }

    @Override
    public void transientFailure(Exception e) {
        LOG.warn("Failure chasing eventstream.", e);
    }

    @Override
    public void chaserReceived(Position position) {
        currentPosition = position;
    }

    @Override
    public void chaserUpToDate(Position position) {
        currentPosition = position;
        lastPollTimestamp = Instant.now(clock);
    }
}

@@ -772,16 +772,172 @@
 class);%0A
+    private static final Duration WARNING_THRESHOLD = Duration.ofSeconds(5);%0A    private static final Duration CRITICAL_THRESHOLD = Duration.ofSeconds(30);%0A
     priv
@@ -1288,61 +1288,59 @@
     
-if (lastPollTimestamp != null) %7B%0A            Instant 
+Instant timestamp = lastPollTimestamp;%0A        if (
 time
@@ -1349,53 +1349,48 @@
 amp 
+!
 = 
-lastPollTimestamp;%0A            long seconds
+null) %7B%0A            Duration duration
  = D
@@ -1439,21 +1439,8 @@
 ck))
-.getSeconds()
 ;%0A  
@@ -1457,19 +1457,49 @@
 if (
-seconds
+duration.compareTo(CRITICAL_THRESHOLD)
  %3E 
-3
 0) %7B
@@ -1596,32 +1596,24 @@
  at %25s. (%25s 
-seconds 
 ago).%22, time
@@ -1611,39 +1611,40 @@
 ).%22, timestamp, 
-seconds
+duration
 ));%0A            
@@ -1658,19 +1658,49 @@
 if (
-seconds %3E 5
+duration.compareTo(WARNING_THRESHOLD) %3E 0
 ) %7B%0A
@@ -1795,32 +1795,24 @@
  at %25s. (%25s 
-seconds 
 ago).%22, time
@@ -1818,23 +1818,24 @@
 estamp, 
-seconds
+duration
 ));%0A    
@@ -1926,16 +1926,8 @@
 (%25s 
-seconds 
 ago)
@@ -1965,15 +1965,16 @@
 mp, 
-seconds
+duration
 , cu

use duration rather than converting to seconds