Imports DigitalData.Modules.Database
Imports DigitalData.Modules.Interfaces
Imports DigitalData.Modules.Logging

Namespace SyncUsers
    Public Class SyncUsersFirebird
        Implements ISyncUsers

        Private ReadOnly _logConfig As LogConfig
        Private ReadOnly _logger As Logger
        Private ReadOnly _firebird As Database.Firebird

        Public Sub New(LogConfig As LogConfig, Firebird As Database.Firebird)
            _logConfig = LogConfig
            _logger = LogConfig.GetLogger()
            _firebird = Firebird
        End Sub

        Public Function SyncUsers(GroupName As String, Users As List(Of ADUser), PropertyMapping As List(Of AttributeMapping)) As List(Of ADUser) Implements ISyncUsers.SyncUsers
            Dim oGroupId As Integer
            Dim oSyncedUsers As New List(Of ADUser)

            Try
                _logger.Debug("Getting group Id for group [{0}]", GroupName)
                oGroupId = GetGroupId(GroupName)

                If oGroupId = 0 Then
                    _logger.Debug("Group [{0}] does not exist in database or is not enabled for sync.", GroupName)
                    Return oSyncedUsers
                End If

                _logger.Debug("Using group Id [{0}]", oGroupId)
            Catch ex As Exception
                _logger.Error(ex)
                Return oSyncedUsers
            End Try

            For Each oUser In Users
                Dim oUserId As Int64
                Dim oUserExists As Boolean = False

                ' Check if user already exists
                Try
                    _logger.Debug("Checking if user [{0}] exists", oUser)
                    oUserId = GetUserId(oUser.samAccountName)
                    oUserExists = Not IsNothing(oUserId)
                    _logger.Debug("User [{0}] exists in database: ", oUser, oUserExists)
                Catch ex As Exception
                    _logger.Error(ex)
                    _logger.Warn("Could not get UserId for user. Skipping")
                    Continue For
                End Try

                ' I user does not exist, create a new user
                Try
                    If Not oUserExists Then
                        _logger.Debug("Creating new user for [{0}]", oUser)
                        oUserId = CreateUser(oUser)
                        _logger.Debug("User created with Id [{0}]", oUserId)
                    End If
                Catch ex As Exception
                    _logger.Error(ex)
                    _logger.Warn("Could not create user. Skipping")
                    Continue For
                End Try

                ' Add the user to group
                Try
                    AddUserToGroup(oUserId, oGroupId)
                Catch ex As Exception
                    _logger.Error(ex)
                    _logger.Warn("Could not add user to group. Skipping")
                    Continue For
                End Try

                oSyncedUsers.Add(oUser)
            Next

            Return oSyncedUsers
        End Function

        Private Function AddUserToGroup(UserId As Integer, GroupId As Integer) As Boolean Implements ISyncUsers.AddUserToGroup
            Try
                Dim oSQL = $"SELECT FNICM_RADM_NEW_USER2GROUP({UserId}, {GroupId}, 'AD-Sync') from RDB$DATABASE"
                Dim oRecordId = _firebird.GetScalarValue(oSQL)

                If IsDBNull(oRecordId) Then
                    _logger.Warn("UserId {0} - GroupId {1} relation already exists.", UserId, GroupId)
                    Return False
                End If

                Return True
            Catch ex As Exception
                _logger.Error(ex)
                Throw ex
            End Try
        End Function
        Private Function GetGroupId(GroupName As String) As Integer Implements ISyncUsers.GetGroupId
            Try
                Dim oSQL As String = $"SELECT FNICM_GET_RECORD4SYSKEY('{GroupName}','002-NAME') from RDB$DATABASE"
                Dim oGroupId = _firebird.GetScalarValue(oSQL)

                If IsDBNull(oGroupId) OrElse oGroupId = 0 Then
                    _logger.Debug("Group {0} not found in database", GroupName)
                    Return Nothing
                End If

                Return oGroupId
            Catch ex As Exception
                _logger.Error(ex)
                Throw ex
            End Try
        End Function
        Private Function GetUserId(UserName As String) As Integer Implements ISyncUsers.GetUserId
            Try
                Dim oSQL As String = $"SELECT FNICM_GET_RECORD4SYSKEY('{UserName}','001-USRNAME') from RDB$DATABASE"
                Dim oResult = _firebird.GetScalarValue(oSQL)

                If IsDBNull(oResult) Then
                    Return Nothing
                End If

                Return oResult
            Catch ex As Exception
                _logger.Error(ex)
                Throw ex
            End Try
        End Function
        Private Function CreateUser(User As ADUser) As Integer Implements ISyncUsers.CreateUser
            Try
                Dim oSQL = $"SELECT FNICM_RADM_NEW_USER('{User?.GivenName}', '{User?.Surname}', '{User?.samAccountName}', 'AD-Sync') from RDB$DATABASE"
                Dim oUserId As Integer = _firebird.GetScalarValue(oSQL)

                Return oUserId
            Catch ex As Exception
                _logger.Error(ex)
                Throw ex
            End Try
        End Function

        Public Sub AddCustomAttributesToUser(User As ADUser, UserId As Integer) Implements ISyncUsers.AddCustomAttributesToUser
            Throw New NotImplementedException()
        End Sub
    End Class
End Namespace
