// Copyright 2023 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.devtools.build.lib.starlarkdebug.server;

import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.Truth.assertThat;
import static java.util.Arrays.stream;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.junit.Assert.assertThrows;

import com.google.common.collect.ImmutableList;
import com.google.devtools.build.lib.actions.FileValue;
import com.google.devtools.build.lib.buildtool.BuildResult;
import com.google.devtools.build.lib.buildtool.util.BuildIntegrationTestCase;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventCollector;
import com.google.devtools.build.lib.events.EventKind;
import com.google.devtools.build.lib.runtime.BlazeRuntime;
import com.google.devtools.build.lib.starlarkdebug.module.StarlarkDebuggerModule;
import com.google.devtools.build.lib.starlarkdebugging.StarlarkDebuggingProtos.Breakpoint;
import com.google.devtools.build.lib.starlarkdebugging.StarlarkDebuggingProtos.DebugRequest;
import com.google.devtools.build.lib.starlarkdebugging.StarlarkDebuggingProtos.Location;
import com.google.devtools.build.lib.starlarkdebugging.StarlarkDebuggingProtos.SetBreakpointsRequest;
import com.google.devtools.build.lib.starlarkdebugging.StarlarkDebuggingProtos.StartDebuggingRequest;
import com.google.devtools.build.lib.testutil.MoreAsserts;
import com.google.devtools.build.lib.vfs.RootedPath;
import com.google.devtools.build.skyframe.QueryableGraph.Reason;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.io.IOException;
import java.net.InetAddress;
import java.time.Duration;
import java.util.Collection;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.regex.Pattern;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

@RunWith(JUnit4.class)
public class StarlarkDebugIntegrationTest extends BuildIntegrationTestCase {
  private static final AtomicInteger sequenceIds = new AtomicInteger(1);

  private final ExecutorService executor = Executors.newFixedThreadPool(1);
  private final Collection<Event> eventCollector = new ConcurrentLinkedQueue<>();

  @Override
  protected BlazeRuntime.Builder getRuntimeBuilder() throws Exception {
    return super.getRuntimeBuilder().addBlazeModule(new StarlarkDebuggerModule());
  }

  @Before
  public void setup() throws Exception {
    addOptions("--experimental_skylark_debug", "--experimental_skylark_debug_server_port=0");
    eventCollector.clear();
    events.addHandler(new EventCollector(EventKind.ALL_EVENTS, eventCollector));
  }

  @Test
  public void testAnalysisResetBlocksOnDebuggingStart() throws Exception {
    addOptions("--experimental_skylark_debug_reset_analysis");
    write("foo/BUILD", "genrule(name = 'foo', outs = ['foo.out'], cmd = 'touch $@')");

    // run async, otherwise this will just block on the result indefinitely
    CompletableFuture<BuildResult> resultCf =
        CompletableFuture.supplyAsync(
            () -> {
              try {
                return buildTarget(StarlarkDebugIntegrationTest::createClient, "//foo");
              } catch (Exception e) {
                throw new RuntimeException(e);
              }
            },
            Executors.newSingleThreadExecutor());

    TimeoutException unusedError =
        assertThrows(TimeoutException.class, () -> resultCf.get(10, SECONDS));
  }

  @Test
  public void testAnalysisResetWithNoBreakpoints() throws Exception {
    addOptions("--experimental_skylark_debug_reset_analysis");
    write("foo/BUILD", "genrule(name = 'foo', outs = ['foo.out'], cmd = 'touch $@')");

    BuildResult result = buildTarget(this::createClientAndSetBreakpoints, "//foo");

    assertThat(result).isNotNull();
    assertThat(result.getSuccessfulTargets()).hasSize(1);
    MoreAsserts.assertDoesNotContainEvent(eventCollector, "did not receive breakpoints");
    MoreAsserts.assertContainsEvent(eventCollector, "resetting analysis for: []");
  }

