# Gitea Workspace Git Operations
#
# Workspace-level git integration with Gitea
#
# Version: 1.0.0

# Selective imports (ADR-025 Phase 3 Layer 2).
use lib_provisioning/gitea/api_client.nu [create-repository get-gitea-config get-repository]

# Initialize workspace as git repository
export def init-workspace-git [
    workspace_path: string
    workspace_name: string
    --remote: string = "gitea"  # gitea, github, gitlab, none
    --private: bool = true
] -> bool {
    let ws_path = $workspace_path | path expand

    if not ($ws_path | path exists) {
        error make {
            msg: $"Workspace path does not exist: ($ws_path)"
        }
    }

    # Initialize git repository
    cd $ws_path
    ^git init

    # Configure git
    ^git config user.name "Provisioning System"
    ^git config user.email "provisioning@system.local"

    # Create initial commit
    ^git add .
    ^git commit -m "Initial workspace commit"

    # Create main branch
    ^git branch -M main

    # Add remote if requested
    if $remote == "gitea" {
        let config = get-gitea-config
        let org = $config.repositories.workspaces_org

        # Create repository on Gitea
        let repo = create-repository $org $workspace_name $"Workspace: ($workspace_name)" $private

        let repo_url = $repo.clone_url

        # Add remote
        ^git remote add origin $repo_url

        # Push initial commit
        ^git push -u origin main

        print $"✓ Workspace initialized with Gitea remote: ($repo_url)"
    } else if $remote != "none" {
        print $"⚠️  Remote type '($remote)' not yet implemented"
    }

    true
}

# Create repository on Gitea for workspace
export def create-workspace-repo [
    workspace_name: string
    --description: string = ""
    --private: bool = true
] -> record {
    let config = get-gitea-config
    let org = $config.repositories.workspaces_org

    let desc = if ($description | is-empty) {
        $"Provisioning workspace: ($workspace_name)"
    } else {
        $description
    }

    create-repository $org $workspace_name $desc $private
}

# Clone workspace from Gitea
export def clone-workspace [
    workspace_identifier: string  # org/workspace-name or just workspace-name
    destination_path: string
    --branch: string = "main"
] -> bool {
    let config = get-gitea-config

    # Parse workspace identifier
    let parts = $workspace_identifier | split row "/"
    let repo_name = if ($parts | length) == 2 {
        $parts.1
    } else {
        $workspace_identifier
    }
    let org = if ($parts | length) == 2 {
        $parts.0
    } else {
        $config.repositories.workspaces_org
    }

    # Get repository info
    let repo = get-repository $org $repo_name
    let clone_url = $repo.clone_url

    # Clone repository
    ^git clone --branch $branch $clone_url $destination_path

    print $"✓ Workspace cloned from ($clone_url)"
    true
}

# Push workspace changes
export def push-workspace [
    workspace_path: string
    commit_message?: string
    --branch: string = "main"
    --add-all: bool = true
] -> bool {
    let ws_path = $workspace_path | path expand

    cd $ws_path

    # Check if git repository
    if not ($"($ws_path)/.git" | path exists) {
        error make {
            msg: "Not a git repository"
            help: "Initialize with 'workspace init --git'"
        }
    }

    # Add changes
    if $add_all {
        ^git add .
    }

    # Check if there are changes
    let status = ^git status --porcelain | complete
    if ($status.stdout | is-empty) {
        print "No changes to commit"
        return false
    }

    # Commit changes
    let msg = if ($commit_message | is-empty) {
        let timestamp = date now | format date "%Y-%m-%d %H:%M:%S"
        $"Workspace update: ($timestamp)"
    } else {
        $commit_message
    }

    ^git commit -m $msg

    # Push to remote
    ^git push origin $branch

    print $"✓ Workspace changes pushed to ($branch)"
    true
}

# Pull workspace changes
export def pull-workspace [
    workspace_path: string
    --branch: string = "main"
] -> bool {
    let ws_path = $workspace_path | path expand

    cd $ws_path

    # Check if git repository
    if not ($"($ws_path)/.git" | path exists) {
        error make {
            msg: "Not a git repository"
        }
    }

    # Pull changes
    ^git pull origin $branch

    print $"✓ Workspace updated from ($branch)"
    true
}

# Create branch
export def create-workspace-branch [
    workspace_path: string
    branch_name: string
    --from-branch: string = "main"
] -> bool {
    let ws_path = $workspace_path | path expand

    cd $ws_path

    # Create local branch
    ^git checkout -b $branch_name $from_branch

    # Push to remote
    ^git push -u origin $branch_name

    print $"✓ Branch created: ($branch_name)"
    true
}

# Switch branch
export def switch-workspace-branch [
    workspace_path: string
    branch_name: string
] -> bool {
    let ws_path = $workspace_path | path expand

    cd $ws_path

    # Switch branch
    ^git checkout $branch_name

    print $"✓ Switched to branch: ($branch_name)"
    true
}

