/*
 * 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.base.web;

import com.axelor.app.AppSettings;
import com.axelor.apps.base.db.AppBase;
import com.axelor.apps.base.exceptions.IExceptionMessage;
import com.axelor.apps.base.service.CurrencyConversionService;
import com.axelor.apps.base.service.MapService;
import com.axelor.apps.base.service.administration.ExportDbObjectService;
import com.axelor.apps.base.service.app.AppBaseService;
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.CallMethod;
import com.axelor.meta.db.MetaFile;
import com.axelor.meta.schema.actions.ActionView;
import com.axelor.rpc.ActionRequest;
import com.axelor.rpc.ActionResponse;
import com.google.inject.Singleton;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.Socket;
import java.net.URL;
import wslite.json.JSONException;
import wslite.json.JSONObject;

@Singleton
public class AppBaseController {

  /** */
  private static final String localhost = "127.0.0.1";

  public void exportObjects(ActionRequest request, ActionResponse response) {
    MetaFile metaFile = Beans.get(ExportDbObjectService.class).exportObject();
    if (metaFile == null) {
      response.setFlash(I18n.get(IExceptionMessage.GENERAL_4));
    } else {
      response.setView(
          ActionView.define(I18n.get(IExceptionMessage.GENERAL_5))
              .model("com.axelor.meta.db.MetaFile")
              .add("form", "meta-files-form")
              .add("grid", "meta-files-grid")
              .param("forceEdit", "true")
              .context("_showRecord", metaFile.getId().toString())
              .map());
    }
  }

  public void checkMapApi(ActionRequest request, ActionResponse response) {
    try {
      AppBase appBase = request.getContext().asType(AppBase.class);
      Integer apiType = appBase.getMapApiSelect();

      if (apiType == 1) {
        Beans.get(MapService.class).testGMapService();
        response.setFlash(IExceptionMessage.GENERAL_6);
      }
    } catch (Exception e) {
      TraceBackService.trace(response, e);
    }
  }

  public void updateCurrencyConversion(ActionRequest request, ActionResponse response)
      throws AxelorException {
    Beans.get(CurrencyConversionService.class).updateCurrencyConverion();
    response.setReload(true);
  }

  public void applyApplicationMode(ActionRequest request, ActionResponse response) {
    String applicationMode = AppSettings.get().get("application.mode", "prod");
    if ("dev".equals(applicationMode)) {
      response.setAttr("mainPanel", "hidden", false);
    }
  }

  public void showCustomersOnMap(ActionRequest request, ActionResponse response) {
    try {
      response.setView(
          ActionView.define(I18n.get("Customers"))
              .add("html", Beans.get(MapService.class).getMapURI("customer"))
              .map());
    } catch (Exception e) {
      TraceBackService.trace(e);
    }
  }

  public void showProspectsOnMap(ActionRequest request, ActionResponse response) {
    try {
      response.setView(
          ActionView.define(I18n.get("Prospects"))
              .add("html", Beans.get(MapService.class).getMapURI("prospect"))
              .map());
    } catch (Exception e) {
      TraceBackService.trace(e);
    }
  }

  public void showSuppliersOnMap(ActionRequest request, ActionResponse response) {
    try {
      response.setView(
          ActionView.define(I18n.get("Suppliers"))
              .add("html", Beans.get(MapService.class).getMapURI("supplier"))
              .map());
    } catch (Exception e) {
      TraceBackService.trace(e);
    }
  }

  @CallMethod
  public void execWhatsApp(String username, String message, String url, String id, String enc)
      throws IOException, ClassNotFoundException {

    try {
      String uri = Beans.get(AppBaseService.class).getAppBase().getWhatsAppURL();

      String fullUrl = uri + "/" + url + "/" + id;
      Socket socket = new Socket(localhost, 6060);
      // String data = "{\"username\" : \"" + username + "\",\"url\": \""+ fullUrl
      // +"\",\"message\":\""+ message +"\"}";
      String data = username + "***" + fullUrl + "***" + message;

      DataOutputStream dout = new DataOutputStream(socket.getOutputStream());
      DataInputStream in = new DataInputStream(socket.getInputStream());

      dout.write(data.getBytes("UTF8"));

      String msg = (String) in.readUTF();

      if (msg == "message_received") {
        dout.flush();
        dout.close();
        // socket.close();
        System.out.println("Message: " + msg);
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  @CallMethod
  public void execWhatsApp2(String username, String message, String url, String id, String enc)
      throws IOException, ClassNotFoundException {
    String args[] = {
      "python",
      "/Users\\Bachir.souldi.SOPHAL\\Desktop\\dev\\whatsapp_erp\\index.py",
      message,
      url,
      id
    };
    Process p = Runtime.getRuntime().exec(args);
    // BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
  }

  public static String getAccessToken() throws Exception {
    AppSettings appSettings = AppSettings.get();
    String BASE_URL = appSettings.get("portail.api.baseurl");
    String username = appSettings.get("portail.api.user");
    String password = appSettings.get("portail.api.password");

    String endpoint = BASE_URL + "token/";
    URL url = new URL(endpoint);
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();

    conn.setRequestMethod("POST");
    conn.setRequestProperty("Content-Type", "application/json");
    conn.setRequestProperty("Accept", "application/json");
    conn.setDoOutput(true);

    // Create a JSON object for the input
    JSONObject jsonInput = new JSONObject();
    jsonInput.put("username", username);
    jsonInput.put("password", password);

    // Write the JSON input to the output stream
    try (OutputStream os = conn.getOutputStream()) {
      byte[] input = jsonInput.toString().getBytes("utf-8");
      os.write(input, 0, input.length);
    }

    int responseCode = conn.getResponseCode();
    if (responseCode == HttpURLConnection.HTTP_OK) {
      try (BufferedReader br =
          new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"))) {
        StringBuilder response = new StringBuilder();
        String responseLine;
        while ((responseLine = br.readLine()) != null) {
          response.append(responseLine.trim());
        }
        return parseAccessToken(response.toString());
      }
    } else {
      // Read the error stream for more details
      StringBuilder errorResponse = new StringBuilder();
      try (BufferedReader br =
          new BufferedReader(new InputStreamReader(conn.getErrorStream(), "utf-8"))) {
        String errorLine;
        while ((errorLine = br.readLine()) != null) {
          errorResponse.append(errorLine.trim());
        }
      }
      throw new RuntimeException(
          "Failed: HTTP error code: " + responseCode + ", Error: " + errorResponse.toString());
    }
  }

  // Parse the JSON response to extract the access token
  private static String parseAccessToken(String jsonResponse) {
    try {
      JSONObject jsonObject = new JSONObject(jsonResponse);
      return jsonObject.get("access").toString(); // Extract the access token
    } catch (JSONException e) {
      System.err.println("Failed to parse JSON: " + jsonResponse);
      e.printStackTrace();
      return null; // Handle error appropriately
    }
  }
}
