package com.axelor.apps.hr.job;

import com.axelor.app.AppSettings;
import com.axelor.apps.hr.db.repo.CheckInOutRepository;
import com.axelor.exception.service.TraceBackService;
import com.axelor.inject.Beans;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.time.LocalDate;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.SchedulerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FetchCheckInOutJob implements Job {

  private final Logger log = LoggerFactory.getLogger(FetchCheckInOutJob.class);
  private final String pythonScriptDir = AppSettings.get().get("services.dir");

  @Override
  public void execute(JobExecutionContext context) throws JobExecutionException {

    if (isRunning(context)) {
      return;
    }

    if (pythonScriptDir == null || pythonScriptDir.isEmpty()) {
      log.error("Python script path is not configured in AppSettings.");
      return;
    }

    try {

      LocalDate today = LocalDate.now();

      // Fetch the CheckInOut list from the repository where the date_attendance is today
      int lenCheckInOutList =
          Beans.get(CheckInOutRepository.class)
              .all()
              .filter("self.date_attendance = :today")
              .bind("today", today)
              .fetch()
              .size();

      // Define the command to run the Python script with the correct path (V3)
      String[] args = {
        "python", pythonScriptDir + "\\Scrape\\main2.py", String.valueOf(lenCheckInOutList)
      };

      // Execute the command
      Process p = Runtime.getRuntime().exec(args);

      // Capture the output stream (standard output)
      BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
      String line;
      while ((line = reader.readLine()) != null) {
        log.info("Python script (Check In Out) output: " + line);
      }

      // Capture the error stream (standard error)
      BufferedReader errorReader = new BufferedReader(new InputStreamReader(p.getErrorStream()));
      while ((line = errorReader.readLine()) != null) {
        log.error("Python script (Check In Out) error: " + line);
      }

      // Wait for the process to complete and check the exit value
      int exitCode = p.waitFor();

      // Check if the process ran successfully
      if (exitCode == 0) {
        log.info("Python script executed successfully (Check In Out).");
      } else {
        log.error("Python script execution (Check In Out) failed with exit code: " + exitCode);
      }
    } catch (IOException e) {
      // Check if the file is not found based on the message or error code
      if (e.getMessage().contains("The system cannot find the file specified")) {
        log.error("Python script file (Check In Out) not found: " + e.getMessage());
      } else {
        log.error("An error occurred while executing the Python script (Check In Out).", e);
      }
      TraceBackService.trace(e);
    } catch (InterruptedException e) {
      // Handle any interruption errors
      log.error("Python script (Check In Out) execution interrupted.", e);
      Thread.currentThread().interrupt();
    }
  }

  private boolean isRunning(JobExecutionContext context) {
    try {
      return context
          .getScheduler()
          .getCurrentlyExecutingJobs()
          .stream()
          .anyMatch(
              j ->
                  j.getTrigger().equals(context.getTrigger())
                      && !j.getFireInstanceId().equals(context.getFireInstanceId()));
    } catch (SchedulerException e) {
      return false;
    }
  }
}
