/*
 * Axelor Business Solutions
 *
 * Copyright (C) 2019 Axelor (<http://axelor.com>).
 *
 * This program is free software: you can redistribute it and/or  modify
 * it under the terms of the GNU Affero General Public License, version 3,
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.axelor.apps.hr.web;

import com.axelor.app.AppSettings;
import com.axelor.apps.ReportFactory;
import com.axelor.apps.base.db.Partner;
import com.axelor.apps.hr.db.DPAE;
import com.axelor.apps.hr.db.Employee;
import com.axelor.apps.hr.db.Granding;
import com.axelor.apps.hr.db.repo.EmployeeRepository;
import com.axelor.apps.hr.db.repo.GrandingRepository;
import com.axelor.apps.hr.report.IReport;
import com.axelor.apps.hr.service.employee.EmployeeService;
import com.axelor.apps.report.engine.ReportSettings;
import com.axelor.auth.AuthUtils;
import com.axelor.auth.db.User;
import com.axelor.exception.AxelorException;
import com.axelor.exception.service.TraceBackService;
import com.axelor.i18n.I18n;
import com.axelor.inject.Beans;
import com.axelor.meta.schema.actions.ActionView;
import com.axelor.meta.schema.actions.ActionView.ActionViewBuilder;
import com.axelor.rpc.ActionRequest;
import com.axelor.rpc.ActionResponse;
import com.google.inject.Singleton;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.invoke.MethodHandles;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import wslite.json.JSONException;
import wslite.json.JSONObject;

@Singleton
public class EmployeeController {

  private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
  private final String pythonScriptDir = AppSettings.get().get("services.dir");

  public void showAnnualReport(ActionRequest request, ActionResponse response)
      throws JSONException, NumberFormatException, AxelorException {

    String employeeId = request.getContext().get("_id").toString();
    String year = request.getContext().get("year").toString();
    int yearId = new JSONObject(year).getInt("id");
    String yearName = new JSONObject(year).getString("name");
    User user = AuthUtils.getUser();

    String name =
        I18n.get("Annual expenses report") + " :  " + user.getFullName() + " (" + yearName + ")";

    String fileLink =
        ReportFactory.createReport(IReport.EMPLOYEE_ANNUAL_REPORT, name)
            .addParam("EmployeeId", Long.valueOf(employeeId))
            .addParam("YearId", Long.valueOf(yearId))
            .addParam("Locale", ReportSettings.getPrintingLocale(null))
            .toAttach(Beans.get(EmployeeRepository.class).find(Long.valueOf(employeeId)))
            .generate()
            .getFileLink();

    response.setView(ActionView.define(name).add("html", fileLink).map());

    response.setCanClose(true);
  }

  public void setEmployeeSocialNetworkUrl(ActionRequest request, ActionResponse response) {

    Employee employee = request.getContext().asType(Employee.class);
    if (employee.getContactPartner() != null) {
      Map<String, String> urlMap =
          Beans.get(EmployeeService.class)
              .getSocialNetworkUrl(
                  employee.getContactPartner().getName(),
                  employee.getContactPartner().getFirstName());
      response.setAttr("contactPartner.facebookLabel", "title", urlMap.get("facebook"));
      response.setAttr("contactPartner.twitterLabel", "title", urlMap.get("twitter"));
      response.setAttr("contactPartner.linkedinLabel", "title", urlMap.get("linkedin"));
      response.setAttr("contactPartner.youtubeLabel", "title", urlMap.get("youtube"));
    }
  }

  public void setContactSocialNetworkUrl(ActionRequest request, ActionResponse response) {

    Partner partnerContact = request.getContext().asType(Partner.class);
    Map<String, String> urlMap =
        Beans.get(EmployeeService.class)
            .getSocialNetworkUrl(partnerContact.getName(), partnerContact.getFirstName());
    response.setAttr("facebookLabel", "title", urlMap.get("facebook"));
    response.setAttr("twitterLabel", "title", urlMap.get("twitter"));
    response.setAttr("linkedinLabel", "title", urlMap.get("linkedin"));
    response.setAttr("youtubeLabel", "title", urlMap.get("youtube"));
  }

  public void printEmployeePhonebook(ActionRequest request, ActionResponse response)
      throws AxelorException {

    User user = AuthUtils.getUser();

    String name = I18n.get("Employee PhoneBook");

    String fileLink =
        ReportFactory.createReport(IReport.EMPLOYEE_PHONEBOOK, name + "-${date}")
            .addParam("Locale", ReportSettings.getPrintingLocale(null))
            .addParam("UserId", user.getId())
            .generate()
            .getFileLink();

    LOG.debug("Printing " + name);

    response.setView(ActionView.define(name).add("html", fileLink).map());
  }

  public void generateNewDPAE(ActionRequest request, ActionResponse response) {
    Employee employee = request.getContext().asType(Employee.class);
    employee = Beans.get(EmployeeRepository.class).find(employee.getId());

    try {
      Long dpaeId = Beans.get(EmployeeService.class).generateNewDPAE(employee);

      ActionViewBuilder builder =
          ActionView.define(I18n.get("DPAE"))
              .model(DPAE.class.getName())
              .add("grid", "dpae-grid")
              .add("form", "dpae-form")
              .context("_showRecord", dpaeId);
      response.setView(builder.map());
    } catch (AxelorException e) {
      TraceBackService.trace(response, e);
    }

    response.setReload(true);
  }

  public void enrollEmployee(ActionRequest request, ActionResponse response) {
    Long employeeId = (Long) request.getContext().asType(Employee.class).getId();
    Employee employee = Beans.get(EmployeeRepository.class).find(employeeId);

    Granding granding =
        Beans.get(GrandingRepository.class).all().filter("self.name = 'POINTEUSE-RDC'").fetchOne();

    String ipAdress = granding.getIpAdress();
    String code = granding.getCode().toString();

    if (employee.getIsEnrolled()) {
      response.setFlash("Employee is already enrolled.");
    } else {
      if (employee.getContactPartner() != null) {
        String employeeRegistrationNumber = employee.getRegistrationNumber();
        String employeeName = employee.getContactPartner().getName();

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

        try {

          String[] args = {
            "python",
            pythonScriptDir + "\\Attendance\\main.py",
            "--commande",
            "create",
            "--ip_address",
            ipAdress,
            "--code",
            code,
            "--user_id",
            employeeRegistrationNumber,
            "--name",
            employeeName
          };

          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 (Employee Enrolling) 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 (Employee Enrolling) 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 (Employee Enrolling).");
            Beans.get(EmployeeService.class).setEmployeeEnrolled(employee);
            response.setFlash("Employee enrolled successfully.");
          } else {
            LOG.error(
                "Python script execution (Employee Enrolling) failed with exit code: " + exitCode);
            response.setFlash("Failed to enroll the Employee.");
          }

        } 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 (Employee Enrolling) not found: " + e.getMessage());
          } else {
            LOG.error(
                "An error occurred while executing the Python script (Employee Enrolling).", e);
          }
          response.setFlash("Failed to enroll the Employee.");
          TraceBackService.trace(e);
        } catch (InterruptedException e) {
          // Handle any interruption errors
          response.setFlash("Failed to enroll the Employee.");
          LOG.error("Python script (Employee Enrolling) execution interrupted.", e);
          Thread.currentThread().interrupt();
        }
      }
    }
  }

  public void setEmployeeConfig(ActionRequest request, ActionResponse response) {

    List<Long> employeeIds = (List<Long>) request.getContext().get("_ids");
    System.out.println("****************");
    System.out.println(employeeIds);
    System.out.println("****************");
    Integer configSelect = (Integer) request.getContext().get("configSelect");

    if (employeeIds == null || employeeIds.isEmpty()) {
      response.setFlash("You haven't selected any Employee.");
    }
    try {
      if (!employeeIds.isEmpty()) {
        Beans.get(EmployeeService.class).massUpdateEmployeeConfig(employeeIds, configSelect, true);
        response.setReload(true);
      }
    } catch (Exception e) {
      TraceBackService.trace(response, e);
    }
  }

  public void unSetEmployeeConfig(ActionRequest request, ActionResponse response) {

    List<Long> employeeIds = (List<Long>) request.getContext().get("_ids");
    System.out.println("****************");
    System.out.println(employeeIds);
    System.out.println("****************");
    Integer configSelect = (Integer) request.getContext().get("configSelect");

    if (employeeIds == null || employeeIds.isEmpty()) {
      response.setFlash("You haven't selected any Employee.");
    }
    try {
      if (!employeeIds.isEmpty()) {
        Beans.get(EmployeeService.class).massUpdateEmployeeConfig(employeeIds, configSelect, false);
        response.setReload(true);
      }

    } catch (Exception e) {
      TraceBackService.trace(response, e);
    }
  }
}
