package com.airlock.iam.servicecontainer.app.infrastructure.webapp;

import com.airlock.iam.servicecontainer.app.application.configuration.Server;
import com.airlock.iam.servicecontainer.app.application.configuration.Service;
import com.airlock.iam.servicecontainer.app.application.configuration.TaskSchedulerService;
import com.google.common.annotations.VisibleForTesting;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.lang3.StringUtils;

public class StartTaskServlet extends HttpServlet {
   private static final List<String> ALLOWED_HOSTS = new ArrayList<>(Arrays.asList("localhost", "127.0.0.1"));

   protected void doGet(HttpServletRequest request, HttpServletResponse response) {
      if (!isRequestValid(request)) {
         response.setStatus(403);
      } else {
         boolean startResult = this.startTask(request);
         response.setStatus(startResult ? 200 : 404);
      }
   }

   private boolean startTask(HttpServletRequest request) {
      String taskName = request.getParameter("task");
      if (StringUtils.isNotBlank(taskName)) {
         for (Service service : this.getServer().getServices()) {
            if (service instanceof TaskSchedulerService) {
               boolean startResult = ((TaskSchedulerService)service).executeTask(taskName);
               if (startResult) {
                  return true;
               }
            }
         }
      }

      return false;
   }

   private static boolean isRequestValid(HttpServletRequest request) {
      return ALLOWED_HOSTS.contains(request.getRemoteHost()) || isFromLoopbackInterface(request);
   }

   private static boolean isFromLoopbackInterface(HttpServletRequest request) {
      try {
         return Arrays.stream(InetAddress.getAllByName(request.getRemoteHost())).anyMatch(InetAddress::isLoopbackAddress);
      } catch (UnknownHostException e) {
         return false;
      }
   }

   @VisibleForTesting
   Server getServer() {
      return Server.get();
   }
}
