Set-StrictMode -Version Latest

<#
.SYNOPSIS
Проверяет, что LinkPath — junction, указывающий на SourcePath.
#>
function Test-AgentSkillLink {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)] [string] $SourcePath,
        [Parameter(Mandatory)] [string] $LinkPath
    )

    $item = Get-Item -LiteralPath $LinkPath -Force -ErrorAction SilentlyContinue
    if ($null -eq $item -or $item.LinkType -ne 'Junction') { return $false }

    $actual = [System.IO.Path]::GetFullPath(($item.Target | Select-Object -First 1))
    $expected = [System.IO.Path]::GetFullPath($SourcePath)
    return [string]::Equals($actual.TrimEnd('\'), $expected.TrimEnd('\'), [StringComparison]::OrdinalIgnoreCase)
}

<#
.SYNOPSIS
Раскладывает навык по LinkPath junction'ом. Возвращает Created | AlreadyLinked | Copied.
Настоящий каталог никогда не удаляется автоматически.
#>
function Sync-AgentSkillLink {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)] [string] $SourcePath,
        [Parameter(Mandatory)] [string] $LinkPath,
        [switch] $AllowCopy
    )

    if (-not (Test-Path -LiteralPath $SourcePath)) {
        throw "нет исходного навыка: $SourcePath"
    }
    if (Test-AgentSkillLink -SourcePath $SourcePath -LinkPath $LinkPath) {
        return 'AlreadyLinked'
    }

    $existing = Get-Item -LiteralPath $LinkPath -Force -ErrorAction SilentlyContinue
    if ($null -ne $existing) {
        if ($existing.LinkType -ne 'Junction') {
            throw "$LinkPath существует и не является junction — удалите его вручную и повторите"
        }
        # Ссылка ведёт не туда: удаляем сам reparse point, не заходя в target.
        [System.IO.Directory]::Delete($LinkPath)
    }

    $parent = Split-Path -Parent $LinkPath
    if (-not (Test-Path -LiteralPath $parent)) {
        New-Item -ItemType Directory -Path $parent -Force | Out-Null
    }

    try {
        New-Item -ItemType Junction -Path $LinkPath -Value $SourcePath -ErrorAction Stop | Out-Null
        return 'Created'
    }
    catch {
        if (-not $AllowCopy) {
            throw "не удалось создать junction $LinkPath -> $SourcePath ($($_.Exception.Message)). Повторите с -AllowCopy, если копия допустима."
        }
        Copy-Item -LiteralPath $SourcePath -Destination $LinkPath -Recurse -Force -ErrorAction Stop
        return 'Copied'
    }
}

<#
.SYNOPSIS
Снимает junction по LinkPath. Возвращает Removed | Missing | Skipped.
Настоящие каталоги не трогает, в target не заходит.
#>
function Remove-AgentSkillLink {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)] [string] $LinkPath
    )

    $item = Get-Item -LiteralPath $LinkPath -Force -ErrorAction SilentlyContinue
    if ($null -eq $item) { return 'Missing' }

    # Проверяем именно атрибут, а не LinkType: junction с удалённым target
    # (ровно наш случай после checkout без plugin/skills) остаётся reparse point,
    # но полагаться на резолв target тут нельзя.
    $isReparse = $item.Attributes.HasFlag([System.IO.FileAttributes]::ReparsePoint)
    if (-not ($item -is [System.IO.DirectoryInfo]) -or -not $isReparse) {
        return 'Skipped'
    }

    # Удаляем сам reparse point: без -Recurse содержимое target не затрагивается.
    [System.IO.Directory]::Delete($LinkPath)
    return 'Removed'
}

Export-ModuleMember -Function Test-AgentSkillLink, Sync-AgentSkillLink, Remove-AgentSkillLink