  @Test
  public void testAnalysisResetWithBreakpoint() throws Exception {
    addOptions("--experimental_skylark_debug_reset_analysis");
    write("foo/BUILD", "genrule(name = 'foo', outs = ['foo.out'], cmd = 'touch $@')");

    BuildResult result =
        buildTarget(debugPort -> createClientAndSetBreakpoints(debugPort, "foo/BUILD"), "//foo");

    MoreAsserts.assertContainsEvent(
        eventCollector, Pattern.compile("resetting analysis for: .*/foo/BUILD"));
    assertThat(result).isNotNull();
    assertThat(result.getSuccessfulTargets()).hasSize(1);
  }

  @Test
  public void testAnalysisResetWithBreakpointDeletesSkyframeFileNode() throws Exception {
    write("foo/BUILD", "genrule(name = 'foo', outs = ['foo.out'], cmd = 'touch $@')");

    // first build to populate skyframe
    BuildResult result =
        buildTarget(StarlarkDebugIntegrationTest::createClientAndStartDebugging, "//foo");
    assertThat(result).isNotNull();

    Set<String> deletedFiles = ConcurrentHashMap.newKeySet();
    injectListenerAtStartOfNextBuild(
        (key, type, order, context) -> {
          if (Objects.equals(key.functionName(), FileValue.FILE)
              && Objects.equals(context, Reason.INVALIDATION)) {
            deletedFiles.add(((RootedPath) key.argument()).getRootRelativePath().getPathString());
          }
        });
    addOptions("--experimental_skylark_debug_reset_analysis");

    // rebuild with non-existent breakpoint
    result =
        buildTarget(debugPort -> createClientAndSetBreakpoints(debugPort, "bar/BUILD"), "//foo");
    assertThat(result).isNotNull();
    assertThat(deletedFiles).isEmpty();

    // rebuild with breakpoint on build file
    result =
        buildTarget(debugPort -> createClientAndSetBreakpoints(debugPort, "foo/BUILD"), "//foo");
    assertThat(result).isNotNull();
    assertThat(deletedFiles).contains("foo/BUILD");
  }

  private BuildResult buildTarget(Consumer<Integer> clientSetup, String target) throws Exception {
    DebugServerTransport.onListenPortCallbackForTests =
        port -> {
          var unused = executor.submit(() -> clientSetup.accept(port));
        };
    return super.buildTarget(target);
  }

  @CanIgnoreReturnValue
  private static MockDebugClient createClient(int debugPort) {
    MockDebugClient client = new MockDebugClient();
    client.connect(InetAddress.getLoopbackAddress(), debugPort, Duration.ofSeconds(5));
    return client;
  }

  private static void startDebugging(MockDebugClient client) {
    try {
      client.sendRequestAndWaitForResponse(
          DebugRequest.newBuilder()
              .setSequenceNumber(sequenceIds.getAndIncrement())
              .setStartDebugging(StartDebuggingRequest.getDefaultInstance())
              .build());
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  private static void createClientAndStartDebugging(int debugPort) {
    MockDebugClient client = createClient(debugPort);
    startDebugging(client);
  }

  private void createClientAndSetBreakpoints(int debugPort, String... paths) {
    MockDebugClient client = createClient(debugPort);
    setBreakpoints(client, paths);
    startDebugging(client);
  }

  private void setBreakpoints(MockDebugClient client, String... paths) {
    ImmutableList<Breakpoint> breakpoints =
        stream(paths)
            .map(path -> getWorkspace().getRelative(path).getPathString())
            .map(
                path ->
                    Breakpoint.newBuilder()
                        .setLocation(Location.newBuilder().setPath(path).build())
                        .build())
            .collect(toImmutableList());
    try {
      client.sendRequestAndWaitForResponse(
          DebugRequest.newBuilder()
              .setSequenceNumber(sequenceIds.getAndIncrement())
              .setSetBreakpoints(
                  SetBreakpointsRequest.newBuilder().addAllBreakpoint(breakpoints).build())
              .build());
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }
}
