package examples.localserver;

import org.apache.cxf.annotations.WSDLDocumentation;
import ru.uss.core.utils.JAXBUtils;
import ru.uss.esf.constant.Namespaces;
import ru.uss.esf.core.utils.InvoiceSignatureHelper;
import ru.uss.esf.model.invoice.abstractinvoice.AbstractInvoice;
import ru.uss.esf.model.invoice.version.InvoiceVersionMapper;
import ru.ussgroup.security.trusty.TrustyUtils;

import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.ParameterStyle;
import javax.security.auth.x500.X500PrivateCredential;

@WebService(name = "LocalService", serviceName = "LocalService", targetNamespace = Namespaces.ESF)
@WSDLDocumentation("Локальный сервис для работы с ИС ЭСФ")
@SOAPBinding(parameterStyle = ParameterStyle.BARE)
public class EsfLocalService {

    @WebResult(name = "signatureResponse")
    public SignatureResponse generateSignature(@WebParam(name = "signatureRequest") SignatureRequest request) {
        try {
            X500PrivateCredential credential = credential(request.getCertificatePath(), request.getCertificatePin());

            SignatureResponse response = new SignatureResponse();

            for (String invoiceBody : request.getInvoiceBodies()) {
                InvoiceHash invoiceHash = new InvoiceHash();

                AbstractInvoice invoice = JAXBUtils.toObject(invoiceBody, InvoiceVersionMapper.getClassByVersion(request.getVersion()));
                invoice.setVersion(request.getVersion());

                String signature = InvoiceSignatureHelper.sign(invoiceBody, credential);

                invoiceHash.setInvoiceNum(invoice.getNum());
                invoiceHash.setHash(invoiceBody);
                invoiceHash.setSignature(signature);

                response.getInvoiceHashList().add(invoiceHash);
            }

            return response;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @WebResult(name = "documentSignatureResponse")
    public DocumentSignatureResponse generateDocumentSignature(@WebParam(name = "documentSignatureRequest") DocumentSignatureRequest request) {
        return DocumentSigner.signatureResponse(request.getSignableData(), request.getCertificatePath(), request.getCertificatePin());
    }

    @WebResult(name = "documentXmlSignatureResponse")
    public DocumentXmlSignatureResponse generateDocumentXmlSignature(@WebParam(name = "documentXmlSignatureRequest") DocumentXmlSignatureRequest request) {
        return DocumentSigner.signatureXmlResponse(request.getSignableXmlData(), request.getCertificatePath(), request.getCertificatePin());
    }

    @WebResult(name = "listSignatureResponse")
    public ListSignatureResponse signIdWithReasonList(@WebParam(name = "idWithReasonListRequest") ListWithReasonSignatureRequest request) {
        String data = InvoiceSignatureHelper.toXML(request.getSignableData());
        String signature = sign(data, request.getCertificatePath(), request.getCertificatePin());
        return new ListSignatureResponse(signature, data);
    }

    @WebResult(name = "listSignatureResponse")
    public ListSignatureResponse signIdList(@WebParam(name = "idListRequest") ListSignatureRequest request) {
        String data = InvoiceSignatureHelper.toXML(request.getSignableData());
        String signature = sign(data, request.getCertificatePath(), request.getCertificatePin());
        return new ListSignatureResponse(signature, data);
    }

    private String sign(String data, String path, String pin) {
        try {
            return TrustyUtils.sign(data, credential(path, pin));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private X500PrivateCredential credential(String path, String pin) {
        return TrustyUtils.loadCredentialFromFile(path, pin);
    }

}
