Imports System.Text
Imports UTS_Core.Database
Imports UTS_Core.UTSModule.DbConnect
Imports UTS_Core.UTSModule.DbTableModel.Manage

Namespace UTSModule.Service
    Public Class AppRegister
        Implements IDisposable

        ''' <summary>
        ''' 当前App所属服务索引
        ''' </summary>
        ''' <returns></returns>
        Public ReadOnly Property ServiceIndex As Integer

        ''' <summary>
        ''' 当前App名称
        ''' </summary>
        ''' <returns></returns>
        Public ReadOnly Property AppName As String

        ''' <summary>
        ''' 当前App版本
        ''' </summary>
        ''' <returns></returns>
        Public ReadOnly Property AppVersion As String

        ''' <summary>
        ''' 当前App运行信息
        ''' </summary>
        ''' <returns></returns>
        Public Property AppMsg As String

        ''' <summary>
        ''' 当前App状态，默认0为空闲
        ''' </summary>
        ''' <returns></returns>
        Public Property AppStatus As Integer


        Private ReadOnly _logLock As Object = New Object()
        Private ReadOnly _logQueue As New Queue(Of Dictionary(Of String, String))


        Enum LogTypeEnum
            ''' <summary>
            ''' 调试信息
            ''' </summary>
            Debug

            ''' <summary>
            ''' 流程信息
            ''' </summary>
            Info

            ''' <summary>
            ''' 警告信息
            ''' </summary>
            Warn

            ''' <summary>
            ''' 错误信息
            ''' </summary>
            [Error]

            ''' <summary>
            ''' 致命信息
            ''' </summary>
            Fatal
        End Enum


        Sub New(serviceIndex As Integer, appName As String, appVersion As String)
            Me.ServiceIndex = serviceIndex
            Me.AppName = appName
            Me.AppVersion = appVersion

            InitApp().GetAwaiter().GetResult()
        End Sub

        Public Property ProjectName() As String
        Public Property StationName() As String
        Public Property TestPlan() As String

        Private Async Function InitApp() As Task
            If AppRegistered() Then
                '更新App版本
                Try
                    Await UpdateAppVersion()
                Catch ex As Exception
                    Throw New Exception($"UpdateAppVersion Error: {ex.Message}")
                End Try
                Return
            End If

            Try
                RegisterApp() '注册App
            Catch ex As Exception
                Throw New Exception($"RegisterApp Error: {ex.Message}")
            End Try

        End Function


        Private Function AppRegistered() As Boolean
            Dim result As Integer

            Dim colName As String = $"count(*)"
            Dim tableName As String = $"{AppListTable.TableName}"
            Dim condition As String = $"`{AppListTable.ColNamesEnum.ServiceID}` = {ServiceIndex} and 
                                    `{AppListTable.ColNamesEnum.AppName}` = '{AppName}'"

            Using db As New DbExecutor(UtsDb.LocalDbType, UtsDb.LocalConnString)
                db.Open()

                Dim cmdText As String = db.CmdHelper.Search(colName, tableName, condition)
                result = CInt(db.ExecuteScalar(cmdText))

                db.Close()
            End Using

            Return result > 0
        End Function


        Private Sub RegisterApp()
            Dim tableName As String = AppListTable.TableName
            Dim filed As New Dictionary(Of String, String) From {
                    {$"{AppListTable.ColNamesEnum.ServiceID}", ServiceIndex.ToString()},
                    {$"{AppListTable.ColNamesEnum.AppName}", AppName},
                    {$"{AppListTable.ColNamesEnum.AppVersion}", AppVersion},
                    {$"{AppListTable.ColNamesEnum.RegisterDateTime}", Now.ToString("yyyy-MM-dd HH:mm:ss")},
                    {$"{AppListTable.ColNamesEnum.LastActiveDateTime}", Now.ToString("yyyy-MM-dd HH:mm:ss")}
                    }

            Dim saved As Boolean
            Dim cmdText As String

            Try
                '远程注册App
                Using db As New DbExecutor(UtsDb.RemoteDbType, UtsDb.RemoteConnString)
                    db.Open()

                    cmdText = $"call `uts_manage`.`RegisterApp` ({ServiceIndex},'{AppName}','{AppVersion}','{Now:yyyy-MM-dd HH:mm:ss}')"

                    db.ExecuteNonQuery(cmdText)

                    db.Close()
                End Using

                saved = True
            Catch ex As Exception
                saved = False
                Console.WriteLine("Register Remote App Error:" & ex.Message)
            End Try


            '本地注册App
            Using db As New DbExecutor(UtsDb.LocalDbType, UtsDb.LocalConnString)
                db.Open()

                cmdText = db.CmdHelper.Insert(tableName, filed)
                db.ExecuteNonQuery(cmdText)

                If saved = False Then
                    cmdText = $"call `uts_manage`.`RegisterApp` ({ServiceIndex},'{AppName}','{AppVersion}','{Now:yyyy-MM-dd HH:mm:ss}')"
                    DbConnector.SaveCmdStringToCacheTable(db, cmdText)
                End If

                db.Close()
            End Using
        End Sub

        Private Async Function UpdateAppVersion() As Task
            Dim tableName As String = AppListTable.TableName
            Dim filed As New Dictionary(Of String, String) From {
                    {$"{AppListTable.ColNamesEnum.AppVersion}", AppVersion},
                    {$"{AppListTable.ColNamesEnum.LastActiveDateTime}", Now.ToString("yyyy-MM-dd HH:mm:ss")}
                    }
            Dim condition As String = $"`{AppListTable.ColNamesEnum.ServiceID}` = {ServiceIndex} and `{AppListTable.ColNamesEnum.AppName}` = '{AppName}'"

            Dim saved As Boolean
            Dim cmdText As String

            Try
                '远程更新App版本
                Using db As New DbExecutor(UtsDb.RemoteDbType, UtsDb.RemoteConnString)
                    cmdText = db.CmdHelper.DbUpdate(UtsDb.RemotePublicDb, tableName, filed, condition)

                    Await db.OpenAsync()

                    Await db.ExecuteNonQueryAsync(cmdText)

                    db.Close()
                End Using
                saved = True
            Catch ex As Exception
                saved = False
                Console.WriteLine("Update Remote AppVersion Error:" & ex.Message)
            End Try


            '本地更新App版本
            Using db As New DbExecutor(UtsDb.LocalDbType, UtsDb.LocalConnString)
                Await db.OpenAsync()

                cmdText = db.CmdHelper.Update(tableName, filed, condition)
                Await db.ExecuteNonQueryAsync(cmdText)

                '保存至缓冲队列
                If saved = False Then
                    cmdText = New DbExecutor(UtsDb.RemoteDbType, UtsDb.RemoteConnString).CmdHelper.DbUpdate(UtsDb.RemotePublicDb, tableName, filed, condition)
                    DbConnector.SaveCmdStringToCacheTable(db, cmdText)
                End If

                db.Close()
            End Using
        End Function

        ''' <summary>
        ''' 定期更新APP的活动时间，调用则会定期基于本地调用存储过程至缓存表
        ''' </summary>
        Public Sub UpdateAliveTime()
            Dim sb As New StringBuilder
            sb.Append($"update `{UtsDb.RemotePublicDb}`.`{AppListTable.TableName}` set ")
            sb.Append($"`{AppListTable.ColNamesEnum.AppVersion}` = '{AppVersion}' ")
            sb.Append($",`{AppListTable.ColNamesEnum.LastActiveDateTime}` =  current_timestamp() ")
            If String.IsNullOrEmpty(AppMsg) = False Then
                Select Case AppStatus
                    Case 0 '空闲状态
                        sb.Append($",`{AppListTable.ColNamesEnum.LastInfomation}` = '{AppMsg},Status:Idle' ")
                    Case 1 '测试中
                        sb.Append($",`{AppListTable.ColNamesEnum.LastInfomation}` = '{AppMsg},Status:Testing'")
                End Select
            End If

            sb.Append($"where `{AppListTable.ColNamesEnum.ServiceID}` = {ServiceIndex} ")
            sb.Append($"and `{AppListTable.ColNamesEnum.AppName}` = '{AppName}' ")

            Try
                Using db As New DbExecutor(UtsDb.RemoteDbType, UtsDb.RemoteConnString)
                    db.Open()

                    db.ExecuteNonQuery(sb.ToString)

                    db.Close()
                End Using
            Catch ex As Exception
                Console.WriteLine($"Update AppInfo Error:{ex.Message}")
            End Try

        End Sub


        Public Shared Sub CreateAppLogTable()
            Try
                Using db As New DbExecutor(UtsDb.LocalDbType, UtsDb.LocalConnString)
                    db.Open()

                    Dim cmdText As String = AppLogTable.CreateTableString("", DbExecutor.DbTypeEnum.Sqlite)

                    db.ExecuteNonQuery(cmdText)

                    db.Close()
                End Using

            Catch ex As Exception
                Throw New Exception($"CreateAppLogTable Error:{ex.Message}")
            End Try
        End Sub


        Public Shared Sub CreateAppListTable()
            Try
                Using db As New DbExecutor(UtsDb.LocalDbType, UtsDb.LocalConnString)
                    db.Open()

                    Dim cmdText As String = AppListTable.CreateTableString("", DbExecutor.DbTypeEnum.Sqlite)

                    db.ExecuteNonQuery(cmdText)

                    db.Close()
                End Using

            Catch ex As Exception
                Throw New Exception($"CreateAppListTable Error:{ex.Message}")
            End Try
        End Sub


        Public Sub AppendDebugLog(logText As String)
            AppendLogToLogQueue(LogTypeEnum.Debug, logText)
        End Sub

        Public Sub AppendTraceLog(logText As String)
            AppendLogToLogQueue(LogTypeEnum.Info, logText)
        End Sub

        Public Sub AppendWarningLog(logText As String)
            AppendLogToLogQueue(LogTypeEnum.Warn, logText)
        End Sub

        Public Sub AppendErrorLog(logText As String)
            AppendLogToLogQueue(LogTypeEnum.Error, logText)
        End Sub

        Public Sub AppendFatalLog(logText As String)
            AppendLogToLogQueue(LogTypeEnum.Fatal, logText)
        End Sub

        ''' <summary>
        ''' 添加日志内容至缓存的日志队列中
        ''' 调用SaveLogQueueToDb将队列中的数据写入到数据库
        ''' 
        ''' Tip:缓存队列仅记录每条日志不同的内容,例如写入时间，日志类型，日志内容等
        ''' </summary>
        ''' <param name="logType"></param>
        ''' <param name="logText"></param>
        Public Sub AppendLogToLogQueue(logType As LogTypeEnum, logText As String)
            Dim dicFiled As New Dictionary(Of String, String)

            dicFiled.Add($"{AppLogTable.ColNamesEnum.DateTime}", $"{Now:yyyy-MM-dd HH:mm:ss}")

            dicFiled.Add($"{AppLogTable.ColNamesEnum.LogType}", $"{logType}")
            dicFiled.Add($"{AppLogTable.ColNamesEnum.LogText}", $"{logText}")

            SyncLock _logLock
                _logQueue.Enqueue(dicFiled) '将日志信息放入缓冲队列
            End SyncLock

        End Sub


        Public Sub SaveLogQueueToDb()
            If _logQueue.Count <= 0 Then Return

            Dim tableName As String = AppLogTable.TableName

            Using db As New DbExecutor(UtsDb.LocalDbType, UtsDb.LocalConnString)
                db.Open()

                db.BeginTransaction()

                Dim dicFiled As Dictionary(Of String, String)
                Dim cmdText As String
                Dim cmdHelper As DbCmdHelper = DbCmdHelper.CreateCmdHelper(UtsDb.RemoteDbType)

                SyncLock _logLock
                    While _logQueue.Count > 0
                        dicFiled = _logQueue.Dequeue()

                        dicFiled.Add($"{AppLogTable.ColNamesEnum.ServiceID}", $"{ServiceIndex}")
                        dicFiled.Add($"{AppLogTable.ColNamesEnum.AppName}", $"{AppName}")
                        dicFiled.Add($"{AppLogTable.ColNamesEnum.AppVersion}", $"{AppVersion}")

                        dicFiled.Add($"{AppLogTable.ColNamesEnum.ProjectName}", $"{ProjectName}")
                        dicFiled.Add($"{AppLogTable.ColNamesEnum.StationName}", $"{StationName}")
                        dicFiled.Add($"{AppLogTable.ColNamesEnum.TestPlan}", $"{TestPlan}")

                        Try
                            cmdText = db.CmdHelper.Insert(tableName, dicFiled)
                            db.ExecuteNonQuery(cmdText) '执行语句
                        Catch ex As Exception
                            Console.WriteLine($"Write LogQueue To Local DB Error: {ex.Message}")
                            Continue While
                        End Try


                        Try
                            cmdText = cmdHelper.DbInsert(UtsDb.RemotePublicDb, tableName, dicFiled)
                            DbConnector.SaveCmdStringToCacheTable(db, cmdText) '执行命令入缓存库
                        Catch ex As Exception
                            Console.WriteLine($"Write LogQueue To Chche DB Error: {ex.Message}")
                            Continue While
                        End Try
                    End While
                End SyncLock

                db.CommitTransaction()
                db.Close()
            End Using
        End Sub




        Public Sub Dispose() Implements IDisposable.Dispose


        End Sub
    End Class
End Namespace