' =============================================
' FTP Client
' Created: 2025-01-XX
' Purpose: Handle FTP file uploads to Repsly export location
'          Uploads XLSX files to FTP server before pushing to Repsly API
' =============================================

Imports System.Net
Imports System.IO
Imports Superbowl_Daily_2.ProjectFunctions
Imports Superbowl_Daily_2.SystemFunctions

Public Class FTPClient

    Private ReadOnly ftpHost As String
    Private ReadOnly ftpPort As Integer
    Private ReadOnly ftpUsername As String
    Private ReadOnly ftpPassword As String
    Private ReadOnly ftpFolder As String
    Private ReadOnly processName As String

    ' =============================================
    ' Constructor
    ' =============================================
    Public Sub New(Optional processName As String = "FTP Client")
        Me.ftpHost = My.Settings.FTPHost
        Me.ftpPort = CInt(My.Settings.FTPPort)
        Me.ftpUsername = My.Settings.FTPUsername
        Me.ftpPassword = My.Settings.FTPPassword
        Me.ftpFolder = My.Settings.FTPFolder
        Me.processName = processName
    End Sub

    ' =============================================
    ' Upload File to FTP
    ' =============================================
    Public Function UploadFile(localFilePath As String, remoteFileName As String) As Boolean
        Return UploadFile(localFilePath, remoteFileName, 0)
    End Function

    ' =============================================
    ' Upload File to FTP with Retry Logic
    ' =============================================
    Public Function UploadFile(localFilePath As String, remoteFileName As String, retryCount As Integer) As Boolean
        Dim maxRetries As Integer = 3
        Dim currentRetry As Integer = retryCount

        While currentRetry < maxRetries
            Try
                ' Verify local file exists
                If Not File.Exists(localFilePath) Then
                    WriteLog("error", processName, "FTP Upload", "Local file not found: " & localFilePath)
                    Return False
                End If

                ' Build FTP URL
                Dim ftpUrl As String = "ftp://" & ftpHost & ":" & ftpPort.ToString() & ftpFolder & "/" & remoteFileName
                WriteLog("info", processName, "FTP Upload", "Uploading: " & localFilePath & " to " & ftpUrl)

                ' Create FTP request
                Dim ftpRequest As FtpWebRequest = CType(WebRequest.Create(ftpUrl), FtpWebRequest)
                ftpRequest.Method = WebRequestMethods.Ftp.UploadFile
                ftpRequest.Credentials = New NetworkCredential(ftpUsername, ftpPassword)
                ftpRequest.UseBinary = True
                ftpRequest.UsePassive = True
                ftpRequest.KeepAlive = False
                ftpRequest.Timeout = 60000 ' 60 seconds

                ' Read file and upload
                Dim fileBytes As Byte() = File.ReadAllBytes(localFilePath)
                ftpRequest.ContentLength = fileBytes.Length

                Using requestStream As Stream = ftpRequest.GetRequestStream()
                    requestStream.Write(fileBytes, 0, fileBytes.Length)
                End Using

                ' Get response
                Using response As FtpWebResponse = CType(ftpRequest.GetResponse(), FtpWebResponse)
                    Dim statusCode As FtpStatusCode = response.StatusCode
                    Dim statusDescription As String = response.StatusDescription

                    If statusCode = FtpStatusCode.ClosingData OrElse 
                       statusCode = FtpStatusCode.FileActionOK OrElse
                       statusCode = FtpStatusCode.ClosingData Then
                        WriteLog("info", processName, "FTP Upload", "Success: " & statusDescription & " | File: " & remoteFileName)
                        Return True
                    Else
                        WriteLog("warning", processName, "FTP Upload", "Unexpected status: " & statusCode.ToString() & " - " & statusDescription)
                        Return True ' Still consider it success if file was uploaded
                    End If
                End Using

            Catch ex As WebException
                Dim ftpResponse As FtpWebResponse = TryCast(ex.Response, FtpWebResponse)
                If ftpResponse IsNot Nothing Then
                    WriteLog("error", processName, "FTP Upload Error", 
                             "Status: " & ftpResponse.StatusCode.ToString() & 
                             " | Description: " & ftpResponse.StatusDescription & 
                             " | Attempt: " & (currentRetry + 1).ToString() & "/" & maxRetries.ToString())
                Else
                    WriteLog("error", processName, "FTP Upload Exception", 
                             ex.Message & " | Attempt: " & (currentRetry + 1).ToString() & "/" & maxRetries.ToString())
                End If

                currentRetry += 1
                If currentRetry < maxRetries Then
                    ' Wait before retry (exponential backoff: 2, 4, 8 seconds)
                    Dim waitSeconds As Integer = CInt(Math.Pow(2, currentRetry))
                    WriteLog("info", processName, "FTP Upload Retry", "Waiting " & waitSeconds.ToString() & " seconds before retry...")
                    System.Threading.Thread.Sleep(waitSeconds * 1000)
                End If

            Catch ex As Exception
                WriteLog("error", processName, "FTP Upload Exception", 
                         ex.Message & " :: " & ex.StackTrace & 
                         " | Attempt: " & (currentRetry + 1).ToString() & "/" & maxRetries.ToString())
                
                currentRetry += 1
                If currentRetry < maxRetries Then
                    ' Wait before retry
                    Dim waitSeconds As Integer = CInt(Math.Pow(2, currentRetry))
                    WriteLog("info", processName, "FTP Upload Retry", "Waiting " & waitSeconds.ToString() & " seconds before retry...")
                    System.Threading.Thread.Sleep(waitSeconds * 1000)
                End If
            End Try
        End While

        WriteLog("error", processName, "FTP Upload Failed", "Failed after " & maxRetries.ToString() & " attempts: " & localFilePath)
        Return False
    End Function

    ' =============================================
    ' Test FTP Connection
    ' =============================================
    Public Function TestConnection() As Boolean
        Try
            Dim ftpUrl As String = "ftp://" & ftpHost & ":" & ftpPort.ToString() & ftpFolder & "/"
            WriteLog("info", processName, "FTP Test", "Testing connection to: " & ftpUrl)

            Dim ftpRequest As FtpWebRequest = CType(WebRequest.Create(ftpUrl), FtpWebRequest)
            ftpRequest.Method = WebRequestMethods.Ftp.ListDirectory
            ftpRequest.Credentials = New NetworkCredential(ftpUsername, ftpPassword)
            ftpRequest.UsePassive = True
            ftpRequest.Timeout = 30000 ' 30 seconds

            Using response As FtpWebResponse = CType(ftpRequest.GetResponse(), FtpWebResponse)
                WriteLog("info", processName, "FTP Test", "Connection successful: " & response.StatusDescription)
                Return True
            End Using

        Catch ex As Exception
            WriteLog("error", processName, "FTP Test Failed", ex.Message & " :: " & ex.StackTrace)
            Return False
        End Try
    End Function

    ' =============================================
    ' Get Full FTP Path
    ' =============================================
    Public Function GetFTPPath(fileName As String) As String
        Return "ftp://" & ftpHost & ":" & ftpPort.ToString() & ftpFolder & "/" & fileName
    End Function

End Class

