package kz.arta.nca_iiscon.service;

import kz.arta.nca_iiscon.data.forward.ForwardApplication;
import kz.arta.nca_iiscon.data.forward.UpdateApplication;
import kz.arta.nca_iiscon.data.forward.application.ApplicationData;
import kz.arta.nca_iiscon.data.forward.application.ConfirmOrder;
import kz.arta.nca_iiscon.data.forward.application.Data;
import kz.arta.nca_iiscon.shep.*;
import kz.arta.nca_iiscon.util.SignerUtil;
import kz.arta.nca_iiscon.util.XmlTemplateBuilder;
import kz.arta.nca_iiscon.util.XmlToJsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.xml.bind.*;
import java.io.File;
import java.util.*;
import java.util.function.Consumer;

@Slf4j
@Service
public class ForwardApplicationNcaService {
    @Value("${login}")
    private String senderIdSHEP;
    @Value("${password}")
    private String senderPassSHEP;
    @Value("${forward_service_id}")
    private String serviceIdSHEP;
    @Value("${service_url}")
    private String urlSHEP;
    @Value("${eds_path}")
    private String keyFile;
    @Value("${eds_password}")
    private String keyPassword;

    @Autowired
    private RestService restService;

    public String sendRequestByTemplate(ForwardApplication forwardApplication) throws Exception {
        String request;

        try {
            //подписать хмл
            File signWSSFile = new File(keyFile);

            Data data = Optional.ofNullable(forwardApplication)
                    .map(ForwardApplication::getUpdateApplication)
                    .map(UpdateApplication::getApplicationData)
                    .map(ApplicationData::getData)
                    .orElse(null);


            // digiSign
            assert data != null;
            updateIfPresent(data, data::setDigiSign, data.getDigiSign(), signWSSFile, keyPassword);

            // confirmOrder
            ConfirmOrder confirm = data.getConfirmOrder();
            if (confirm != null && confirm.getDigiSign() != null) {
                updateIfPresent(confirm, confirm::setDigiSign, confirm.getDigiSign(), signWSSFile, keyPassword);
            }

            // denyOrder
            ConfirmOrder deny = data.getDenyOrder();
            if (deny != null && deny.getDigiSign() != null) {
                updateIfPresent(deny, deny::setDigiSign, deny.getDigiSign(), signWSSFile, keyPassword);
            }

            request = XmlTemplateBuilder.buildXMLForward(forwardApplication, serviceIdSHEP, senderIdSHEP, senderPassSHEP);

            log.info("Request: {}\n", request);
            String response =  restService.getPostWithsSoapHeaders(urlSHEP, request);
            log.info("Response: {}\n", response);

            return response;
        } catch (Exception e) {
            log.error("Ошибка: {}", e.getMessage(), e);
            e.printStackTrace();
            return e.getMessage();
        }
    }

    private static void updateIfPresent(Object obj, Consumer<String> setter,
                                        String valueToSign, File p12, String password) throws Exception {
        if (obj != null && valueToSign != null) {

            String cleaned = XmlToJsonUtil.cleanXml(valueToSign);
            log.info("Cleaned {}\n", cleaned);
            if (cleaned == null || cleaned.isEmpty()) return;
            String signedXml = signIfPresent(cleaned, p12, password);
            setter.accept(signedXml);
        }
    }

    private static String signIfPresent(String xml, File signWSSFile, String password) throws Exception {
        if (xml == null || xml.isEmpty()) {
            return null;
        }
        return SignerUtil.signXML(xml, signWSSFile, password);
    }
}
