SET STEP ON 
Test1()
Test2()
Procedure Test1
	Local loRar As "RarAutoPass"
	Local lcXMLComenzi, llTestMode

	* Creare instanta
	loRar = Createobject("RarAutoPass")

	* Setare credentiale - pentru test
	llTestMode = .T.
	loRar.SetCredentials(m.llTestMode)

	* Actualizare nomenclator
	loRar.UpdateNomenclator()

	TEXT TO lcXMLComenzi NOSHOW
<?xml version="1.0" encoding="UTF-8"?>
<comenzi>
    <comanda>
        <nr_comanda>COM001</nr_comanda>
        <data>2024-02-04</data>
        <vin>VF1234567890</vin>
        <nr_inmatriculare>B01AAA</nr_inmatriculare>
        <km_final>150000</km_final>
        <km_initial>0</km_initial>
        <observatii>Test prezentare</observatii>
        <operatii>
            <operatie>
                <cod_operatie>SCHIMB_VITEZOMETRU</cod_operatie>
                <denumire>Schimbare vitezometru</denumire>
            </operatie>
            <operatie>
                <cod_operatie>REPARATIE_BORD</cod_operatie>
                <denumire>Reparatie instrumente bord</denumire>
            </operatie>
        </operatii>
    </comanda>
    <comanda>
        <!-- ... alte comenzi ... -->
    </comanda>
</comenzi>
	ENDTEXT

	* Procesare fisier XML cu comenzi
	If !loRar.ProcessXMLComenzi("comenzi.xml")
		? "Eroare: " + loRar.ErrorMsg
	Endif

Endproc && Test1

***********************************
Procedure Test2
	Local loRar As "RarAutoPass"
	Local llTestMode

	* Creare instanta si setare mediu
	loRar = Createobject("RarAutoPass")

	* Pentru test
	llTestMode = .T.
	loRar.SetCredentials(m.llTestMode)

	* SAU pentru productie
	* loRar.SetCredentials("email@service.ro", "parola", .F.)

	* Actualizare nomenclator (fortat)
	If !loRar.UpdateNomenclator(.T.)
		? "Eroare actualizare nomenclator: " + loRar.ErrorMsg
		Return
	Endif

	* Adaugare mapari operatii
	Use mapare_prestatii
	Append Blank
	Replace cod_op_service With "SCHIMB_VITEZOMETRU", ;
		descr_op_service With "Schimbare vitezometru/instrumente bord", ;
		cod_prestatie_rar With "OE-1", ;
		auto_send With .T., ;
		data_actualizare With Date()

	* Procesare comenzi din XML
	If !loRar.ProcessXMLComenzi("comenzi.xml")
		? "Eroare procesare comenzi: " + loRar.ErrorMsg
		* Verificam log-ul pentru detalii
		Select rar_log
		Browse
	Endif

	* Sau trimitere prezentare individuala
	If !loRar.SendPrezentare(;
			"2024-02-04", ;        && Data prestatie
		"B01AAA", ;            && Nr inmatriculare
		"VF1234567890", ;      && VIN
		150000, ;              && Km final
		0, ;                   && Km initial
		"Test", ;              && Observatii
		"", ;                  && Imagine base64
		'[{"codPrestatie":"OE-1"}]', ;  && Prestatii JSON
		"COM001")             && Nr comanda pentru logging
		? "Eroare trimitere prezentare: " + loRar.ErrorMsg
	Endif

Endproc && Test2

* Clasa pentru integrarea cu RAR AutoPass
#DEFINE C_API_TIMEOUT 30
#DEFINE C_TEST_URL "https://apps.rarom.ro/test-rar-autopass"
#DEFINE C_PROD_URL "https://apps.rarom.ro/rar-autopass"

