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

import com.axelor.apps.message.service.MailAccountService;
import com.axelor.apps.purchase.db.PurchaseOrder;
import com.axelor.apps.purchase.db.PurchaseRequest;
import com.axelor.apps.purchase.db.PurchaseRequestLine;
import com.axelor.apps.purchase.db.repo.PurchaseRequestRepository;
import com.axelor.apps.purchase.db.repo.PurchaseRequestLineRepository;
import com.axelor.apps.purchase.exception.IExceptionMessage;
import com.axelor.apps.purchase.service.PurchaseRequestService;
import com.axelor.apps.tool.StringTool;
import com.axelor.auth.AuthUtils;
import com.axelor.auth.db.User;
import com.axelor.auth.db.repo.UserRepository;
import com.axelor.exception.AxelorException;
import com.axelor.exception.db.repo.TraceBackRepository;
import com.axelor.i18n.I18n;
import com.axelor.inject.Beans;
import com.axelor.mail.db.repo.MailFollowerRepository;
import com.axelor.meta.CallMethod;
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.Inject;
import com.google.inject.Singleton;

import wslite.json.JSONException;
import wslite.json.JSONObject;

import java.util.List;
import java.util.stream.Collectors;
import com.axelor.apps.purchase.service.print.PurchaseRequestPrintService;
import com.axelor.common.ObjectUtils;
import com.axelor.rpc.Context;
import com.google.common.base.Function;
import java.util.List;
import javax.annotation.Nullable;
import javax.json.JsonObject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.axelor.apps.report.engine.ReportSettings;
import com.axelor.exception.service.TraceBackService;
import com.google.common.collect.Lists;
import java.lang.invoke.MethodHandles;



@Singleton
public class PurchaseRequestController {

  private final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

  @Inject private MailAccountService mailAccountService;

  public void confirmCart(ActionRequest request, ActionResponse response) {
    Beans.get(PurchaseRequestService.class).confirmCart();
    response.setReload(true);
  }

  public void acceptRequest(ActionRequest request, ActionResponse response) {

    if (request.getContext().get("_ids") == null) {
      return;
    }

    List<Long> requestIds = (List<Long>) request.getContext().get("_ids");

    if (!requestIds.isEmpty()) {
      List<PurchaseRequest> purchaseRequests =
          Beans.get(PurchaseRequestRepository.class)
              .all()
              .filter("self.id in (?1)", requestIds)
              .fetch();

      Beans.get(PurchaseRequestService.class).acceptRequest(purchaseRequests);

      response.setReload(true);
    }
  }

  public void generatePo(ActionRequest request, ActionResponse response) {
    @SuppressWarnings("unchecked")
    List<Long> requestIds = (List<Long>) request.getContext().get("_ids");
    Boolean groupBySupplier = (Boolean) request.getContext().get("groupBySupplier");
    groupBySupplier = groupBySupplier == null ? false : groupBySupplier;
    Boolean groupByProduct = (Boolean) request.getContext().get("groupByProduct");
    groupByProduct = groupByProduct == null ? false : groupByProduct;
    if (requestIds != null && !requestIds.isEmpty()) {
      try {
        List<PurchaseRequest> purchaseRequests =
            Beans.get(PurchaseRequestRepository.class)
                .all()
                .filter("self.id in (?1)", requestIds)
                .fetch();
		// sophal 
		 int condition = 0;
        String message = "";
        for (PurchaseRequest result  : purchaseRequests) {
          if(result.getStatusSelect() != 5){  
            condition = 1;
            message = "purchase request not approved";
            break;           
          }
          if(result.getPurchaseOrderSet().size() > 0){  
            condition = 1;
             message = "you have already generated this purchase request";
            break;           
          }
        }
		
		if( condition == 0){
        List<String> purchaseRequestSeqs =
            purchaseRequests
                .stream()
                .filter(pr -> pr.getSupplierUser() == null)
                .map(PurchaseRequest::getPurchaseRequestSeq)
                .collect(Collectors.toList());
        if (purchaseRequestSeqs != null && !purchaseRequestSeqs.isEmpty()) {
          throw new AxelorException(
              TraceBackRepository.CATEGORY_CONFIGURATION_ERROR,
              I18n.get(IExceptionMessage.PURCHASE_REQUEST_MISSING_SUPPLIER_USER),
              purchaseRequestSeqs.toString());
        }
        response.setCanClose(true);
        List<PurchaseOrder> purchaseOrderList =
            Beans.get(PurchaseRequestService.class)
                .generatePo(purchaseRequests, groupBySupplier, groupByProduct);
        ActionViewBuilder actionViewBuilder =
            ActionView.define(
                    String.format(
                        "Purchase Order%s generated", (purchaseOrderList.size() > 1 ? "s" : "")))
                .model(PurchaseOrder.class.getName())
                .add("grid", "purchase-order-quotation-grid")
                .add("form", "purchase-order-form")
                .context("_showSingle", true)
                .domain(
                    String.format(
                        "self.id in (%s)", StringTool.getIdListString(purchaseOrderList)));
        response.setView(actionViewBuilder.map());
		
		}else{
          response.setAlert(I18n.get(message));       
        }
		
      } catch (AxelorException e) {
        response.setFlash(e.getMessage());
      }
    }
  }
  
