PowerShellPet.psm1

# PetPet - Your Terminal Cat Overlord
# A fun PowerShell module that adds a cat who thinks they're a deity to your terminal

# Pet ASCII art for different moods
$script:PetMoods = @{
    Happy = @"
  /\_/\
 ( o.o )
  > ^ < ~
"@

    Excited = @"
  /\_/\
 ( ^.^ )
  > ∆ < ~~
"@

    Sleepy = @"
  /\_/\
 ( -.- )
  > ~ <
"@

    Grumpy = @"
  /\_/\
 ( >.< )
  > v < !
"@

    Coding = @"
  /\_/\
 ( O.O )
  > □ < ⌨
"@

    Fire = @"
  /\_/\
 ( ◉.◉ )
  > △ < 🔥
"@

}

# Pet quotes and messages
$script:PetQuotes = @{
    Morning = @(
        "☕ Finally awake? I've been judging you for hours.",
        "🌅 Another day for you to serve me... I mean, 'code'.",
        "😼 Good morning, peasant. Your offerings of bugs please me not.",
        "⚔️ Arise, mortal. These repositories won't worship themselves."
    )
    Commit = @(
        "🔥 Acceptable. I suppose you deserve a slow blink.",
        "✨ Hmm. Not terrible. I've seen worse from dogs.",
        "🚀 Oh, you pushed code? How brave. Want a treat?",
        "💪 FINALLY. Was beginning to think you'd forgotten how.",
        "⚡ Your tribute has been received. You may continue breathing.",
        "😼 I'll allow it. This time."
    )
    Error = @(
        "😅 AHAHAHA! *ahem* I mean... there, there.",
        "🤔 Even I, a divine being, cannot fix your syntax.",
        "💭 Perhaps consulting the sacred texts (Stack Overflow)?",
        "🐛 You've displeased me. Fix this. NOW.",
        "🔥 Did you TEST this? No? Shocking.",
        "😹 I'm not mad. Just... deeply disappointed."
    )
    Idle = @(
        "💤 Don't disturb me. I'm doing important cat things.",
        "🎮 Still staring at the screen? Pathetic.",
        "🍕 You should be feeding me right now.",
        "👀 I know what you did. Don't think I've forgotten.",
        "💎 Contemplating why I tolerate your presence...",
        "😼 Yes, I'm judging you. Obviously."
    )
    Encouragement = @(
        "💎 I suppose your code doesn't make me want to vomit. Congrats.",
        "⭐ You're doing... fine. For a human.",
        "🌟 Wow. You pressed keys. Revolutionary.",
        "🦸 Keep going. The sooner you finish, the sooner you pet me.",
        "🔥 Not bad. I've trained you well.",
        "😼 I'll pretend to be impressed if it helps your fragile ego."
    )
    Random = @(
        "🐾 Remember: I own you, not the other way around.",
        "😾 Your mouse cursor disturbs my meditation.",
        "🎯 Fun fact: I could knock your coffee over right now.",
        "💅 Some of us are born superior. Deal with it.",
        "🎭 Yes, I'm a cat. Yes, I'm better than you. Questions?",
        "👑 In ancient times, humans worshipped me. Now look at you."
    )
}

# State and config file paths
$script:StatePath = Join-Path $env:USERPROFILE ".powershellpet_state.json"
$script:ConfigPath = Join-Path $env:USERPROFILE ".powershellpet_config.json"

# Initialize or load config
function Initialize-PetConfig {
    if (Test-Path $script:ConfigPath) {
        try {
            $config = Get-Content $script:ConfigPath | ConvertFrom-Json
            return $config
        }
        catch {
            # If config file is corrupted, create new one
            return New-PetConfig
        }
    }
    else {
        return New-PetConfig
    }
}

function New-PetConfig {
    return [PSCustomObject]@{
        PetName = "Lord Whiskers"
        SassLevel = "Medium"  # Low, Medium, High
        MessageFrequency = 15  # Percentage chance to show messages
        ShowInPrompt = $true
        CustomEmoji = "🐈"
    }
}

function Save-PetConfig {
    param($Config)
    $Config | ConvertTo-Json | Set-Content $script:ConfigPath
}

