# Als Administrator ausführen
# Testaufbau für Standalone DFS Namespace auf Windows Server 2016

$ErrorActionPreference = "Stop"

# =========================
# Konfiguration
# =========================
$ServerFqdn    = "srvwsm001.imagoverum.com"
$NamespaceName = "DFS"

$NamespacePath = "\\$ServerFqdn\$NamespaceName"
$RootPath      = "C:\$NamespaceName"

$Shares = @(
    @{ Name = "share1"; Path = "C:\share1" },
    @{ Name = "share2"; Path = "C:\share2" }
)

# =========================
# Hilfsfunktionen
# =========================
function Write-Step {
    param([string]$Text)
    Write-Host "`n=== $Text ===" -ForegroundColor Cyan
}

function Ensure-WindowsFeatureInstalled {
    param([string]$FeatureName)

    $feature = Get-WindowsFeature -Name $FeatureName
    if (-not $feature) {
        throw "Windows-Feature '$FeatureName' wurde nicht gefunden."
    }

    if ($feature.Installed) {
        Write-Host "Feature '$FeatureName' ist bereits installiert." -ForegroundColor Yellow
    }
    else {
        Write-Host "Installiere Feature '$FeatureName'..." -ForegroundColor Green
        Install-WindowsFeature -Name $FeatureName -IncludeManagementTools | Out-Null
        Write-Host "Feature '$FeatureName' wurde installiert." -ForegroundColor Green
    }
}

function Ensure-DirectoryExists {
    param([string]$Path)

    if (Test-Path -LiteralPath $Path) {
        Write-Host "Ordner existiert bereits: $Path" -ForegroundColor Yellow
    }
    else {
        New-Item -Path $Path -ItemType Directory -Force | Out-Null
        Write-Host "Ordner angelegt: $Path" -ForegroundColor Green
    }
}

function Ensure-ModifyAclEveryone {
    param([string]$Path)

    if (-not (Test-Path -LiteralPath $Path)) {
        throw "Pfad nicht gefunden: $Path"
    }

    $acl = Get-Acl -Path $Path

    $inheritanceFlags = [System.Security.AccessControl.InheritanceFlags]"ContainerInherit, ObjectInherit"
    $propagationFlags = [System.Security.AccessControl.PropagationFlags]::None
    $rights           = [System.Security.AccessControl.FileSystemRights]::Modify
    $accessType       = [System.Security.AccessControl.AccessControlType]::Allow

    $rule = New-Object System.Security.AccessControl.FileSystemAccessRule(
        "Everyone",
        $rights,
        $inheritanceFlags,
        $propagationFlags,
        $accessType
    )

    $existing = $false
    foreach ($entry in $acl.Access) {
        if (
            $entry.IdentityReference.Value -eq "Everyone" -and
            $entry.AccessControlType -eq "Allow" -and
            (($entry.FileSystemRights -band [System.Security.AccessControl.FileSystemRights]::Modify) -ne 0)
        ) {
            $existing = $true
            break
        }
    }

    if ($existing) {
        Write-Host "NTFS-Recht bereits vorhanden: Everyone Modify auf $Path" -ForegroundColor Yellow
    }
    else {
        $acl.AddAccessRule($rule) | Out-Null
        Set-Acl -Path $Path -AclObject $acl
        Write-Host "NTFS-Recht gesetzt: Everyone Modify auf $Path" -ForegroundColor Green
    }
}

function Ensure-SmbShareExists {
    param(
        [string]$Name,
        [string]$Path
    )

    $share = Get-SmbShare -Name $Name -ErrorAction SilentlyContinue

    if (-not $share) {
        New-SmbShare -Name $Name -Path $Path -FullAccess "Everyone" | Out-Null
        Write-Host "SMB-Share angelegt: \\$ServerFqdn\$Name -> $Path" -ForegroundColor Green
        return
    }

    Write-Host "SMB-Share existiert bereits: \\$ServerFqdn\$Name" -ForegroundColor Yellow

    if ($share.Path -ne $Path) {
        throw "Share '$Name' existiert bereits, zeigt aber auf '$($share.Path)' statt '$Path'. Bitte manuell korrigieren."
    }

    $shareAccess = Get-SmbShareAccess -Name $Name -ErrorAction SilentlyContinue
    $everyoneFull = $shareAccess | Where-Object {
        $_.Name -eq "Everyone" -and $_.AccessControlType -eq "Allow" -and $_.AccessRight -eq "Full"
    }

    if (-not $everyoneFull) {
        Grant-SmbShareAccess -Name $Name -AccountName "Everyone" -AccessRight Full -Force | Out-Null
        Write-Host "Share-Recht ergänzt: Everyone Full auf \\$ServerFqdn\$Name" -ForegroundColor Green
    }
    else {
        Write-Host "Share-Recht bereits vorhanden: Everyone Full auf \\$ServerFqdn\$Name" -ForegroundColor Yellow
    }
}