* Clasa pentru integrarea cu RAR AutoPass
DEFINE CLASS RarAutoPass AS Custom

    * Proprietati private
    lcUrl = ""
    lcEmail = ""
    lcPassword = ""
    lcToken = ""
    lcError = ""
    llTestMode = .T.
    loXMLHTTP = null 

    * Proprietati publice
    ErrorMsg = ""
    LastResponse = ""

    * Constructor
    FUNCTION Init
        THIS.lcUrl = ""
        THIS.lcEmail = ""
        THIS.lcPassword = ""
        THIS.lcToken = ""
        THIS.lcError = ""
        THIS.llTestMode = .T.
        THIS.loXMLHTTP = CREATEOBJECT("MSXML2.ServerXMLHTTP.6.0")
        THIS.SetHttpTimeout()

        * Cream tabelele necesare daca nu exista
        THIS.InitializeStructure()
        RETURN .T.
    ENDFUNC

    * Setare timeout pentru requesturi HTTP
    FUNCTION SetHttpTimeout
        LOCAL llSuccess
        llSuccess = .F.
        
        TRY
            THIS.loXMLHTTP.setTimeouts(C_API_TIMEOUT*1000, ; && ResolveTimeout
                                     C_API_TIMEOUT*1000, ; && ConnectTimeout
                                     C_API_TIMEOUT*1000, ; && SendTimeout
                                     C_API_TIMEOUT*1000)  && ReceiveTimeout
            llSuccess = .T.
        CATCH TO loError
            THIS.ErrorMsg = "Eroare setare timeout: " + loError.Message
            llSuccess = .F.
        ENDTRY
        
        RETURN llSuccess
    ENDFUNC

    * Setare credentiale
    FUNCTION SetCredentials
        PARAMETERS tlTestMode
        LOCAL llSuccess
        llSuccess = .F.

        TRY
            * Setam modul de lucru (test/productie)
            THIS.llTestMode = tlTestMode
            
            * Setam URL-ul corespunzator
            THIS.lcUrl = IIF(THIS.llTestMode, C_TEST_URL, C_PROD_URL)
            
            * Citim credentialele din fisierul de setari
            llSuccess = THIS.ReadSettings(tlTestMode)
            
        CATCH TO loEx
            THIS.ErrorMsg = "Eroare setare credentiale: " + loEx.Message
            llSuccess = .F.
        ENDTRY
        
        RETURN llSuccess
    ENDFUNC

    * Initializare structura tabele
    FUNCTION InitializeStructure
        LOCAL llSuccess
        llSuccess = .T.

        TRY
            IF !FILE("prestatii_rar.dbf")
                CREATE TABLE prestatii_rar FREE (;
                    cod_prest C(10), ;    && cod_prestatie
                    nume_prest C(250), ;  && nume_prestatie
                    data_act D)          && data_actualizare
                
                INDEX ON cod_prest TAG cod_prest
                USE IN SELECT('prestatii_rar')
            ENDIF

            IF !FILE("mapare_prestatii.dbf")
                CREATE TABLE mapare_prestatii FREE (;
                    cod_op C(20), ;      && cod_op_service
                    descr_op M, ;        && descr_op_service
                    cod_rar C(10), ;     && cod_prestatie_rar
                    auto_send L, ;       && auto_send
                    data_act D)          && data_actualizare
                INDEX ON cod_op TAG cod_op
                USE IN SELECT('mapare_prestatii')
            ENDIF

            IF !FILE("rar_log.dbf")
                CREATE TABLE rar_log FREE (;
                    id I AUTOINC, ;
                    data_prez D, ;       && data_prezentare
                    nr_comanda C(20), ;
                    vin C(20), ;
                    nr_inm C(10), ;
                    km_final N(10), ;
                    km_init N(10), ;     && km_initial
                    prestatii M, ;
                    status C(20), ;
                    error_msg M, ;
                    data_trim T)         && data_trimitere
                USE IN SELECT('rar_log')
            ENDIF

        CATCH TO loEx
            THIS.ErrorMsg = "Eroare initializare structura: " + loEx.Message
            llSuccess = .F.
        ENDTRY

        RETURN llSuccess
    ENDFUNC

    * Login si obtinere token
    FUNCTION Login
        LOCAL lcJsonLogin, llSuccess
        llSuccess = .F.
        
        lcJsonLogin = '{"email":"' + THIS.lcEmail + '","password":"' + THIS.lcPassword + '"}'

        TRY
            THIS.loXMLHTTP.Open("POST", THIS.lcUrl + "/public/login", .F.)
            THIS.loXMLHTTP.setRequestHeader("Content-Type", "application/json")
            THIS.loXMLHTTP.Send(lcJsonLogin)

            IF THIS.loXMLHTTP.Status != 200
                THIS.ErrorMsg = "Eroare login: " + THIS.loXMLHTTP.responseText
                llSuccess = .F.
                RETURN llSuccess
            ENDIF

            * Folosim nfjsonread pentru a parsa raspunsul
            loResponse = nfjsonread(THIS.loXMLHTTP.responseText)
            
            IF TYPE('loResponse') == 'O' AND !ISNULL(loResponse)
                THIS.lcToken = loResponse.token
                IF EMPTY(THIS.lcToken)
                    THIS.ErrorMsg = "Nu s-a putut obtine token-ul"
                    llSuccess = .F.
                ELSE
                    llSuccess = .T.
                ENDIF
            ELSE
                THIS.ErrorMsg = "Eroare parsare raspuns JSON"
                llSuccess = .F.
            ENDIF

        CATCH TO loEx
            THIS.ErrorMsg = "Eroare login: " + loEx.Message
            llSuccess = .F.
        ENDTRY

        RETURN llSuccess
    ENDFUNC