# List branches
export def list-workspace-branches [
    workspace_path: string
    --remote: bool = false
] -> list {
    let ws_path = $workspace_path | path expand

    cd $ws_path

    if $remote {
        ^git branch -r | lines | each {|line| $line | str trim | str replace "origin/" ""}
    } else {
        ^git branch | lines | each {|line| $line | str trim | str replace "* " ""}
    }
}

# Delete branch
export def delete-workspace-branch [
    workspace_path: string
    branch_name: string
    --remote: bool = false
    --force: bool = false
] -> bool {
    let ws_path = $workspace_path | path expand

    cd $ws_path

    # Delete local branch
    if $force {
        ^git branch -D $branch_name
    } else {
        ^git branch -d $branch_name
    }

    # Delete remote branch
    if $remote {
        ^git push origin --delete $branch_name
    }

    print $"✓ Branch deleted: ($branch_name)"
    true
}

# Sync workspace (pull + push)
export def sync-workspace [
    workspace_path: string
    --branch: string = "main"
    --commit-message?: string
] -> record {
    let ws_path = $workspace_path | path expand

    # Pull latest changes
    pull-workspace $ws_path --branch $branch

    # Push local changes
    let pushed = push-workspace $ws_path $commit_message --branch $branch

    {
        pulled: true
        pushed: $pushed
        branch: $branch
    }
}

# Get workspace git status
export def get-workspace-git-status [
    workspace_path: string
] -> record {
    let ws_path = $workspace_path | path expand

    cd $ws_path

    # Check if git repository
    if not ($"($ws_path)/.git" | path exists) {
        return {
            is_git_repo: false
            branch: null
            status: null
            remote: null
        }
    }

    # Get current branch
    let branch = ^git branch --show-current | str trim

    # Get status
    let status = ^git status --porcelain | lines

    # Get remote
    let remote_result = (do {
        ^git remote get-url origin
    } | complete)

    let remote = if $remote_result.exit_code == 0 {
        $remote_result.stdout | str trim
    } else {
        null
    }

    # Get last commit
    let commit_result = (do {
        ^git log -1 --format="%H|%an|%ae|%at|%s"
    } | complete)

    let last_commit = if $commit_result.exit_code == 0 {
        $commit_result.stdout | str trim
    } else {
        null
    }

    let commit_info = if ($last_commit | is-not-empty) {
        let parts = $last_commit | split row "|"
        {
            hash: $parts.0
            author_name: $parts.1
            author_email: $parts.2
            timestamp: ($parts.3 | into int)
            message: $parts.4
        }
    } else {
        null
    }

    {
        is_git_repo: true
        branch: $branch
        status: $status
        remote: $remote
        last_commit: $commit_info
        has_changes: ($status | length) > 0
    }
}

# Get workspace remote info
export def get-workspace-remote-info [
    workspace_path: string
] -> record {
    let ws_path = $workspace_path | path expand

    cd $ws_path

    let remote_result = (do {
        ^git remote get-url origin
    } | complete)

    if $remote_result.exit_code != 0 {
        return {has_remote: false}
    }

    let remote_url = $remote_result.stdout | str trim

    # Parse Gitea URL
    let config = get-gitea-config
    let base_url = if $config.mode == "local" {
        $"http://localhost:($config.local.port)"
    } else {
        $config.remote.url
    }

    let is_gitea = $remote_url | str starts-with $base_url

    if $is_gitea {
        # Extract owner and repo from URL
        let parts = $remote_url | str replace $"($base_url)/" "" | str replace ".git" "" | split row "/"
        {
            has_remote: true
            type: "gitea"
            url: $remote_url
            owner: $parts.0
            repo: $parts.1
        }
    } else {
        {
            has_remote: true
            type: "external"
            url: $remote_url
        }
    }
}

# Check if workspace has uncommitted changes
export def has-uncommitted-changes [
    workspace_path: string
] -> bool {
    let status = get-workspace-git-status $workspace_path
    $status.has_changes
}

# Get workspace diff
export def get-workspace-diff [
    workspace_path: string
    --staged: bool = false
] -> string {
    let ws_path = $workspace_path | path expand

    cd $ws_path

    if $staged {
        ^git diff --staged
    } else {
        ^git diff
    }
}

# Stash workspace changes
export def stash-workspace-changes [
    workspace_path: string
    message?: string
] -> bool {
    let ws_path = $workspace_path | path expand

    cd $ws_path

    let msg = if ($message | is-empty) {
        "Workspace stash"
    } else {
        $message
    }

    ^git stash push -m $msg

    print "✓ Changes stashed"
    true
}

# Pop stashed changes
export def pop-workspace-stash [
    workspace_path: string
] -> bool {
    let ws_path = $workspace_path | path expand

    cd $ws_path

    ^git stash pop

    print "✓ Stash applied"
    true
}

# List workspace stashes
export def list-workspace-stashes [
    workspace_path: string
] -> list {
    let ws_path = $workspace_path | path expand

    cd $ws_path

    ^git stash list | lines
}
