package tech.picnic.errorprone.bugpatterns;

import com.google.errorprone.CompilationTestHelper;
import org.junit.jupiter.api.Test;

final class TimeZoneUsageTest {
  @Test
  void identification() {
    CompilationTestHelper.newInstance(TimeZoneUsage.class, getClass())
        .addSourceLines(
            "A.java",
            "import static java.time.ZoneOffset.UTC;",
            "",
            "import java.time.Clock;",
            "import java.time.Duration;",
            "import java.time.Instant;",
            "import java.time.LocalDate;",
            "import java.time.LocalDateTime;",
            "import java.time.LocalTime;",
            "import java.time.OffsetDateTime;",
            "import java.time.OffsetTime;",
            "import java.time.ZoneId;",
            "import java.time.ZonedDateTime;",
            "import reactor.core.publisher.Mono;",
            "",
            "class A {",
            "  void m() {",
            "    Clock clock = Clock.fixed(Instant.EPOCH, UTC);",
            "    clock.instant();",
            "    clock.millis();",
            "    Clock.offset(clock, Duration.ZERO);",
            "    Clock.tick(clock, Duration.ZERO);",
            "",
            "    // BUG: Diagnostic contains:",
            "    clock.getZone();",
            "    // BUG: Diagnostic contains:",
            "    Mono.fromSupplier(clock::getZone);",
            "    // BUG: Diagnostic contains:",
            "    clock.withZone(UTC);",
            "    // BUG: Diagnostic contains:",
            "    Mono.<ZoneId>empty().map(clock::withZone);",
            "    // BUG: Diagnostic contains:",
            "    Clock.system(UTC);",
            "    // BUG: Diagnostic contains:",
            "    Mono.<ZoneId>empty().map(Clock::system);",
            "    // BUG: Diagnostic contains:",
            "    Clock.systemDefaultZone();",
            "    // BUG: Diagnostic contains:",
            "    Mono.fromSupplier(Clock::systemDefaultZone);",
            "    // BUG: Diagnostic contains:",
            "    Clock.systemUTC();",
            "    // BUG: Diagnostic contains:",
            "    Mono.fromSupplier(Clock::systemUTC);",
            "    // BUG: Diagnostic contains:",
            "    Clock.tickMillis(UTC);",
            "    // BUG: Diagnostic contains:",
            "    Mono.<ZoneId>empty().map(Clock::tickMillis);",
            "    // BUG: Diagnostic contains:",
            "    Clock.tickMinutes(UTC);",
            "    // BUG: Diagnostic contains:",
            "    Mono.<ZoneId>empty().map(Clock::tickMinutes);",
            "    // BUG: Diagnostic contains:",
            "    Clock.tickSeconds(UTC);",
            "    // BUG: Diagnostic contains:",
            "    Mono.<ZoneId>empty().map(Clock::tickSeconds);",
            "",
            "    Instant.now(clock);",
            "    Mono.<Clock>empty().map(Instant::now);",
            "    // BUG: Diagnostic contains:",
            "    Instant.now();",
            "    // BUG: Diagnostic contains:",
            "    Mono.fromSupplier(Instant::now);",
            "",
            "    // BUG: Diagnostic contains:",
            "    LocalDate.now();",
            "    // BUG: Diagnostic contains:",
            "    Mono.fromSupplier(LocalDate::now);",
            "    // BUG: Diagnostic contains:",
            "    LocalDate.now(clock);",
            "    // BUG: Diagnostic contains:",
            "    Mono.<Clock>empty().map(LocalDate::now);",
            "    // BUG: Diagnostic contains:",
            "    LocalDate.now(UTC);",
            "    // BUG: Diagnostic contains:",
            "    Mono.<ZoneId>empty().map(LocalDate::now);",
            "",
            "    // BUG: Diagnostic contains:",
            "    LocalDateTime.now();",
            "    // BUG: Diagnostic contains:",
            "    Mono.fromSupplier(LocalDateTime::now);",
            "    // BUG: Diagnostic contains:",
            "    LocalDateTime.now(clock);",
            "    // BUG: Diagnostic contains:",
            "    Mono.<Clock>empty().map(LocalDateTime::now);",
            "    // BUG: Diagnostic contains:",
            "    LocalDateTime.now(UTC);",
            "    // BUG: Diagnostic contains:",
            "    Mono.<ZoneId>empty().map(LocalDateTime::now);",
            "",
            "    // BUG: Diagnostic contains:",
            "    LocalTime.now();",
            "    // BUG: Diagnostic contains:",
            "    Mono.fromSupplier(LocalTime::now);",
            "    // BUG: Diagnostic contains:",
            "    LocalTime.now(clock);",
            "    // BUG: Diagnostic contains:",
            "    Mono.<Clock>empty().map(LocalTime::now);",
            "    // BUG: Diagnostic contains:",
            "    LocalTime.now(UTC);",
            "    // BUG: Diagnostic contains:",
            "    Mono.<ZoneId>empty().map(LocalTime::now);",
            "",
            "    // BUG: Diagnostic contains:",
            "    OffsetDateTime.now();",
            "    // BUG: Diagnostic contains:",
            "    Mono.fromSupplier(OffsetDateTime::now);",
            "    // BUG: Diagnostic contains:",
            "    OffsetDateTime.now(clock);",
            "    // BUG: Diagnostic contains:",
            "    Mono.<Clock>empty().map(OffsetDateTime::now);",
            "    // BUG: Diagnostic contains:",
            "    OffsetDateTime.now(UTC);",
            "    // BUG: Diagnostic contains:",
            "    Mono.<ZoneId>empty().map(OffsetDateTime::now);",
            "",
            "    // BUG: Diagnostic contains:",
            "    OffsetTime.now();",
            "    // BUG: Diagnostic contains:",
            "    Mono.fromSupplier(OffsetTime::now);",
            "    // BUG: Diagnostic contains:",
            "    OffsetTime.now(clock);",
            "    // BUG: Diagnostic contains:",
            "    Mono.<Clock>empty().map(OffsetTime::now);",
            "    // BUG: Diagnostic contains:",
            "    OffsetTime.now(UTC);",
            "    // BUG: Diagnostic contains:",
            "    Mono.<ZoneId>empty().map(OffsetTime::now);",
            "",
            "    // BUG: Diagnostic contains:",
            "    ZonedDateTime.now();",
            "    // BUG: Diagnostic contains:",
            "    Mono.fromSupplier(ZonedDateTime::now);",
            "    // BUG: Diagnostic contains:",
            "    ZonedDateTime.now(clock);",
            "    // BUG: Diagnostic contains:",
            "    Mono.<Clock>empty().map(ZonedDateTime::now);",
            "    // BUG: Diagnostic contains:",
            "    ZonedDateTime.now(UTC);",
            "    // BUG: Diagnostic contains:",
            "    Mono.<ZoneId>empty().map(ZonedDateTime::now);",
            "  }",
            "",
            "  abstract class ForwardingClock extends Clock {",
            "    private final Clock clock;",
            "",
            "    ForwardingClock(Clock clock) {",
            "      this.clock = clock;",
            "    }",
            "",
            "    @Override",
            "    public ZoneId getZone() {",
            "      return clock.getZone();",
            "    }",
            "",
            "    @Override",
            "    public Clock withZone(ZoneId zone) {",
            "      return clock.withZone(zone);",
            "    }",
            "  }",
            "}")
        .doTest();
  }
}