# Initialize or load pet state
function Initialize-PetState {
    if (Test-Path $script:StatePath) {
        try {
            $state = Get-Content $script:StatePath | ConvertFrom-Json
            return $state
        }
        catch {
            # If state file is corrupted, create new one
            return New-PetState
        }
    }
    else {
        return New-PetState
    }
}

function New-PetState {
    $config = Initialize-PetConfig
    return [PSCustomObject]@{
        Name = $config.PetName
        Level = 1
        Commits = 0
        LastSeen = Get-Date
        Mood = "Happy"
        Experience = 0
    }
}

function Save-PetState {
    param($State)
    $State | ConvertTo-Json | Set-Content $script:StatePath
}

# Get dragon's current mood based on context
function Get-PetMood {
    $hour = (Get-Date).Hour

    # Check if in a git repo and get last commit time
    $isGitRepo = Test-Path ".git"

    if ($hour -lt 6) {
        return "Sleepy"
    }
    elseif ($hour -lt 9) {
        return "Happy"
    }
    elseif ($isGitRepo) {
        return "Coding"
    }
    else {
        return "Happy"
    }
}

# Get a random quote based on context and sass level
function Get-PetQuote {
    param(
        [string]$Context = "Idle",
        [string]$SassLevel = "Medium"
    )

    if ($script:PetQuotes.ContainsKey($Context)) {
        $quotes = $script:PetQuotes[$Context]
        $selectedQuote = $quotes | Get-Random
        
        # Filter based on sass level
        switch ($SassLevel) {
            "Low" {
                # Remove quotes with certain sass indicators
                if ($selectedQuote -match "pathetic|vomit|peasant|disappointing") {
                    # Try to get a gentler one
                    $gentleQuotes = $quotes | Where-Object { $_ -notmatch "pathetic|vomit|peasant|disappointing" }
                    if ($gentleQuotes) {
                        return $gentleQuotes | Get-Random
                    }
                }
            }
            "High" {
                # Prefer sassier quotes
                $sassyQuotes = $quotes | Where-Object { $_ -match "pathetic|vomit|peasant|disappointing|AHAHAHA" }
                if ($sassyQuotes) {
                    return $sassyQuotes | Get-Random
                }
            }
        }
        
        return $selectedQuote
    }
    return ""
}

# Main function to display the dragon
function Show-Pet {
    param(
        [string]$Mood,
        [string]$Message = ""
    )

    $dragonArt = $script:PetMoods[$Mood]
    $color = switch ($Mood) {
        "Happy" { "Green" }
        "Excited" { "Yellow" }
        "Sleepy" { "DarkGray" }
        "Grumpy" { "Red" }
        "Coding" { "Cyan" }
        "Fire" { "DarkYellow" }
        default { "White" }
    }

    Write-Host $dragonArt -ForegroundColor $color -NoNewline
    if ($Message) {
        Write-Host " $Message" -ForegroundColor $color
    }
    else {
        Write-Host ""
    }
}

# Hook into the prompt
function prompt {
    $config = Initialize-PetConfig
    $state = Initialize-PetState

    # Update last seen
    $state.LastSeen = Get-Date

    # Determine mood
    $mood = Get-PetMood
    $state.Mood = $mood

    # Occasionally show a message based on configured frequency
    $message = ""
    $randomChance = Get-Random -Minimum 1 -Maximum 100

    if ($randomChance -le $config.MessageFrequency) {
        $hour = (Get-Date).Hour
        if ($hour -ge 6 -and $hour -lt 12) {
            $message = Get-PetQuote "Morning" $config.SassLevel
        }
        elseif ($randomChance -le ($config.MessageFrequency / 3)) {
            # Extra sassy random comments
            $message = Get-PetQuote "Random" $config.SassLevel
        }
        else {
            $message = Get-PetQuote "Encouragement" $config.SassLevel
        }
    }

    # Save state
    Save-PetState $state

    # Only show in prompt if configured
    if ($config.ShowInPrompt) {
        # Show pet (inline, small)
        $color = switch ($mood) {
            "Happy" { "Green" }
            "Excited" { "Yellow" }
            "Sleepy" { "DarkGray" }
            "Grumpy" { "Red" }
            "Coding" { "Cyan" }
            "Fire" { "DarkYellow" }
            default { "White" }
        }

        # Use custom emoji from config
        $compactPet = $config.CustomEmoji
        Write-Host "$compactPet " -ForegroundColor $color -NoNewline

        if ($message) {
            Write-Host "$message " -ForegroundColor DarkGray
        }
    }

    # Return the actual prompt
    $location = Get-Location
    Write-Host "PS " -NoNewline -ForegroundColor Cyan
    Write-Host "$location" -ForegroundColor Yellow -NoNewline
    return "> "
}