  public void purchaseRequestsAssignedToUser(ActionRequest request, ActionResponse response) {

    List<Long> requestIds = (List<Long>) request.getContext().get("_ids");
    User user = (User) request.getContext().get("assignedToUser");

      if (requestIds != null && !requestIds.isEmpty()) {
        Beans.get(PurchaseRequestService.class).purchaseRequestsAssignedToUser(requestIds, user);
        response.setCanClose(true);
      }
    
  }

  /**
   * Called from grid or form purchase order view, print selected purchase order.
   *
   * @param request
   * @param response
   * @return
   */
  @SuppressWarnings("unchecked")
  public void showPurchaseRequest(ActionRequest request, ActionResponse response) {

    Context context = request.getContext();
    String fileLink;
    String title;
    PurchaseRequestPrintService purchaseRequestPrintService =
        Beans.get(PurchaseRequestPrintService.class);

    try {
      if (!ObjectUtils.isEmpty(request.getContext().get("_ids"))) {
        List<Long> ids =
            Lists.transform(
                (List) request.getContext().get("_ids"),
                new Function<Object, Long>() {
                  @Nullable
                  @Override
                  public Long apply(@Nullable Object input) {
                    return Long.parseLong(input.toString());
                  }
                });
        fileLink = purchaseRequestPrintService.printPurchaseRequests(ids);
        title = I18n.get("Purchase requests");
      } else if (context.get("id") != null) {
        PurchaseRequest purchaseRequest = request.getContext().asType(PurchaseRequest.class);
        title = purchaseRequestPrintService.getFileName(purchaseRequest);
        fileLink =
            purchaseRequestPrintService.printPurchaseRequest(purchaseRequest, ReportSettings.FORMAT_PDF);
        logger.debug("Printing " + title);
      } else {
        throw new AxelorException(
            TraceBackRepository.CATEGORY_MISSING_FIELD,
            I18n.get(IExceptionMessage.NO_PURCHASE_REQUEST_SELECTED_FOR_PRINTING));
      }
      response.setView(ActionView.define(title).add("html", fileLink).map());
    } catch (Exception e) {
      TraceBackService.trace(response, e);
    }
  }

  public void followPurchaseRequest(ActionRequest request, ActionResponse response) throws JSONException{
    Long id = request.getContext().asType(PurchaseRequest.class).getId();
    PurchaseRequest purchaseRequest = Beans.get(PurchaseRequestRepository.class).find(id);
    Beans.get(MailFollowerRepository.class).follow(purchaseRequest, AuthUtils.getUser());
    
    JSONObject obj = new JSONObject(purchaseRequest.getAttrs());
    JSONObject superiorId = obj.getJSONObject("superior_user");

    User sup = Beans.get(UserRepository.class).find(superiorId.getLong("id"));

    Beans.get(MailFollowerRepository.class).follow(purchaseRequest, sup);
  }

  @CallMethod
  public void sendEmail(String email,String subject,String body){
    EmailUtil.sendEmail(mailAccountService, email,subject, body);    
  }
  
  public void checkProductFamily(ActionRequest request, ActionResponse response) throws AxelorException {

      Long id = request.getContext().asType(PurchaseRequest.class).getId();
      PurchaseRequest purchaseRequest  = Beans.get(PurchaseRequestRepository.class).find(id);
      String productFamily = purchaseRequest.getFamilleProduit().getName().toString();
      Integer size = 0;
      
      List<PurchaseRequestLine> purchaseRequestLines  = 
        Beans.get(PurchaseRequestLineRepository.class)
        .all()
        .filter("self.newProduct = ?1 and self.purchaseRequest = ?2",false,id)
        .fetch();

      if (purchaseRequestLines  != null){ 
        
             size = purchaseRequestLines.stream()
             .collect(Collectors.groupingBy(fa -> fa.getProduct().getFamilleProduit())).size();

      }         
      if (size > 1){
            response.setError(I18n.get("Lines of expression of needs are not of the same family :") +productFamily);
            //return;    
      }
      if (size == 1){
        long idOfFamily = purchaseRequestLines.stream()
        .collect(Collectors.groupingBy(fa -> fa.getProduct().getFamilleProduit().getId()))
        .keySet().stream().collect(Collectors.toList()).get(0);

        if (purchaseRequest.getFamilleProduit().getId() != idOfFamily){
          response.setError(I18n.get("Lines of expression of needs are not of the same family :") +productFamily);   
        }
      }    
  }

}