function Ensure-DfsRootExists {
    param(
        [string]$NamespacePath,
        [string]$TargetPath
    )

    $root = Get-DfsnRoot -Path $NamespacePath -ErrorAction SilentlyContinue

    if ($root) {
        Write-Host "DFS Namespace existiert bereits: $NamespacePath" -ForegroundColor Yellow
        return
    }

    if (-not (Get-SmbShare -Name $NamespaceName -ErrorAction SilentlyContinue)) {
        throw "Root-Share '$NamespaceName' existiert nicht. DFS Root kann nicht erstellt werden."
    }

    New-DfsnRoot -Path $NamespacePath -TargetPath $TargetPath -Type Standalone | Out-Null
    Write-Host "DFS Namespace angelegt: $NamespacePath" -ForegroundColor Green
}

function Ensure-DfsFolderExists {
    param(
        [string]$FolderPath,
        [string]$TargetPath
    )

    $folder = Get-DfsnFolder -Path $FolderPath -ErrorAction SilentlyContinue

    if (-not $folder) {
        New-DfsnFolder -Path $FolderPath -TargetPath $TargetPath | Out-Null
        Write-Host "DFS-Ordner angelegt: $FolderPath -> $TargetPath" -ForegroundColor Green
        return
    }

    Write-Host "DFS-Ordner existiert bereits: $FolderPath" -ForegroundColor Yellow

    $targets = Get-DfsnFolderTarget -Path $FolderPath -ErrorAction SilentlyContinue
    $targetExists = $targets | Where-Object { $_.TargetPath -eq $TargetPath }

    if (-not $targetExists) {
        New-DfsnFolderTarget -Path $FolderPath -TargetPath $TargetPath | Out-Null
        Write-Host "DFS-Target ergänzt: $FolderPath -> $TargetPath" -ForegroundColor Green
    }
    else {
        Write-Host "DFS-Target bereits vorhanden: $FolderPath -> $TargetPath" -ForegroundColor Yellow
    }
}

# =========================
# Start
# =========================
Write-Step "DFS Rolle sicherstellen"
Ensure-WindowsFeatureInstalled -FeatureName "FS-DFS-Namespace"

Write-Step "Root-Ordner und Shares sicherstellen"
Ensure-DirectoryExists -Path $RootPath
Ensure-ModifyAclEveryone -Path $RootPath
Ensure-SmbShareExists -Name $NamespaceName -Path $RootPath

Write-Step "Zielordner und Shares sicherstellen"
foreach ($s in $Shares) {
    Ensure-DirectoryExists -Path $s.Path
    Ensure-ModifyAclEveryone -Path $s.Path
    Ensure-SmbShareExists -Name $s.Name -Path $s.Path
}

Write-Step "DFS Namespace sicherstellen"
Ensure-DfsRootExists -NamespacePath $NamespacePath -TargetPath "\\$ServerFqdn\$NamespaceName"

Write-Step "DFS Ordner sicherstellen"
foreach ($s in $Shares) {
    $dfsFolderPath = "$NamespacePath\$($s.Name)"
    $targetPath    = "\\$ServerFqdn\$($s.Name)"
    Ensure-DfsFolderExists -FolderPath $dfsFolderPath -TargetPath $targetPath
}

Write-Step "Ergebnis"
Write-Host "Namespace: $NamespacePath" -ForegroundColor Green
foreach ($s in $Shares) {
    Write-Host " - $NamespacePath\$($s.Name) -> \\$ServerFqdn\$($s.Name)" -ForegroundColor Green
}

Write-Host "`nFertig." -ForegroundColor Green