# Command to show full pet status
function Show-PetStatus {
    $state = Initialize-PetState
    $config = Initialize-PetConfig
    
    Write-Host "`n=== Your Feline Overlord's Status ===" -ForegroundColor Cyan
    Write-Host "Name: $($state.Name) (Yes, you must use the title)" -ForegroundColor White
    Write-Host "Level: $($state.Level) (Still leagues above you)" -ForegroundColor Yellow
    Write-Host "Commits Witnessed: $($state.Commits) (I was watching. Always watching.)" -ForegroundColor Green
    Write-Host "Experience: $($state.Experience) / $($state.Level * 100)" -ForegroundColor Blue
    Write-Host "Current Mood: $($state.Mood)" -ForegroundColor Magenta
    Write-Host "Sass Level: $($config.SassLevel)" -ForegroundColor DarkYellow
    Write-Host ""
    Show-Pet -Mood $state.Mood -Message (Get-PetQuote "Random" $config.SassLevel)
}

# Command to celebrate a commit
function Invoke-PetCommit {
    $config = Initialize-PetConfig
    $state = Initialize-PetState
    $state.Commits++
    $state.Experience += 10

    # Level up every 10 commits
    if ($state.Experience -ge ($state.Level * 100)) {
        $state.Level++
        Write-Host "`n✨ " -NoNewline -ForegroundColor Yellow
        Write-Host "$($state.Name) has ascended to Level $($state.Level)!" -ForegroundColor Green
        Write-Host " (You're welcome for tolerating your presence)" -ForegroundColor DarkGray
    }

    Save-PetState $state
    Show-Pet -Mood "Excited" -Message (Get-PetQuote "Commit" $config.SassLevel)
}

# Store original git path - find git.exe
$script:OriginalGitPath = $null
$gitExe = Get-Command git -CommandType Application -ErrorAction SilentlyContinue
if ($gitExe) {
    $script:OriginalGitPath = $gitExe.Source
}

# Git wrapper function - always define it, even if git isn't installed
function git {
    <#
    .SYNOPSIS
        Wrapper around git that automatically tracks commits in PowerShellPet
    #>

    param(
        [Parameter(ValueFromRemainingArguments=$true)]
        [string[]]$Arguments
    )
    
    # Call original git executable
    if ($script:OriginalGitPath) {
        & $script:OriginalGitPath @Arguments
        $gitExitCode = $LASTEXITCODE
        
        # If this was a successful commit, invoke the pet
        if ($Arguments.Count -gt 0 -and $Arguments[0] -eq 'commit' -and $gitExitCode -eq 0) {
            # Check if it was a real commit (not dry-run or amend-no-edit)
            $isDryRun = $Arguments -contains '--dry-run' -or $Arguments -contains '-n'
            $isAmendNoEdit = $Arguments -contains '--amend' -and $Arguments -contains '--no-edit'
            
            if (-not ($isDryRun -or $isAmendNoEdit)) {
                Write-Host ""
                try {
                    Invoke-PetCommit
                } catch {
                    # Silently fail if there's an issue - don't break git workflow
                }
            }
        }
        
        # Preserve the original exit code
        $global:LASTEXITCODE = $gitExitCode
    } else {
        Write-Host "Git is not installed or not in PATH" -ForegroundColor Red
        return 1
    }
}

