# Gitea API Client
#
# REST API v1 client for Gitea operations
#
# Version: 1.0.0
# Dependencies: http, nu_plugin_tera

use ../config/loader.nu get-config

# Get Gitea configuration from global config
export def get-gitea-config [] -> record {
    let config = get-config

    if "gitea" not-in $config {
        error make {
            msg: "Gitea not configured"
            help: "Add gitea section to configuration"
        }
    }

    $config.gitea
}

# Get Gitea auth token
export def get-gitea-token [
    gitea_config: record
] -> string {
    let token_path = $gitea_config.auth.token_path | path expand

    if not ($token_path | path exists) {
        error make {
            msg: $"Token file not found: ($token_path)"
            help: "Create token file with Gitea access token"
        }
    }

    # Check if encrypted (SOPS)
    if ($token_path | str ends-with ".enc") {
        # Decrypt with SOPS
        ^sops --decrypt $token_path | str trim
    } else {
        open $token_path | str trim
    }
}

# Get base API URL
export def get-api-url [
    gitea_config: record
] -> string {
    if $gitea_config.mode == "local" {
        let port = $gitea_config.local.port
        $"http://localhost:($port)/api/v1"
    } else {
        $gitea_config.remote.api_url
    }
}

# Make API call to Gitea
export def gitea-api-call [
    endpoint: string
    method: string = "GET"
    body?: record
    --gitea-config: record
] -> record {
    let config = if ($gitea_config | is-empty) {
        get-gitea-config
    } else {
        $gitea_config
    }

    let token = get-gitea-token $config
    let base_url = get-api-url $config

    let url = $"($base_url)/($endpoint)"

    let headers = [
        "Authorization" $"token ($token)"
        "Content-Type" "application/json"
        "Accept" "application/json"
    ]

    let result = if $method == "GET" {
        http get --headers $headers $url
    } else if $method == "POST" {
        if ($body | is-empty) {
            http post --headers $headers $url ""
        } else {
            http post --headers $headers $url ($body | to json)
        }
    } else if $method == "PUT" {
        if ($body | is-empty) {
            http put --headers $headers $url ""
        } else {
            http put --headers $headers $url ($body | to json)
        }
    } else if $method == "DELETE" {
        http delete --headers $headers $url
    } else if $method == "PATCH" {
        if ($body | is-empty) {
            http patch --headers $headers $url ""
        } else {
            http patch --headers $headers $url ($body | to json)
        }
    } else {
        error make {
            msg: $"Unsupported HTTP method: ($method)"
        }
    }

    $result
}

# Repository Operations

# Create repository
export def create-repository [
    org: string
    repo_name: string
    description?: string
    private: bool = false
    auto_init: bool = true
] -> record {
    let body = {
        name: $repo_name
        description: ($description | default "")
        private: $private
        auto_init: $auto_init
        default_branch: "main"
    }

    gitea-api-call $"orgs/($org)/repos" "POST" $body
}

# Get repository
export def get-repository [
    owner: string
    repo_name: string
] -> record {
    gitea-api-call $"repos/($owner)/($repo_name)" "GET"
}

# Delete repository
export def delete-repository [
    owner: string
    repo_name: string
    --force (-f)
] -> bool {
    if not $force {
        print $"⚠️  About to delete repository ($owner)/($repo_name)"
        let confirm = input "Type repository name to confirm: "
        if $confirm != $repo_name {
            print "Deletion cancelled"
            return false
        }
    }

    gitea-api-call $"repos/($owner)/($repo_name)" "DELETE"
    true
}

# List repositories in organization
export def list-repositories [
    org: string
] -> list {
    gitea-api-call $"orgs/($org)/repos" "GET"
}

# List user repositories
export def list-user-repositories [
    username?: string
] -> list {
    let user = if ($username | is-empty) {
        (get-current-user).login
    } else {
        $username
    }

    gitea-api-call $"users/($user)/repos" "GET"
}

# Release Operations

# Create release
export def create-release [
    owner: string
    repo_name: string
    tag_name: string
    release_name: string
    body?: string
    draft: bool = false
    prerelease: bool = false
] -> record {
    let release_body = {
        tag_name: $tag_name
        name: $release_name
        body: ($body | default "")
        draft: $draft
        prerelease: $prerelease
        target_commitish: "main"
    }

    gitea-api-call $"repos/($owner)/($repo_name)/releases" "POST" $release_body
}

