Imports System.IO
Imports DigitalData.Modules.Database
Imports DigitalData.Modules.Interfaces
Imports DigitalData.Modules.Logging
Imports DigitalData.Modules.Config
Imports Newtonsoft.Json
Imports Newtonsoft.Json.Linq
Imports System.Net
Imports System.Text.RegularExpressions

Public Class frmMain
    Private _LogConfig As LogConfig
    Private _Logger As Logger
    Private _Interface As GraphQLInterface
    Private _MSSQL As MSSQLServer
    Private _Config As ConfigManager(Of Config)
    Private _Datapools As New List(Of String) From {
        "sap_aviation",
        "sap_facility",
        "sap_holding"
    }

    Public Class SAPData
        Public sapdaten As List(Of SAPDataItem)
    End Class

    Public Class SAPDataItem
        Public buchungskreis As String
        Public kostenstelle As String
        Public beschreibung As String
        Public gueltig_bis As String
    End Class

    Const GRAPHQL_QUERY_SAP_DATA = "
        query SAPDaten {
	        sapdaten(datenpool: __DATA_POOL__) {
		        sapdaten {
			        buchungskreis
			        kostenstelle
			        beschreibung
			        gueltig_bis
		        }
	        }
        }
    "

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Try
            Dim oStartupPath As String = AppDomain.CurrentDomain.BaseDirectory

            _LogConfig = New LogConfig(LogConfig.PathType.CustomPath, oStartupPath) With {
                .Debug = True
            }
            _Logger = _LogConfig.GetLogger()
            _Config = New ConfigManager(Of Config)(_LogConfig, oStartupPath)

            txtBaseUrl.Text = _Config.Config.BaseUrl
            txtUsername.Text = _Config.Config.Email
            txtPassword.Text = _Config.Config.Password

            txtCertFile.Text = _Config.Config.CertificateFile
            txtCertPass.Text = _Config.Config.CertificatePass
            txtCertFingerprint.Text = _Config.Config.CertificateFingerprint

            txtConnectionString.Text = _Config.Config.ConnectionString
            txtProxyHost.Text = _Config.Config.ProxyHost
            txtProxyPort.Text = _Config.Config.ProxyPort
            txtProxyUser.Text = _Config.Config.ProxyUsername
            txtProxyPass.Text = _Config.Config.ProxyPassword
            txtQuery.Text = _Config.Config.CustomQueryString

            Dim oIndex = cmbQuery.FindStringExact(_Config.Config.CurrentQuery)
            cmbQuery.SelectedIndex = oIndex

            _MSSQL = New MSSQLServer(_LogConfig, _Config.Config.ConnectionString)
        Catch ex As Exception
            _Logger.Error(ex)
            MsgBox(ex.Message, MsgBoxStyle.Critical, Text)
        End Try
    End Sub

    Private Sub btnLogin_Click(sender As Object, e As EventArgs) Handles btnLogin.Click
        Try
            SaveConfig()
            _Interface = New GraphQLInterface(_LogConfig,
                                          txtBaseUrl.Text,
                                          txtUsername.Text,
                                          txtPassword.Text,
                                          txtCertFingerprint.Text)

            If _Config.Config.HasProxySet() And _Config.Config.HasProxyCredentialsSet() Then
                Dim oURI As New Uri($"http://{_Config.Config.ProxyHost}:{_Config.Config.ProxyPort}")
                Dim oCredentials As New NetworkCredential(_Config.Config.ProxyUsername, _Config.Config.ProxyPassword)
                Dim oProxy As New WebProxy(oURI, True) With {
                    .Address = oURI,
                    .UseDefaultCredentials = False,
                    .Credentials = oCredentials
                }
                _Interface.Proxy = oProxy
                _Interface.Credentials = oCredentials

                _Logger.Debug("Using Proxy: {0}", oURI.ToString)
                _Logger.Debug("Proxy Credentials: [{0}] [{1}]", _Config.Config.ProxyUsername, _Config.Config.ProxyPassword)
            Else
                _Interface.Proxy = Nothing
                _Interface.Credentials = Nothing

                _Logger.Debug("Proxy not set.")
            End If

            Dim oResponse = _Interface.Login
            _Interface.SaveCookies(oResponse.Cookies.Item(0))

            If oResponse.StatusCode = Net.HttpStatusCode.OK Then
                MsgBox("Login Successful!", MsgBoxStyle.Information, Text)
            Else
                MsgBox("Login failed! Check Certificate and User Credentials!", MsgBoxStyle.Critical, Text)
            End If
        Catch ex As Exception
            _Logger.Error(ex)
            MsgBox(ex.Message, MsgBoxStyle.Critical, Text)
        End Try
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Try

            If _Interface Is Nothing Then
                MsgBox("Please login first!", MsgBoxStyle.Exclamation, Text)
                Exit Sub
            End If

            If cmbQuery.SelectedIndex = -1 Then
                MsgBox("Please select a query!", MsgBoxStyle.Exclamation, Text)
                Exit Sub
            End If

            If cmbQuery.Text = "SAPDaten" Then
                _MSSQL.ExecuteNonQuery("DELETE FROM TBCUST_SYNC_API_SAPDATEN")

                txtResult.Text = String.Empty

                Dim oTotalTotal As Integer = 0

                For Each oDatapool In _Datapools
                    Dim oQuery As String = GRAPHQL_QUERY_SAP_DATA.Trim.Replace("__DATA_POOL__", oDatapool)
                    Dim oDataResponse = _Interface.GetData(oQuery, "SAPDaten")
                    Dim oResult As String

                    Using oStream = oDataResponse.GetResponseStream()
                        Using oReader As New StreamReader(oStream)
                            oResult = oReader.ReadToEnd()
                        End Using
                    End Using

                    'Dim oObj As JObject = JsonConvert.DeserializeObject(oResult)
                    Dim oObj As JObject = JObject.Parse(oResult)

                    Dim oData As SAPData = ConvertResponse(oResult)

                    _Logger.Debug("Inserting [{0}] items for datapool [{1}]", oData.sapdaten.Count, oDatapool)

                    Dim oCounter As Integer = 0
                    Dim oTotal As Integer = oData.sapdaten.Count
                    ProgressBar1.Maximum = oTotal
                    ProgressBar1.Value = oCounter

                    For Each oItem As SAPDataItem In oData.sapdaten
                        Dim oBeschreibung = Regex.Replace(oItem.beschreibung, "'", "''", RegexOptions.IgnoreCase)

                        Dim oSQL = $"INSERT INTO TBCUST_SYNC_API_SAPDATEN (BESCHREIBUNG, BUCHUNGSKREIS, KOSTENSTELLE, GUELTIG_BIS) VALUES ('{oBeschreibung}', '{oItem.buchungskreis}', '{oItem.kostenstelle}', '{oItem.gueltig_bis}')"
                        Dim oSuccess = _MSSQL.ExecuteNonQuery(oSQL)

                        If oSuccess Then
                            _Logger.Debug("Record [{0}] inserted!", oItem.beschreibung)
                        End If

                        oCounter += 1
                        ProgressBar1.Value = oCounter
                    Next

                    txtResult.Text &= "--------------------------------------------" & vbNewLine
                    txtResult.Text &= $"--- Datapool: {oDatapool}" & vbNewLine
                    txtResult.Text &= JsonConvert.SerializeObject(oObj, Formatting.Indented) & vbNewLine

                    Application.DoEvents()

                    oTotalTotal += oTotal
                Next

                MsgBox($"Query finished! Lines inserted: [{oTotalTotal}]", MsgBoxStyle.Information, Text)
            ElseIf cmbQuery.Text = "Custom" Then
                If txtOperation.Text = String.Empty Then
                    MsgBox("Please select an operation!", MsgBoxStyle.Exclamation, Text)
                    Exit Sub
                End If

                Dim oDataResponse = _Interface.GetData(txtQuery.Text, txtOperation.Text)

                Dim oResult As String

                Using oStream = oDataResponse.GetResponseStream()
                    Using oReader As New StreamReader(oStream)
                        oResult = oReader.ReadToEnd()
                    End Using
                End Using

                Dim oPath = "data.auftraege.auftraege"
                Dim oObj As JObject = JObject.Parse(oResult)
                If _Interface.ReadJSONPathFragmented(oObj, oPath) = False Then
                    MsgBox($"JSONPath [{oPath}] was not successfully read", MsgBoxStyle.Critical, Text)
                End If
                'Dim oObj As JObject = JsonConvert.DeserializeObject(oResult)

                Dim oIndentedJson As String = JsonConvert.SerializeObject(oObj, Formatting.Indented)
                txtResult.Text = oIndentedJson

                TabControl1.SelectedTab = pageRaw
            Else
                MsgBox("Unknown query!", MsgBoxStyle.Exclamation, Text)
                Exit Sub
            End If
        Catch ex As Exception
            _Logger.Error(ex)
            MsgBox(ex.Message, MsgBoxStyle.Critical)
        End Try
    End Sub

    Sub SaveConfig()
        _Config.Config.ConnectionString = txtConnectionString.Text
        _Config.Config.BaseUrl = txtBaseUrl.Text

        _Config.Config.CertificateFile = txtCertFile.Text
        _Config.Config.CertificatePass = txtCertPass.Text
        _Config.Config.CertificateFingerprint = txtCertFingerprint.Text

        _Config.Config.Email = txtUsername.Text
        _Config.Config.Password = txtPassword.Text
        _Config.Config.ProxyHost = txtProxyHost.Text
        _Config.Config.ProxyPassword = txtProxyPass.Text
        _Config.Config.ProxyPort = txtProxyPort.Text
        _Config.Config.ProxyUsername = txtProxyUser.Text
        _Config.Config.CustomQueryString = txtQuery.Text
        _Config.Save(ForceAll:=True)
    End Sub
    Private Sub frmMain_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
        Try
            SaveConfig()
            Dim oLogoutResponse = _Interface.Logout()
            If oLogoutResponse.StatusCode = Net.HttpStatusCode.OK Then
                _Logger.Info("Logout successful.")
            End If
        Catch ex As Exception
            _Logger.Error(ex)
        End Try
    End Sub

    Public Function ConvertResponse(JsonString As String) As SAPData
        Dim oObj As JObject = JObject.Parse(JsonString)("data")("sapdaten")
        Dim oString As String = JsonConvert.SerializeObject(oObj, Formatting.None)
        Dim oSAPData As SAPData = JsonConvert.DeserializeObject(Of SAPData)(oString)

        Return oSAPData
    End Function

    Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbQuery.SelectedIndexChanged
        _Config.Config.CurrentQuery = cmbQuery.Text
        _Config.Save()
    End Sub
End Class
