<#
.SYNOPSIS
    Queries common user information from either Local Accounts or Active Directory.

.DESCRIPTION
    This script retrieves detailed information about user accounts.
    It can query local user accounts on the machine or Active Directory user accounts
    if the machine is domain-joined and the Active Directory module is available.

.PARAMETER UserName
    Specifies the username (SamAccountName for AD, or Name for Local) of the user
    to query. If omitted, all users based on the specified source will be listed.

.PARAMETER ActiveDirectory
    Use this switch to query Active Directory.
    Requires the 'ActiveDirectory' module to be installed and the machine to be
    connected to a domain. If not specified, local users are queried by default.

.PARAMETER IncludeGroups
    Use this switch to include group memberships for each user.
    This can take longer, especially for Active Directory.

.EXAMPLE
    .\GetUserInformation.ps1 -UserName "jdoe"

    Queries information for the local user 'jdoe'.

.EXAMPLE
    .\GetUserInformation.ps1 -ActiveDirectory -UserName "s.smith"

    Queries information for the Active Directory user 's.smith'.

.EXAMPLE
    .\GetUserInformation.ps1 -AllUsers -ActiveDirectory -IncludeGroups

    Lists all Active Directory users with their group memberships.

.EXAMPLE
    .\GetUserInformation.ps1

    Lists all local users on the machine.

.NOTES
    Author: ChatGPT (with improvements for clarity and robustness)
    Date: 2023-10-27
    Version: 1.1

    For Active Directory queries:
    - Ensure you have the ActiveDirectory module installed (part of RSAT tools).
    - Your user account needs appropriate permissions to read AD objects.
#>
[CmdletBinding(DefaultParameterSetName='AllUsers')]
param (
    [Parameter(ParameterSetName='SpecificUser', Position=0)]
    [string]$UserName,

    [Parameter(ParameterSetName='AllUsers')]
    [switch]$AllUsers,

    [Parameter()]
    [switch]$ActiveDirectory,

    [Parameter()]
    [switch]$IncludeGroups
)

function Get-LocalUserInformation {
    [CmdletBinding()]
    param (
        [string]$TargetUsername
    )

    Write-Host "Querying local user accounts..." -ForegroundColor Cyan

    $users = @()
    try {
        if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey('TargetUsername')) {
            # Try to get a specific local user
            $user = Get-LocalUser -Name $TargetUsername -ErrorAction SilentlyContinue
            if ($user) {
                $users += $user
            } else {
                Write-Warning "Local user '$TargetUsername' not found."
            }
        } else {
            # Get all local users
            $users = Get-LocalUser -ErrorAction Stop
        }

        if ($users.Count -eq 0) {
            Write-Warning "No local user accounts found matching the criteria."
            return
        }

        foreach ($user in $users) {
            $groups = @()
            if ($IncludeGroups) {
                try {
                    # Get-LocalUser has a .Groups property in PS 5.1+
                    # For older versions, one might have to iterate Get-LocalGroup and check members
                    $userGroups = $user.Groups | Select-Object -ExpandProperty Name
                    if ($userGroups) {
                        $groups = $userGroups
                    }
                }
                catch {
                    Write-Warning "Could not retrieve groups for local user $($user.Name): $($_.Exception.Message)"
                }
            }

            [PSCustomObject]@{
                Source           = 'Local'
                Username         = $user.Name
                FullName         = $user.FullName
                Description      = $user.Description
                Enabled          = $user.Enabled
                LastLogon        = 'N/A (Local)'
                EmailAddress     = 'N/A (Local)'
                Department       = 'N/A (Local)'
                Office           = 'N/A (Local)'
                PhoneNumber      = 'N/A (Local)'
                HomeDirectory    = 'N/A (Local)'
                ProfilePath      = 'N/A (Local)'
                Groups           = if ($groups.Count -gt 0) { $groups -join ', ' } else { 'None' }
                SID              = $user.SID.Value
                WhenCreated      = $user.CreationTime
            }
        }
    }
    catch {
        Write-Error "An error occurred while querying local users: $($_.Exception.Message)"
    }
}