# Upload release asset
export def upload-release-asset [
    owner: string
    repo_name: string
    release_id: int
    file_path: string
] -> bool {
    let config = get-gitea-config
    let token = get-gitea-token $config
    let base_url = get-api-url $config

    let filename = $file_path | path basename
    let url = $"($base_url)/repos/($owner)/($repo_name)/releases/($release_id)/assets?name=($filename)"

    # Use curl for file upload (http command doesn't support multipart/form-data well)
    let result = ^curl -X POST \
        -H $"Authorization: token ($token)" \
        -F $"attachment=@($file_path)" \
        $url

    true
}

# Get release by tag
export def get-release-by-tag [
    owner: string
    repo_name: string
    tag: string
] -> record {
    gitea-api-call $"repos/($owner)/($repo_name)/releases/tags/($tag)" "GET"
}

# List releases
export def list-releases [
    owner: string
    repo_name: string
] -> list {
    gitea-api-call $"repos/($owner)/($repo_name)/releases" "GET"
}

# Delete release
export def delete-release [
    owner: string
    repo_name: string
    release_id: int
] -> bool {
    gitea-api-call $"repos/($owner)/($repo_name)/releases/($release_id)" "DELETE"
    true
}

# Issue Operations (for locking)

# Create issue
export def create-issue [
    owner: string
    repo_name: string
    title: string
    body: string
    labels: list = []
    assignee?: string
] -> record {
    let issue_body = {
        title: $title
        body: $body
        labels: $labels
    }

    let issue_with_assignee = if ($assignee | is-not-empty) {
        $issue_body | merge {assignee: $assignee}
    } else {
        $issue_body
    }

    gitea-api-call $"repos/($owner)/($repo_name)/issues" "POST" $issue_with_assignee
}

# Close issue
export def close-issue [
    owner: string
    repo_name: string
    issue_number: int
] -> bool {
    let body = {state: "closed"}
    gitea-api-call $"repos/($owner)/($repo_name)/issues/($issue_number)" "PATCH" $body
    true
}

# List issues
export def list-issues [
    owner: string
    repo_name: string
    state: string = "open"
    labels?: string
] -> list {
    let endpoint = if ($labels | is-empty) {
        $"repos/($owner)/($repo_name)/issues?state=($state)"
    } else {
        $"repos/($owner)/($repo_name)/issues?state=($state)&labels=($labels)"
    }

    gitea-api-call $endpoint "GET"
}

# Get issue
export def get-issue [
    owner: string
    repo_name: string
    issue_number: int
] -> record {
    gitea-api-call $"repos/($owner)/($repo_name)/issues/($issue_number)" "GET"
}

# Organization Operations

# Create organization
export def create-organization [
    org_name: string
    description?: string
    visibility: string = "private"
] -> record {
    let body = {
        username: $org_name
        description: ($description | default "")
        visibility: $visibility
    }

    gitea-api-call "orgs" "POST" $body
}

# Get organization
export def get-organization [
    org_name: string
] -> record {
    gitea-api-call $"orgs/($org_name)" "GET"
}

# List organizations
export def list-organizations [] -> list {
    gitea-api-call "user/orgs" "GET"
}

# User/Auth Operations

# Get current user
export def get-current-user [] -> record {
    gitea-api-call "user" "GET"
}

# Validate token
export def validate-token [
    gitea_config?: record
] {
    let config = if ($gitea_config | is-empty) {
        get-gitea-config
    } else {
        $gitea_config
    }

    let result = (do {
        gitea-api-call "user" "GET" --gitea-config $config
    } | complete)

    if $result.exit_code == 0 {
        let user = $result.stdout | from json
        $user.login? != null
    } else {
        false
    }
}

# Branch Operations

# Create branch
export def create-branch [
    owner: string
    repo_name: string
    branch_name: string
    base_branch: string = "main"
] -> record {
    let body = {
        new_branch_name: $branch_name
        old_branch_name: $base_branch
    }

    gitea-api-call $"repos/($owner)/($repo_name)/branches" "POST" $body
}

# List branches
export def list-branches [
    owner: string
    repo_name: string
] -> list {
    gitea-api-call $"repos/($owner)/($repo_name)/branches" "GET"
}

# Get branch
export def get-branch [
    owner: string
    repo_name: string
    branch_name: string
] -> record {
    gitea-api-call $"repos/($owner)/($repo_name)/branches/($branch_name)" "GET"
}

# Tag Operations

# Create tag
export def create-tag [
    owner: string
    repo_name: string
    tag_name: string
    message?: string
    target?: string
] -> record {
    let body = {
        tag_name: $tag_name
        message: ($message | default "")
        target: ($target | default "main")
    }

    gitea-api-call $"repos/($owner)/($repo_name)/tags" "POST" $body
}

# List tags
export def list-tags [
    owner: string
    repo_name: string
] -> list {
    gitea-api-call $"repos/($owner)/($repo_name)/tags" "GET"
}
