' SecureConfig.vb - Loads connection strings from environment variables.
' .env file is loaded from the root directory (parent of application folder) only.
' Credentials are never stored in Web.config or source control.

Imports System
Imports System.Collections.Generic
Imports System.IO
Imports System.Configuration
Imports System.Web

Namespace Stock_Control
  ''' <summary>
  ''' Loads environment variables from .env (root directory only) and system env.
  ''' Provides connection strings with fail-fast if required variables are missing.
  ''' </summary>
  Public NotInheritable Class SecureConfig
    Private Shared ReadOnly _lockObject As New Object()
    Private Shared _envVarsLoaded As Boolean = False

    Private Sub New()
    End Sub

    ''' <summary>
    ''' Load .env from root directory only (parent of application folder).
    ''' </summary>
    Private Shared Sub LoadEnvFile()
      Dim appRoot As String = Nothing
      If HttpRuntime.AppDomainAppPath <> Nothing Then
        appRoot = HttpRuntime.AppDomainAppPath.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)
      End If
      If String.IsNullOrEmpty(appRoot) Then
        appRoot = AppDomain.CurrentDomain.BaseDirectory
        If appRoot <> Nothing Then appRoot = appRoot.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)
      End If
      If String.IsNullOrEmpty(appRoot) Then Return

      ' Root directory = solution root (parent of project folder). When running from bin, appRoot is ...\Stock_Control\bin so go up two levels.
      Dim rootDir As String = Path.GetDirectoryName(appRoot)
      If rootDir <> Nothing AndAlso rootDir.EndsWith(Path.DirectorySeparatorChar & "bin", StringComparison.OrdinalIgnoreCase) Then
        rootDir = Path.GetDirectoryName(rootDir)
      End If
      If String.IsNullOrEmpty(rootDir) Then Return

      Dim envPath As String = Path.Combine(rootDir, ".env")
      If Not File.Exists(envPath) Then Return

      Try
        For Each line As String In File.ReadAllLines(envPath)
          line = line.Trim()
          If line.Length = 0 OrElse line.StartsWith("#") Then Continue For
          Dim idx As Integer = line.IndexOf("="c)
          If idx <= 0 Then Continue For
          Dim key As String = line.Substring(0, idx).Trim()
          Dim value As String = line.Substring(idx + 1).Trim()
          If key.Length = 0 Then Continue For
          ' Remove optional surrounding quotes
          If value.Length >= 2 AndAlso value.StartsWith(""""c) AndAlso value.EndsWith(""""c) Then
            value = value.Substring(1, value.Length - 2)
          End If
          Environment.SetEnvironmentVariable(key, value, EnvironmentVariableTarget.Process)
        Next
      Catch ex As Exception
        Throw New ConfigurationErrorsException("Warning: Could not load .env file: " & ex.Message, ex)
      End Try
    End Sub

    Private Shared Sub LoadEnvironmentVariables()
      If _envVarsLoaded Then Return
      SyncLock _lockObject
        If _envVarsLoaded Then Return
        LoadEnvFile()
        _envVarsLoaded = True
      End SyncLock
    End Sub

    ''' <summary>
    ''' Get connection string by config name. csStockControl requires env var STOCK_CONTROL_CONNECTION_STRING.
    ''' </summary>
    Public Shared Function GetConnectionString(ByVal connectionName As String) As String
      LoadEnvironmentVariables()
      Dim envVar As String = Nothing
      If String.Equals(connectionName, "csStockControl", StringComparison.OrdinalIgnoreCase) Then
        envVar = Environment.GetEnvironmentVariable("STOCK_CONTROL_CONNECTION_STRING")
      End If
      If String.IsNullOrEmpty(envVar) Then
        Throw New ConfigurationErrorsException(
          "Required environment variable for connection '" & connectionName & "' is not set. " &
          "Please set STOCK_CONTROL_CONNECTION_STRING in your .env file (in the solution root directory) or system environment variables.")
      End If
      Return envVar.Trim()
    End Function
  End Class
End Namespace