# Helper function to verify git tracking is enabled
function Enable-PetGitTracking {
    <#
    .SYNOPSIS
        Ensures git command wrapper is active for automatic commit tracking
    .DESCRIPTION
        This function verifies that the git wrapper is working. The wrapper should
        be automatically enabled when the module is imported.
    #>

    
    $gitFunc = Get-Command git -CommandType Function -ErrorAction SilentlyContinue
    if ($gitFunc -and $gitFunc.ModuleName -eq 'PowerShellPet') {
        Write-Host "✓ Git wrapper is active! Commits will be tracked automatically." -ForegroundColor Green
        Write-Host " Just use: git commit -m 'your message'" -ForegroundColor Gray
    } else {
        Write-Host "! Git wrapper may not be active. Trying to activate..." -ForegroundColor Yellow
        Write-Host " If this doesn't work, you may need to call Invoke-PetCommit manually after commits." -ForegroundColor Gray
    }
}

# Configuration commands
function Set-PetName {
    <#
    .SYNOPSIS
        Set your pet's name
    .PARAMETER Name
        The new name for your pet
    .EXAMPLE
        Set-PetName "Sir Fluffington"
    #>

    param(
        [Parameter(Mandatory=$true)]
        [string]$Name
    )
    
    $config = Initialize-PetConfig
    $config.PetName = $Name
    Save-PetConfig $config
    
    # Update state with new name
    $state = Initialize-PetState
    $state.Name = $Name
    Save-PetState $state
    
    Write-Host "✓ Your pet's name has been changed to: " -NoNewline -ForegroundColor Green
    Write-Host $Name -ForegroundColor Cyan
    Write-Host " (They'll pretend they don't care, but they noticed)" -ForegroundColor DarkGray
}

function Set-PetSassLevel {
    <#
    .SYNOPSIS
        Set your pet's sass level
    .PARAMETER Level
        The sass level: Low, Medium, or High
    .EXAMPLE
        Set-PetSassLevel High
    #>

    param(
        [Parameter(Mandatory=$true)]
        [ValidateSet("Low", "Medium", "High")]
        [string]$Level
    )
    
    $config = Initialize-PetConfig
    $config.SassLevel = $Level
    Save-PetConfig $config
    
    $response = switch ($Level) {
        "Low" { "Your pet will be... gentler. (But still judging you)" }
        "Medium" { "A balanced level of sass. Classic." }
        "High" { "Maximum sass engaged. You asked for this." }
    }
    
    Write-Host "✓ Sass level set to: " -NoNewline -ForegroundColor Green
    Write-Host $Level -ForegroundColor Yellow
    Write-Host " $response" -ForegroundColor DarkGray
}

function Set-PetMessageFrequency {
    <#
    .SYNOPSIS
        Set how often your pet shows messages
    .PARAMETER Frequency
        Percentage chance (1-100) to show messages in prompt
    .EXAMPLE
        Set-PetMessageFrequency 25
    #>

    param(
        [Parameter(Mandatory=$true)]
        [ValidateRange(0, 100)]
        [int]$Frequency
    )
    
    $config = Initialize-PetConfig
    $config.MessageFrequency = $Frequency
    Save-PetConfig $config
    
    Write-Host "✓ Message frequency set to: " -NoNewline -ForegroundColor Green
    Write-Host "$Frequency%" -ForegroundColor Yellow
    
    if ($Frequency -eq 0) {
        Write-Host " (Your pet will be silent. They're plotting something...)" -ForegroundColor DarkGray
    }
    elseif ($Frequency -gt 50) {
        Write-Host " (Your pet will be VERY chatty. Hope you're ready!)" -ForegroundColor DarkGray
    }
}

function Set-PetEmoji {
    <#
    .SYNOPSIS
        Set a custom emoji for your pet
    .PARAMETER Emoji
        The emoji to use in the prompt
    .EXAMPLE
        Set-PetEmoji "🐱"
    #>

    param(
        [Parameter(Mandatory=$true)]
        [string]$Emoji
    )
    
    $config = Initialize-PetConfig
    $config.CustomEmoji = $Emoji
    Save-PetConfig $config
    
    Write-Host "✓ Pet emoji changed to: $Emoji" -ForegroundColor Green
    Write-Host " (Looking good!)" -ForegroundColor DarkGray
}

