param (
    [Parameter(Mandatory)]
    [ValidateScript({
        Test-Path $_ -PathType Leaf
    })]
    [string]$Path
)

process {
Add-Type -AssemblyName System.Management.Automation
$script_path_raw = Get-Item $Path
	$script_name = $script_path_raw.Name
	$script_path = $script_path_raw | Select-Object -ExpandProperty FullName
$tokens = $null
$errors = $null
$ast = [System.Management.Automation.Language.Parser]::ParseFile($script_path, [ref]$tokens, [ref]$errors)

if ($errors.Count -gt 0) {
    throw "Parse errors found: $($errors | ForEach-Object { $_.Message })"
}

$paramBlock = $ast.ParamBlock
if (-not $paramBlock) {
    throw "No param() block found at the script level."
}

$cmdletBindingAttr = $paramBlock.Attributes | Where-Object { $_.TypeName.Name -eq 'CmdletBinding' }

$defaultParamSet = $cmdletBindingAttr.NamedArguments |
    Where-Object { $_.ArgumentName -eq 'DefaultParameterSetName' } |
    Select-Object -ExpandProperty Argument |
    Select-Object -ExpandProperty Value

$parameters = @()

foreach ($param in $paramBlock.Parameters) {
    $paramName = $param.Name.VariablePath.UserPath

    # Fix the type name
    $staticType = $param.StaticType
    if ($staticType.IsGenericType -and $staticType.Name -eq 'Nullable`1') {
        $innerType = $staticType.GenericTypeArguments[0].Name
        $paramType = "Nullable[$innerType]"
    } else {
        $paramType = $staticType.Name
    }

    $aliases = @()
    $validations = @()
    $parameterSets = @()
    $description = $null
    $helpMessage = $null

    foreach ($attr in $param.Attributes) {
        switch ($attr.TypeName.Name) {
            'Parameter' {

                $mandatory = $false
                $parametersetname = 'Default'
                $position = $null
                $frompipeline = $null
                $frompipeline_by_property = $null
                $helpmessage = $null

                foreach ($arg in $attr.NamedArguments) {
                    switch ($arg.ArgumentName) {
                        'Mandatory' {
                            $mandatory = $arg.Argument.Extent.Text -eq '$true'
                        }
                        'Position' {
                            $position = $arg.Argument.Value
                        }
                        'ParameterSetName' {
                            $parametersetname = $arg.Argument.Value
                        }
                        'ValueFromPipeline' {
                            $frompipeline = $arg.Argument.Extent.Text -eq '$true'
                        }
                        'ValueFromPipelineByPropertyName' {
                            $frompipeline_by_property = $arg.Argument.Extent.Text -eq '$true'
                        }
                        'HelpMessage' {
                            $helpMessage = $arg.Argument.Value
                        }
                    }
                }

                $paramInfo = @{
                    name = $parametersetname
                    mandatory = $mandatory
                }

                if($null -ne $position) {
                    $paramInfo.position = $position
                }

                if($null -ne $frompipeline) {
                    $paramInfo.valueFromPipeline = $frompipeline
                }

                if($null -ne $frompipeline_by_property) {
                    $paramInfo.valueFromPipelineByPropertyName = $frompipeline_by_property
                }

                $parameterSets += [pscustomobject]$paramInfo
                break
            }
            'Alias' {
                $aliases += $attr.PositionalArguments.Value
                break
            }
            { $_ -like 'Validate*' } {
                $val = @{
                    type = $attr.TypeName.Name
                }

                if ($attr.TypeName.Name -eq 'ValidateRange') {
                    $val.min = $attr.PositionalArguments[0].Value
                    $val.max = $attr.PositionalArguments[1].Value
                } elseif ($attr.TypeName.Name -eq 'ValidateSet') {
                    $val.values = $attr.PositionalArguments.Value
                } elseif ($attr.TypeName.Name -eq 'ValidateScript') {
                    $val.value = $attr.PositionalArguments.ScriptBlock.Extent.Text
                } elseif ($attr.TypeName.Name -eq 'ValidatePattern') {
                    $val.value = $attr.PositionalArguments.Value
                }

                $validations += [pscustomobject]$val
                break
            }
        }
    }

    if ($parameterSets.Count -eq 0) {
        $parameterSets += [pscustomobject]@{
            name = "Default"
            mandatory = $false
        }
    }

    $parameters += [pscustomobject]@{
        name = $paramName
        type = $paramType
        aliases = $aliases
        description = $description
        helpMessage = $helpMessage
        validations = $validations
        parameterSets = $parameterSets
    }
}

$result = [pscustomobject]@{
    name = $script_name
    path = $script_path
    parameters = $parameters
    #cmdletBinding = [pscustomobject]@{
    defaultParameterSetName = $defaultParamSet ?? "Default"
    #}
}

return $result 
}