function Get-ADUserInformation {
    [CmdletBinding()]
    param (
        [string]$TargetUsername
    )

    Write-Host "Querying Active Directory user accounts..." -ForegroundColor Cyan

    # Check if ActiveDirectory module is available
    if (-not (Get-Module -ListAvailable -Name ActiveDirectory)) {
        Write-Warning "The ActiveDirectory module is not installed or available."
        Write-Warning "Please install Remote Server Administration Tools (RSAT) for Active Directory Domain Services."
        Write-Warning "Cannot query Active Directory."
        return
    }

    # Import the module if not already loaded in the current session
    if (-not (Get-Module -Name ActiveDirectory -ErrorAction SilentlyContinue)) {
        try {
            Import-Module ActiveDirectory -ErrorAction Stop
            Write-Host "ActiveDirectory module loaded successfully." -ForegroundColor Green
        }
        catch {
            Write-Error "Failed to load ActiveDirectory module: $($_.Exception.Message)"
            return
        }
    }

    $propertiesToLoad = @(
        "SamAccountName", "DisplayName", "GivenName", "Surname", "Description", "Enabled",
        "LastLogonTimestamp", "EmailAddress", "OfficePhone", "Department", "Office",
        "HomeDirectory", "ProfilePath", "SID", "WhenCreated", "PasswordLastSet"
    )

    $adUsers = @()
    try {
        if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey('TargetUsername')) {
            # Try to get a specific AD user
            $user = Get-ADUser -Identity $TargetUsername -Properties $propertiesToLoad -ErrorAction SilentlyContinue
            if ($user) {
                $adUsers += $user
            } else {
                Write-Warning "Active Directory user '$TargetUsername' not found."
            }
        } else {
            # Get all AD users (excluding disabled or specific service accounts if desired, for now, all)
            $adUsers = Get-ADUser -Filter * -Properties $propertiesToLoad -ErrorAction Stop
        }

        if ($adUsers.Count -eq 0) {
            Write-Warning "No Active Directory user accounts found matching the criteria."
            return
        }

        foreach ($adUser in $adUsers) {
            $groups = @()
            if ($IncludeGroups) {
                try {
                    $userGroups = Get-ADPrincipalGroupMembership -Identity $adUser.SamAccountName | Select-Object -ExpandProperty Name
                    if ($userGroups) {
                        $groups = $userGroups
                    }
                }
                catch {
                    Write-Warning "Could not retrieve groups for AD user $($adUser.SamAccountName): $($_.Exception.Message)"
                }
            }

            # Convert LastLogonTimestamp from FileTime to DateTime
            $lastLogon = if ($adUser.LastLogonTimestamp) {
                [DateTime]::FromFileTime($adUser.LastLogonTimestamp)
            } else {
                "Not available" # Or "Never"
            }

            [PSCustomObject]@{
                Source           = 'Active Directory'
                Username         = $adUser.SamAccountName
                FullName         = $adUser.DisplayName
                Description      = $adUser.Description
                Enabled          = $adUser.Enabled
                LastLogon        = $lastLogon
                EmailAddress     = $adUser.EmailAddress
                Department       = $adUser.Department
                Office           = $adUser.Office
                PhoneNumber      = $adUser.OfficePhone
                HomeDirectory    = $adUser.HomeDirectory
                ProfilePath      = $adUser.ProfilePath
                Groups           = if ($groups.Count -gt 0) { $groups -join ', ' } else { 'None' }
                SID              = $adUser.SID.Value
                WhenCreated      = $adUser.WhenCreated
                PasswordLastSet  = $adUser.PasswordLastSet
            }
        }
    }
    catch {
        Write-Error "An error occurred while querying Active Directory users: $($_.Exception.Message)"
    }
}

# --- Main Script Logic ---
if ($ActiveDirectory) {
    if ($UserName) {
        Get-ADUserInformation -TargetUsername $UserName
    }
    else {
        Get-ADUserInformation
    }
} else {
    # Default to local users if -ActiveDirectory not specified
    if ($UserName) {
        Get-LocalUserInformation -TargetUsername $UserName
    }
    else {
        Get-LocalUserInformation
    }
}

# How to Use the Script:
#
#    Save: Copy the code above and save it in a file named GetUserInformation.ps1 (or any other .ps1 name) on your computer.
#
#    Open PowerShell:
#        Right-click on the PowerShell icon and select "Run as administrator" (recommended for querying all local users, though usually not strictly necessary for just reading common info).
#        Navigate to the directory where you saved the script using cd C:\path\to\your\script.
#
#    Execution Policy: If you haven't run PowerShell scripts before, you might need to adjust your execution policy. You can do this by running:
#
#    Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
#
#    Confirm with Y when prompted. You can revert this later with Set-ExecutionPolicy Restricted -Scope CurrentUser.
#
#    Run the Script:
#
#        To list all Local Users:
#
#        .\GetUserInformation.ps1
#
#        To query a specific Local User (e.g., "Administrator"):
#
#        .\GetUserInformation.ps1 -UserName "Administrator"
#
#        To list all Active Directory Users (if domain-joined and AD module installed):
#
#        .\GetUserInformation.ps1 -ActiveDirectory
#
#        (Be aware this might list many users in a large domain.)
#
#        To query a specific Active Directory User (e.g., "johndoe"):
#
#        .\GetUserInformation.ps1 -ActiveDirectory -UserName "johndoe"
#
#        To include Group Memberships (can be slower for many users):
#
#        .\GetUserInformation.ps1 -ActiveDirectory -IncludeGroups -UserName "johndoe"
#
#        or
#
#        .\GetUserInformation.ps1 -IncludeGroups # For local users