* Actualizare nomenclator presta?ii
    FUNCTION UpdateNomenclator
        LPARAMETERS tlForceRefresh
        LOCAL llSuccess
        llSuccess = .F.

        IF !tlForceRefresh AND FILE("prestatii_rar.dbf")
            llSuccess = .T.
            RETURN llSuccess
        ENDIF

        IF !THIS.Login()
            RETURN .F.
        ENDIF

        TRY
            THIS.loXMLHTTP.Open("GET", THIS.lcUrl + "/nomenclator/getNomenclatorPrestatii", .F.)
            THIS.loXMLHTTP.setRequestHeader("Authorization", "Bearer " + THIS.lcToken)
            THIS.loXMLHTTP.Send()

            IF THIS.loXMLHTTP.Status != 200
                THIS.ErrorMsg = "Eroare obtinere nomenclator: " + THIS.loXMLHTTP.responseText
                llSuccess = .F.
                RETURN llSuccess
            ENDIF
            
            * Folosim nfjsonread pentru a parsa raspunsul
            loJson = nfjsonread(THIS.loXMLHTTP.responseText)
            
            IF TYPE('loJson') == 'O' AND !ISNULL(loJson) AND TYPE('loJson.data') == 'O'
                * Deschidem tabelul prestatii_rar
                IF !USED("prestatii_rar")
                    USE prestatii_rar IN 0
                ENDIF
                
                SELECT prestatii_rar
                
                * Procesam fiecare prestatie
                FOR EACH loItem IN loJson.data
                    * Cautam prestatia dupa cod
                    LOCATE FOR cod_prest = loItem.codPrestatie
                    
                    IF FOUND()
                        * Update daca exista ?i s-a modificat numele
                        IF nume_prest != loItem.numePrestatie
                            REPLACE ;
                                nume_prest WITH loItem.numePrestatie, ;
                                data_act WITH DATE()
                        ENDIF
                    ELSE
                        * Insert daca nu exista
                        INSERT INTO prestatii_rar (;
                            cod_prest, ;
                            nume_prest, ;
                            data_act) ;
                            VALUES (;
                            loItem.codPrestatie, ;
                            loItem.numePrestatie, ;
                            DATE())
                    ENDIF
                ENDFOR
                
                llSuccess = .T.
            ELSE
                THIS.ErrorMsg = "Eroare parsare raspuns JSON pentru nomenclator"
                llSuccess = .F.
            ENDIF

        CATCH TO loEx
            THIS.ErrorMsg = "Eroare actualizare nomenclator: " + loEx.Message
            llSuccess = .F.
        ENDTRY

        RETURN llSuccess
    ENDFUNC

    * Trimitere prezentare individuala
    FUNCTION SendPrezentare
        LPARAMETERS tcDataPrest, tcNrInm, tcVin, tnKmFinal, tnKmInitial, ;
            tcObs, tcImagineB64, tcPrestatii, tcNrComanda
        LOCAL llSuccess, lcJson
        llSuccess = .F.

        IF !THIS.Login()
            RETURN .F.
        ENDIF

        * Construim JSON-ul pentru prezentare
        TEXT TO lcJson NOSHOW TEXTMERGE
{
    "dataPrestatie": "<<tcDataPrest>>",
    "nrInmatriculare": "<<tcNrInm>>",
    "vin": "<<tcVin>>",
    "odometruFinal": <<tnKmFinal>>,
    "odometruInitial": <<IIF(EMPTY(tnKmInitial), "null", tnKmInitial)>>,
    "obs": "<<tcObs>>",
    "b64Image": "<<tcImagineB64>>",
    "status": "FINALIZATA",
    "prestatii": <<tcPrestatii>>
}
        ENDTEXT

        TRY
            THIS.loXMLHTTP.Open("POST", THIS.lcUrl + "/prezentari/postPrezentare", .F.)
            THIS.loXMLHTTP.setRequestHeader("Content-Type", "application/json")
            THIS.loXMLHTTP.setRequestHeader("Authorization", "Bearer " + THIS.lcToken)
            THIS.loXMLHTTP.Send(lcJson)

            THIS.LastResponse = THIS.loXMLHTTP.responseText

            IF THIS.loXMLHTTP.Status != 200
                THIS.ErrorMsg = "Eroare trimitere prezentare: " + THIS.LastResponse
                THIS.LogPrezentare(tcDataPrest, tcNrComanda, tcVin, tcNrInm, ;
                    tnKmFinal, tnKmInitial, tcPrestatii, "ERROR", THIS.ErrorMsg)
                llSuccess = .F.
            ELSE
                THIS.LogPrezentare(tcDataPrest, tcNrComanda, tcVin, tcNrInm, ;
                    tnKmFinal, tnKmInitial, tcPrestatii, "SUCCESS")
                llSuccess = .T.
            ENDIF

        CATCH TO loEx
            THIS.ErrorMsg = "Eroare trimitere prezentare: " + loEx.Message
            THIS.LogPrezentare(tcDataPrest, tcNrComanda, tcVin, tcNrInm, ;
                tnKmFinal, tnKmInitial, tcPrestatii, "ERROR", THIS.ErrorMsg)
            llSuccess = .F.
        ENDTRY

        RETURN llSuccess
    ENDFUNC

    * Logging prezentari
    FUNCTION LogPrezentare
        LPARAMETERS tcDataPrest, tcNrComanda, tcVin, tcNrInm, tnKmFinal, ;
            tnKmInitial, tcPrestatii, tcStatus, tcErrorMsg
        LOCAL llSuccess
        llSuccess = .F.

        TRY
            IF !USED("rar_log")
                USE rar_log IN 0
            ENDIF

            INSERT INTO rar_log (;
                data_prez, ;
                nr_comanda, ;
                vin, ;
                nr_inm, ;
                km_final, ;
                km_init, ;
                prestatii, ;
                status, ;
                error_msg, ;
                data_trim) ;
                VALUES (;
                CTOD(tcDataPrest), ;
                tcNrComanda, ;
                tcVin, ;
                tcNrInm, ;
                tnKmFinal, ;
                tnKmInitial, ;
                tcPrestatii, ;
                tcStatus, ;
                tcErrorMsg, ;
                DATETIME())
            llSuccess = .T.

        CATCH TO loEx
            THIS.ErrorMsg = "Eroare logging: " + loEx.Message
            llSuccess = .F.
        ENDTRY

        RETURN llSuccess
    ENDFUNC    
    
