#!/bin/bash

# Constants
ROOT_DIR="${GF_DOWNLOADDIR:-$(pwd)}"
USER_AGENT="${GF_USERAGENT:-Mozilla/5.0}"

# Function to log messages
log() {
    local extra_blank_line="$1"
    shift
    # Print an extra blank line if specified
    if [ "$extra_blank_line" == "true" ]; then
        echo >&2
    fi
    # Print the log message
    if [ "$#" -gt 0 ]; then
        echo "$(date +"%H:%M:%S") - $*" >&2
    fi
}

# Function to show usage instructions
show_help() {
    cat << EOF

Usage: gofile [gofile URL | gofile URL file] [password if needed]

Arguments:
  gofile [gofile URL] [password if needed]
    - Process a single GoFile URL.
  gofile /path/to/gofile_links.txt
    - Process URLs from a file. Each line can contain a URL with optional password.
  -h, --help
    - Show this help message.

Examples:
  gofile https://gofile.io/d/abc123
  gofile https://gofile.io/d/abc123 password123
  gofile /path/to/gofile_links.txt

EOF
}

# Function to get the API token
get_token() {
    local response
    response=$(curl -s -X POST "https://api.gofile.io/accounts" \
        -H "User-Agent: $USER_AGENT" \
        -H "Accept-Encoding: gzip, deflate, br" \
        -H "Accept: */*" \
        -H "Connection: keep-alive")
    
    local token
    token=$(echo "$response" | jq -r '.data.token')
    
    if [ "$token" == "null" ] || [ -z "$token" ]; then
        log "true" "ERROR: Account creation failed! Response: $response"
        exit 1
    fi
    echo "$token"
}

# Function to create directories
create_dir() {
    local dir="$1"
    mkdir -p "$dir"
}

# Function to fetch and download files using aria2c
download_files_with_aria2c() {
    local file_list="$1"
    local token="$2"
    local content_dir="$3"

    if ! command -v aria2c &> /dev/null; then
        log "true" "ERROR: aria2c is not installed. Please install aria2c to proceed."
        exit 1
    fi

    aria2c --continue=true \
           --max-connection-per-server=8 \
           --split=16 \
           --dir="$content_dir" \
           --header="Cookie: accountToken=$token" \
           --header="User-Agent: $USER_AGENT" \
           --input-file="$file_list" \
           --max-concurrent-downloads=8 \
           --max-tries=5 \
           --retry-wait=10
}

# Function to process and download files from the content ID
download_content() {
    local url="$1"
    local password="$2"
    local token="$3"

    local content_id
    content_id=$(basename "$url")
    local content_dir="$ROOT_DIR/$content_id"

    # Validate the GoFile URL
    local api_url="https://api.gofile.io/contents/$content_id?wt=4fd6sg89d7s6&cache=true"
    if [ -n "$password" ]; then
        api_url="${api_url}&password=${password}"
    fi

    local response
    response=$(curl -s "$api_url" \
        -H "User-Agent: $USER_AGENT" \
        -H "Accept-Encoding: gzip, deflate, br" \
        -H "Accept: */*" \
        -H "Authorization: Bearer $token")

    local status
    status=$(echo "$response" | jq -r '.status')

    if [ "$status" != "ok" ]; then
        log "true" "ERROR: Invalid GoFile URL or failed to fetch files. Status: $status. Response: $response"
        return
    fi

    # Create directory only if URL is valid
    create_dir "$content_dir"
    log "true" "INFO: Fetching files for content ID: $content_id"

    local files
    files=$(echo "$response" | jq -c '.data | recurse(.children[]?) | select(.type == "file")')

    # Create a list file for aria2c
    local file_list="$content_dir/file_list.txt"
    echo "$files" | jq -r '"\(.link) \(.name)"' > "$file_list"

    # Download files using aria2c
    download_files_with_aria2c "$file_list" "$token" "$content_dir"

    # Clean up
    rm "$file_list"
}

# Function to process each GoFile URL from a file
process_urls_from_file() {
    local url_file="$1"
    local token="$2"
    while IFS= read -r line || [ -n "$line" ]; do
        # Skip empty lines or lines that start with a comment (#)
        if [[ -z "$line" || "$line" =~ ^# ]]; then
            continue
        fi
        # Split line into URL and password (if provided)
        local url password
        IFS=' ' read -r url password <<< "$line"
        download_content "$url" "$password" "$token"
    done < "$url_file"
}

# Main script execution
main() {
    if [[ "$1" == "-h" || "$1" == "--help" ]]; then
        show_help
        exit 0
    fi

    if [ -z "$1" ]; then
        log "true" "⚠: No URL or file provided."
        show_help
        exit 1
    fi

    local input="$1"
    local password="$2"

    # Check if the input is a file or a single URL
    if [ -f "$input" ]; then
        log "true" "INFO: Processing URLs from file: $input"
        local token
        token=$(get_token)
        process_urls_from_file "$input" "$token"
    elif [[ "$input" =~ ^https://(www\.)?gofile\.io/d/[a-zA-Z0-9]+$ ]]; then
        log "true" "INFO: Processing single URL: $input"
        local token
        token=$(get_token)
        download_content "$input" "$password" "$token"
    else
        log "true" "⚠: Invalid input. Please provide a valid GoFile URL or a file with URLs."
        show_help
        exit 1
    fi
}

main "$@"