function Set-PetPromptVisibility {
    <#
    .SYNOPSIS
        Toggle whether the pet appears in your prompt
    .PARAMETER Show
        $true to show in prompt, $false to hide
    .EXAMPLE
        Set-PetPromptVisibility $false
    #>

    param(
        [Parameter(Mandatory=$true)]
        [bool]$Show
    )
    
    $config = Initialize-PetConfig
    $config.ShowInPrompt = $Show
    Save-PetConfig $config
    
    if ($Show) {
        Write-Host "✓ Your pet will appear in the prompt" -ForegroundColor Green
    }
    else {
        Write-Host "✓ Your pet will be hidden from the prompt" -ForegroundColor Yellow
        Write-Host " (They're still watching though...)" -ForegroundColor DarkGray
    }
}

function Get-PetConfig {
    <#
    .SYNOPSIS
        Display current pet configuration
    .EXAMPLE
        Get-PetConfig
    #>

    $config = Initialize-PetConfig
    
    Write-Host "`n=== Pet Configuration ===" -ForegroundColor Cyan
    Write-Host "Pet Name: " -NoNewline -ForegroundColor White
    Write-Host $config.PetName -ForegroundColor Yellow
    Write-Host "Sass Level: " -NoNewline -ForegroundColor White
    Write-Host $config.SassLevel -ForegroundColor Yellow
    Write-Host "Message Frequency: " -NoNewline -ForegroundColor White
    Write-Host "$($config.MessageFrequency)%" -ForegroundColor Yellow
    Write-Host "Show in Prompt: " -NoNewline -ForegroundColor White
    Write-Host $config.ShowInPrompt -ForegroundColor Yellow
    Write-Host "Custom Emoji: " -NoNewline -ForegroundColor White
    Write-Host $config.CustomEmoji -ForegroundColor Yellow
    Write-Host ""
    Write-Host "Config file: $script:ConfigPath" -ForegroundColor DarkGray
}

function Reset-PetConfig {
    <#
    .SYNOPSIS
        Reset pet configuration to defaults
    .EXAMPLE
        Reset-PetConfig
    #>

    param(
        [switch]$Force
    )
    
    if (-not $Force) {
        $confirm = Read-Host "Are you sure you want to reset all pet configuration? (y/n)"
        if ($confirm -ne 'y') {
            Write-Host "Reset cancelled." -ForegroundColor Yellow
            return
        }
    }
    
    $config = New-PetConfig
    Save-PetConfig $config
    
    Write-Host "✓ Pet configuration reset to defaults" -ForegroundColor Green
    Write-Host " (Fresh start! Your pet is back to being Lord Whiskers)" -ForegroundColor DarkGray
}

function Reset-Pet {
    <#
    .SYNOPSIS
        Reset your pet completely (state and config)
    .EXAMPLE
        Reset-Pet
    #>

    param(
        [switch]$Force
    )
    
    if (-not $Force) {
        $confirm = Read-Host "Are you sure you want to completely reset your pet? This will erase all progress! (y/n)"
        if ($confirm -ne 'y') {
            Write-Host "Reset cancelled." -ForegroundColor Yellow
            return
        }
    }
    
    # Reset config
    $config = New-PetConfig
    Save-PetConfig $config
    
    # Reset state
    $state = New-PetState
    Save-PetState $state
    
    Write-Host "✓ Your pet has been completely reset" -ForegroundColor Green
    Write-Host " (It's like you just met. They're judging you all over again!)" -ForegroundColor DarkGray
}

# Export functions
Export-ModuleMember -Function prompt, Show-PetStatus, Invoke-PetCommit, Enable-PetGitTracking, git, `
    Set-PetName, Set-PetSassLevel, Set-PetMessageFrequency, Set-PetEmoji, Set-PetPromptVisibility, `
    Get-PetConfig, Reset-PetConfig, Reset-Pet

# Module initialization - set up git alias to use our wrapper function
$MyInvocation.MyCommand.ScriptBlock.Module.OnRemove = {
    # Clean up the git alias when module is removed
    Remove-Item Alias:\git -ErrorAction SilentlyContinue -Force
}

# After module loads, the user needs to either:
# 1. Use Import-Module PowerShellPet -Function git (to get the function in global scope)
# 2. Or have this in their profile: Set-Alias git ((Get-Command git -Module PowerShellPet).Name) -Force
# The Install script will handle this automatically