* Procesare comenzi din XML
    FUNCTION ProcessXMLComenzi
        LPARAMETERS tcXMLFile
        LOCAL loXML AS MSXML2.DOMDocument.6.0
        LOCAL loNodes AS MSXML2.IXMLDOMNodeList
        LOCAL loNode AS MSXML2.IXMLDOMNode
        LOCAL lcPrestatii, llSuccess
        llSuccess = .F.

        TRY
            loXML = CREATEOBJECT("MSXML2.DOMDocument.6.0")
            loXML.async = .F.

            IF !loXML.load(tcXMLFile)
                THIS.ErrorMsg = "Eroare incarcare XML: " + loXML.parseError.reason
                llSuccess = .F.
                RETURN llSuccess
            ENDIF

            * Obtinem toate nodurile de comenzi
            loNodes = loXML.selectNodes("/comenzi/comanda")

            FOR EACH loNode IN loNodes
                * Extragem datele din XML
                lcNrComanda = loNode.selectSingleNode("nr_comanda").text
                lcDataPrest = loNode.selectSingleNode("data").text
                lcVin = loNode.selectSingleNode("vin").text
                lcNrInm = loNode.selectSingleNode("nr_inmatriculare").text
                lnKmFinal = VAL(loNode.selectSingleNode("km_final").text)
                lnKmInitial = VAL(loNode.selectSingleNode("km_initial").text)
                lcObs = NVL(loNode.selectSingleNode("observatii").text, "")

                * Generam JSON cu prestatii din operatiile comenzii
                lcPrestatii = THIS.GetPrestatiiFromXMLNode(loNode.selectNodes("operatii/operatie"))

                * Trimitem prezentarea
                IF !THIS.SendPrezentare(lcDataPrest, lcNrInm, lcVin, ;
                    lnKmFinal, lnKmInitial, lcObs, ;
                    "", lcPrestatii, lcNrComanda)
                    * Continuam cu urmatoarea comanda chiar daca una esueaza
                    * dar am logat deja eroarea in SendPrezentare
                    LOOP
                ENDIF
            ENDFOR
            llSuccess = .T.

        CATCH TO loEx
            THIS.ErrorMsg = "Eroare procesare XML: " + loEx.Message
            llSuccess = .F.
        ENDTRY

        RETURN llSuccess
    ENDFUNC

    * Generare JSON prestatii din noduri XML
    FUNCTION GetPrestatiiFromXMLNode
        LPARAMETERS loOperatiiNodes
        LOCAL lcPrestatiiJson, lcCodRar
        LOCAL loNode AS MSXML2.IXMLDOMNode

        TEXT TO lcPrestatiiJson NOSHOW
[
        ENDTEXT

        lnCount = 0
        FOR EACH loNode IN loOperatiiNodes
            lcCodOperatie = loNode.selectSingleNode("cod_operatie").text
            lcCodRar = THIS.GetCodRarPentruOperatie(lcCodOperatie)

            IF !EMPTY(lcCodRar)
                lcPrestatiiJson = lcPrestatiiJson + ;
                    IIF(lnCount > 0, ",", "") + ;
                    '{"codPrestatie":"' + lcCodRar + '","idPrezentare":null}'
                lnCount = lnCount + 1
            ENDIF
        ENDFOR

        lcPrestatiiJson = lcPrestatiiJson + "]"
        RETURN lcPrestatiiJson
    ENDFUNC

    * Obtinere cod RAR pentru operatie service
    FUNCTION GetCodRarPentruOperatie
        LPARAMETERS tcCodOperatie
        LOCAL lcCodRar

        IF !USED("mapare_prestatii")
            USE mapare_prestatii IN 0
        ENDIF

        SELECT mapare_prestatii
        LOCATE FOR cod_op = tcCodOperatie
        IF FOUND() AND auto_send
            lcCodRar = cod_rar
        ELSE
            lcCodRar = ""
        ENDIF

        RETURN lcCodRar
    ENDFUNC

    * Functie pentru citirea credentialelor din settings.xml
    FUNCTION ReadSettings
        PARAMETERS tlTestMode
        LOCAL loXML AS MSXML2.DOMDocument.6.0
        LOCAL lcSettingsPath, lcEnvironment, loCredentials
        LOCAL lcEmail, lcPassword, llSuccess
        llSuccess = .F.

        TRY
            * Cream obiectul XML
            loXML = CREATEOBJECT("MSXML2.DOMDocument.6.0")
            loXML.async = .F.

            * Determinam calea catre settings.xml
            lcSettingsPath = ADDBS(JUSTPATH(SYS(16,0))) + "settings.xml"

            * Verificam daca exista fisierul
            IF !FILE(lcSettingsPath)
                THIS.ErrorMsg = "Fisierul settings.xml nu exista in: " + lcSettingsPath
                llSuccess = .F.
                RETURN llSuccess
            ENDIF

            * Incarcam XML-ul
            IF !loXML.load(lcSettingsPath)
                THIS.ErrorMsg = "Eroare incarcare settings.xml: " + loXML.parseError.reason
                llSuccess = .F.
                RETURN llSuccess
            ENDIF

            * Determinam mediul (test/productie)
            lcEnvironment = IIF(tlTestMode, "test", "production")

            * Selectam credentialele pentru mediul dorit
            loCredentials = loXML.selectSingleNode("/settings/" + lcEnvironment + "/credentials")

            IF !ISNULL(loCredentials)
                lcEmail = loCredentials.selectSingleNode("email").text
                lcPassword = loCredentials.selectSingleNode("password").text

                * Setam credentialele
                THIS.lcEmail = lcEmail
                THIS.lcPassword = lcPassword
                llSuccess = .T.
            ELSE
                THIS.ErrorMsg = "Nu s-au gasit credentiale pentru mediul: " + lcEnvironment
                llSuccess = .F.
            ENDIF

        CATCH TO loEx
            THIS.ErrorMsg = "Eroare citire setari: " + loEx.Message
            llSuccess = .F.
        ENDTRY

        RETURN llSuccess
    ENDFUNC
ENDDEFINE      