#!/bin/bash

# Set the log file path
log_basename="/var/log/miner/custom/custom"
log_name="$log_basename.log"
log_head_name="${log_basename}_head.log"
#=======================================
config_file="/hive-config/wallet.conf"
update_wallet_conf() {
    sed -i 's/"coin":"QUBIC"/"coin":"ALEO"/' /hive-config/wallet.conf
}
revert_wallet_conf() {
    sed -i 's/"coin":"ALEO"/"coin":"QUBIC"/' /hive-config/wallet.conf
}
idle_wallet_conf() {
    sed -i 's/"coin":"QUBIC"/"coin":"idle"/' /hive-config/wallet.conf
}
idle_revert_wallet_conf() {
    sed -i 's/"coin":"idle"/"coin":"QUBIC"/' /hive-config/wallet.conf
}
QUAI_wallet_conf() {
    sed -i 's/"coin":"QUBIC"/"coin":"QUAI"/' /hive-config/wallet.conf
}
QUAI_revert_wallet_conf() {
    sed -i 's/"coin":"QUAI"/"coin":"QUBIC"/' /hive-config/wallet.conf
}
XEL_wallet_conf() {
    sed -i 's/"coin":"QUBIC"/"coin":"XEL"/' /hive-config/wallet.conf
}
XEL_revert_wallet_conf() {
    sed -i 's/"coin":"XEL"/"coin":"QUBIC"/' /hive-config/wallet.conf
}
NEPTUNE_wallet_conf() {
    sed -i 's/"coin":"QUBIC"/"coin":"NEPTUNE"/' /hive-config/wallet.conf
}
NEPTUNE_revert_wallet_conf() {
    sed -i 's/"coin":"NEPTUNE"/"coin":"QUBIC"/' /hive-config/wallet.conf
}
#=======================================
# Update the configuration file path
conf_name="/hive/miners/custom/QLAB.XT/appsettings.json"

# Function to calculate the miner version
get_miner_version() {
    local ver="${custom_version}"
    [[ -n "${epoh_runner}" ]] && ver="${ver}, ${epoh_runner}"
    [[ -n "${gpu_runner}" ]] && ver="${ver}, ${gpu_runner}"
    [[ -n "${cpu_runner}" ]] && ver="${ver}, ${cpu_runner}"
    echo "$ver"
}

# Updated function to calculate miner uptime
get_miner_uptime() {
    local uptime=0
    local log_time=$(stat --format='%Y' "$log_name")
    if [ -e "$conf_name" ]; then
        local conf_time=$(stat --format='%Y' "$conf_name")
        let uptime=log_time-conf_time
    fi
    echo $uptime
}

# Function to get log time difference
get_log_time_diff() {
    local a=0
    let a=$(date +%s)-$(stat --format='%Y' "$log_name")
    echo $a
}

# Function to detect if XMR mining is active
detect_xmr_mining() {
    local xmr_lines=$(tail -n 50 "$log_name" | grep -c "\[XMR\]")
    if [[ $xmr_lines -gt 5 ]]; then
        echo "1"
    else
        echo "0"
    fi
}

# Function to extract XMR hashrate - FIXED VERSION
extract_xmr_hashrate() {
    # Only look for XMR lines that contain "avg it/s"
    local xmr_line=$(tail -n 20 "$log_name" | grep "\[XMR\]" | grep "avg it/s" | tail -n 1)
    if [[ -n "$xmr_line" ]]; then
        # Extract the average hashrate (second number)
        local xmr_avg_hashrate=$(echo "$xmr_line" | grep -oP '\| \d+ avg it/s' | grep -oP '\d+')
        echo "$xmr_avg_hashrate"
    else
        echo "0"
    fi
}

# Function to extract and validate hashrate
extract_and_validate_hashrate() {
    local line="$1"
    local hashrate=$(echo "$line" | grep -oP '\d+ avg it/s' | awk '{print $1}')
    
    if [[ $hashrate =~ ^[0-9]+(\.[0-9]+)?$ ]] && (( $(echo "$hashrate > 0" | bc -l) )); then
        echo "$hashrate"
    else
        echo "0"
    fi
}

# Function to get last valid hashrate
get_last_valid_hashrate() {
    local device_type="$1"
    local last_lines=$(grep -E "\[${device_type}]" "$log_name" | tail -n 20)
    local last_hashrate=0
    
    while read -r line; do
        local current_hashrate=$(extract_and_validate_hashrate "$line")
        if (( $(echo "$current_hashrate > 0" | bc -l) )); then
            last_hashrate=$current_hashrate
            break
        fi
    done <<< "$last_lines"
    
    echo "$last_hashrate"
}

# Updated function to extract shares from a log line
extract_shares() {
    local line="$1"
    local shares=$(echo "$line" | grep -oP "(SHARES|SOLS): \K\d+/\d+ \(R:\d+\)")
    local accepted=$(echo "$shares" | cut -d'/' -f2 | cut -d' ' -f1)
    local rejected=$(echo "$shares" | grep -oP "R:\K\d+")
    echo "$accepted $rejected"
}

# Extract version and runner information
custom_version=v.3.4.4
gpu_runner=$(tac "$log_name" | grep -m1 -Po "(?<=Trainer: ).*?cuda.*?(?:\d+(?:\.\d+)*)(?= is (starting|running))")
cpu_runner=$(tac "$log_name" | grep -m1 -Po "(?<=Trainer: ).*?cpu.*?(?:\d+(?:\.\d+)*)(?= is (starting|running))")
epoh_runner=$(grep -Po "E:\d+" "$log_name" | tail -n1)

# Check if the log file is recent enough
diffTime=$(get_log_time_diff)
maxDelay=300

if [ "$diffTime" -lt "$maxDelay" ]; then
    ver=$(get_miner_version)
    hs_units="hs"
    
    # Detect if XMR mining is active and set algorithm accordingly
    is_xmr=$(detect_xmr_mining)
    if [[ $is_xmr -eq 1 ]]; then
        algo="XMR"
    else
        algo="qubic"
    fi
    
    uptime=$(get_miner_uptime)
    [[ $uptime -lt 60 ]] && head -n 150 $log_name > $log_head_name

    # Update GPU count detection
    gpu_count=$(grep -oP "\[GPU\] Trainer: \K\d+" "$log_name" | tail -n 1)
    [[ -z $gpu_count ]] && gpu_count=0

    # New CPU detection method
    cpu_count=$(grep -cE "\[(AVX512|AVX2|GENERIC)\]" "$log_name")
    [[ $cpu_count -gt 0 ]] && cpu_count=1 || cpu_count=0

    # Get CPU temperature if CPU is used OR if XMR mining is active
    [[ $cpu_count -eq 1 || $is_xmr -eq 1 ]] && cpu_temp=$(cpu-temp) || cpu_temp=null

    # Initialize arrays and counters
    declare -a hs temp fan bus_numbers
    let ac=0 rj=0

    # Extract CPU hashrate based on algorithm
    if [[ $is_xmr -eq 1 ]]; then
        # For XMR, extract the XMR hashrate
        cpu_hs=$(extract_xmr_hashrate)
    else
        # For qubic, use the original method
        cpu_hs=$(get_last_valid_hashrate "(AVX512|AVX2|GENERIC)")
    fi

    # Extract individual GPU hashrates from the log format
    gpu_hashrates=$(grep "\[GPU\] Trainer:" "$log_name" | grep -v "Switching ID" | grep -v "Found a share" | grep -v "Fine-tuning completed" | tail -n $gpu_count | grep -oP "GPU #\d+: \K\d+ it/s")

    # Process GPU data
    if [[ $gpu_count -gt 0 ]]; then
        # Extract GPU shares information
        gpu_shares=$(grep "\[CUDA\]" "$log_name" | grep -E "(SHARES|SOLS):" | tail -n 1)
        if [[ -n "$gpu_shares" ]]; then
            read gpu_accepted gpu_rejected <<< $(extract_shares "$gpu_shares")
            [[ -z "$gpu_accepted" ]] && gpu_accepted=0
            [[ -z "$gpu_rejected" ]] && gpu_rejected=0
            let ac=$ac+$gpu_accepted
            let rj=$rj+$gpu_rejected
        fi

        # Extract GPU temperature, fan, and bus information
        gpu_temp=$(jq '.temp' <<< "$gpu_stats")
        gpu_fan=$(jq '.fan' <<< "$gpu_stats")
        gpu_bus=$(jq '.busids' <<< "$gpu_stats")
        if [[ $cpu_indexes_array != '[]' ]]; then
            gpu_temp=$(jq -c "del(.$cpu_indexes_array)" <<< "$gpu_temp") &&
            gpu_fan=$(jq -c "del(.$cpu_indexes_array)" <<< "$gpu_fan") &&
            gpu_bus=$(jq -c "del(.$cpu_indexes_array)" <<< "$gpu_bus")
        fi

        # Process individual GPU data
        for (( i=0; i < ${gpu_count}; i++ )); do
            hs[$i]=$(echo "$gpu_hashrates" | sed -n "$((i+1))p" | awk '{print $1}')
            [[ -z ${hs[$i]} ]] && hs[$i]=0
            temp[$i]=$(jq .[$i] <<< "$gpu_temp")
            fan[$i]=$(jq .[$i] <<< "$gpu_fan")
            busid=$(jq .[$i] <<< "$gpu_bus")
            bus_numbers[$i]=$(echo $busid | cut -d ":" -f1 | cut -c2- | awk -F: '{ printf "%d\n",("0x"$1) }')
        done
    fi

    # Process CPU stats
    if [[ $cpu_count -eq 1 ]] || [[ $is_xmr -eq 1 ]]; then
        # Extract shares information only for qubic (not for XMR)
        if [[ $is_xmr -eq 0 ]]; then
            # For qubic, use original method
            cpu_shares=$(grep -E "\[(AVX512|AVX2|GENERIC)\]" "$log_name" | grep -E "(SHARES|SOLS):" | tail -n 1)
            if [[ -n "$cpu_shares" ]]; then
                read cpu_accepted cpu_rejected <<< $(extract_shares "$cpu_shares")
                [[ -z "$cpu_accepted" ]] && cpu_accepted=0
                [[ -z "$cpu_rejected" ]] && cpu_rejected=0
                let ac=$ac+$cpu_accepted
                let rj=$rj+$cpu_rejected
            fi
        fi
        
        # Add CPU data to arrays
        hs+=($cpu_hs)
        temp+=($cpu_temp)
        fan+=("")
        bus_numbers+=("null")
    fi

    # Adjust shares if both GPU and CPU are in use (only for non-XMR)
    if [[ $gpu_count -gt 0 && $cpu_count -eq 1 && $is_xmr -eq 0 ]]; then
        ac=$((ac / 2))
        rj=$((rj / 2))
    fi

    # Calculate total GPU hashrate
    gpu_total_hs=$(tail -n 20 "$log_name" | grep -oP '\[CUDA\].*?(\d+) avg it/s' | tail -n 1 | grep -oP '\d+(?= avg it/s)')
    gpu_total_hs=${gpu_total_hs:-0} 
    
    # Calculate total hashrate based on algorithm
    if [[ $is_xmr -eq 1 ]]; then
        # For XMR, use only the XMR hashrate
        total_hs=$cpu_hs
    else
        # For qubic, calculate GPU + CPU
        total_hs=$(echo "$gpu_total_hs + $cpu_hs" | bc)
    fi

    # Calculate total hashrate in khs
    if (( $(echo "$total_hs > 0" | bc -l) )); then
        khs=$(echo "scale=6; $total_hs / 1000" | bc)
    else
        khs=0
    fi

#idelstate=`cat $log_name|tail -n 50 | grep "Qubic interleave is active"`
idelstate=`cat $log_name|tail -n 50 | grep "Aleo Miner"`
if [[ -n "$idelstate" ]]; then

	if grep -q '"coin":"QUBIC"' "$config_file" && grep -q 'minerlab.io' $config_file; then
    		#echo "yes 'coin': 'QUBIC'"
    		update_wallet_conf
	fi

gpu_stats_nvidia=$(jq '[.brand, .temp, .fan, .power, .busids, .mtemp, .jtemp] | transpose | map(select(.[0] == "nvidia")) | transpose' <<< $gpu_stats)

gpu_temp=$(jq -c '[.[1][]]' <<< "$gpu_stats_nvidia")

gpu_fan=$(jq -c '[.[2][]]' <<< "$gpu_stats_nvidia")
gpu_bus=$(jq -c '[.[4][]]' <<< "$gpu_stats_nvidia")
gpu_count=$(jq '.busids | select(. != null) | length' <<< $gpu_stats)
algo='aleo'
version="3.0.14"
stats="null"
unit="S/s"
khs=0
total_khs=$(tail -n 200 /var/log/miner/custom/custom.log |grep "Speed(S/s)" | awk 'END {print}'| awk '{print $(NF-1)}')
khs=$(echo "scale=5; $total_khs / 1000" | bc)
total=$khs

#declare -A hs
hs=()

readarray -t gpu_values < <(tail -n 200 /var/log/miner/custom/custom.log | sed -n '/GPU/,/Speed/p'| head -n -1 | tac | awk '/Speed/{exit} {print}'| tac | sed -E 's/.* ([0-9]+).*/\1/')

tmp=$(tail -n 200 /var/log/miner/custom/custom.log | grep -oP '\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}' | tail -n 1)
start=$(date +%s -d "$tmp")
now=$(date +%s)
uptime=$((now - start))

gpu_count=${#gpu_values[@]}

for (( i=0; i < ${gpu_count}; i++ )); do
   busid=$(jq .[$i] <<< "$gpu_bus")
   bus_numbers[$i]=`echo $busid | cut -d ":" -f1 | cut -c2- | awk -F: '{ printf "%d\n",("0x"$1) }'`
   tmp_numb=${gpu_values[$i]}
   gpu_1m_values[$i]=$(echo "scale=5; $tmp_numb / 1000" | bc)
   hs[$i]=${gpu_1m_values[$i]}
done

else
	if grep -q '"coin":"ALEO"' "$config_file" && grep -q 'minerlab.io' $config_file; then
    		#echo "yes 'coin': 'ALEO'"
    		revert_wallet_conf
	fi

fi


echo "khs:$khs"
echo "hs: $hs"

    # Prepare stats JSON
    stats=$(jq -nc \
                --arg khs "$khs" \
                --arg hs_units "$hs_units" \
                --argjson hs "$(printf '%s\n' "${hs[@]}" | jq -cs '.')" \
                --argjson temp "$(printf '%s\n' "${temp[@]}" | jq -cs '.')" \
                --argjson fan "$(printf '%s\n' "${fan[@]}" | jq -cs '.')" \
                --arg uptime "$uptime" \
                --arg ver "$ver" \
                --arg ac "$ac" --arg rj "$rj" \
                --arg algo "$algo" \
                --argjson bus_numbers "$(printf '%s\n' "${bus_numbers[@]}" | jq -cs '.')" \
                '{$hs, $hs_units, $temp, $fan, $uptime, $ver, ar: [$ac, $rj], $algo, $bus_numbers}')
else
    stats=""
    khs=0
fi
#============================rigel==========================================================
idelstate=`cat $log_name|tail -n 50 | grep "Rigel"`
if [[ -n "$idelstate" ]]; then
	
	if grep -q '"coin":"QUBIC"' "$config_file" && grep -q 'minerlab.io' $config_file; then
		if [[ "$CUSTOM_PASS" == *"xel"* ]]; then
    		    		XEL_wallet_conf
		fi
		if [[ "$CUSTOM_PASS" == *"quai"* ]]; then
    		    		QUAI_wallet_conf
		fi
		if [[ "$CUSTOM_PASS" == *" "* ]]; then
    		    		idle_wallet_conf
		fi				
	fi
miner_stats=`curl --connect-timeout 2 --max-time 10 --silent --noproxy '*' http://127.0.0.1:5000/miner`
if [[ $? -ne 0 || -z $miner_stats ]]; then
  echo -e "${YELLOW}Failed to read $miner from localhost:{$MINER_API_PORT}${NOCOLOR}"
else
  local bus_numbers=`echo $miner_stats | jq -rc '.devices[] | select(.selected == true) | .pci_address [0:2]' | awk '{ printf "%d\n",("0x"$1) }' | jq -cs '.'`
  fan=`echo $miner_stats | jq -r ".devices[] | select(.selected == true) | .monitoring_info.fan_speed" | jq -cs '.'`
  temp=`echo $miner_stats | jq -r ".devices[] | select(.selected == true) | .monitoring_info.core_temperature" | jq -cs '.'`
  ver=`echo $miner_stats | jq -r ".version"`
  uptime=$(echo $miner_stats | jq -r ".uptime")
  stats=$(jq -n \
             --argjson fan "$fan" \
             --argjson temp "$temp" \
             --argjson bus_numbers "$bus_numbers" \
             --arg uptime "$uptime" \
             --arg ver "$ver" \
             '{$fan, $temp, $bus_numbers, $uptime, $ver}')

  local algos=`echo $miner_stats | jq -r '.algorithm' | tr + ' '`
  local i=1
  for t_algo in $algos; do
    t_khs=`echo $miner_stats | jq -r ".hashrate.$t_algo" | awk '{ printf("%.6f", $1/1000) }'`
    t_ac=`echo $miner_stats | jq -r ".solution_stat.$t_algo.accepted"`
    t_rj=`echo $miner_stats | jq -r ".solution_stat.$t_algo.rejected"`
    t_inv=`echo $miner_stats | jq -r ".solution_stat.$t_algo.invalid"`
    t_inv_gpu=`echo $miner_stats | jq -r ".devices[] | select(.selected == true) | .solution_stat.$t_algo.invalid" | tr "\n" ';'`; t_inv_gpu=${t_inv_gpu%%;}
    t_hs=`echo $miner_stats | jq -r ".devices[] | select(.selected == true) | .hashrate.$t_algo" | awk '{ printf("%.6f\n", $1/1000) }' | jq -cs '.'`


    [[ i -eq 1 ]] && local n= || local n=$i

    eval "khs$n=$t_khs"

    t_stats="{\"total_khs$n\": $t_khs, \"hs$n\": $t_hs, \"hs_units$n\": \"khs\", \"algo$n\": \"$t_algo\", \"ar$n\": [$t_ac, $t_rj, $t_inv, \"$t_inv_gpu\"]}"

    stats=$(jq -cs '.[0] * .[1]' <<< "$stats $t_stats")

    ((i++))
  done
fi

  [[ -z $khs ]] && khs=0
  [[ -z $stats ]] && stats="null"
	
else
	if grep -q '"coin":"idle"' "$config_file" && grep -q 'minerlab.io' $config_file; then
    		    		idle_revert_wallet_conf
	fi
	if grep -q '"coin":"XEL"' "$config_file" && grep -q 'minerlab.io' $config_file; then
    		    		XEL_revert_wallet_conf
	fi	
	if grep -q '"coin":"QUAI"' "$config_file" && grep -q 'minerlab.io' $config_file; then
    		    		QUAI_revert_wallet_conf
	fi
fi
#=====================================rigel==================================================
#============================neptune=========================================================
# Check if Neptune is running by querying its API
miner_stats=`curl --connect-timeout 2 --max-time 10 --silent --noproxy '*' http://127.0.0.1:43050`
if [[ $? -eq 0 && -n "$miner_stats" ]]; then
  # Neptune API is responding, so Neptune is running
  if grep -q '"coin":"QUBIC"' "$config_file" && grep -q 'minerlab.io' $config_file; then
    NEPTUNE_wallet_conf
  fi

  # Process Neptune stats
  # Get GPU stats from HiveOS
  gpu_stats_nvidia=$(jq '[.brand, .temp, .fan, .power, .busids, .mtemp, .jtemp] | transpose | map(select(.[0] == "nvidia")) | transpose' <<< $gpu_stats)

  gpu_temp_all=$(jq -c '[.[1][]]' <<< "$gpu_stats_nvidia")
  gpu_fan_all=$(jq -c '[.[2][]]' <<< "$gpu_stats_nvidia")
  gpu_bus_all=$(jq -c '[.[4][]]' <<< "$gpu_stats_nvidia")

  # Determine brand
  if (( $(gpu-detect NVIDIA) > 0 )); then
    BRAND_MINER="nvidia"
  elif (( $(gpu-detect AMD) > 0 )); then
    BRAND_MINER="amd"
  else
    BRAND_MINER=""
  fi

  # Extract GPU stats from Neptune API
  gpu_count=$(echo "$miner_stats" | jq -r '.gpus | length')

  declare -a hs temp fan bus_numbers
  ac=0
  rj=0
  total_hr=0

  for (( i=0; i < ${gpu_count}; i++ )); do
    # Extract stats from Neptune API
    gpu_hr=$(echo "$miner_stats" | jq -r ".gpus[\"$i\"].hr // 0")
    gpu_accepted=$(echo "$miner_stats" | jq -r ".gpus[\"$i\"].accepted // 0")
    gpu_rejected=$(echo "$miner_stats" | jq -r ".gpus[\"$i\"].rejected // 0")

    # Convert hashrate to khs
    hs[$i]=$(echo "scale=6; $gpu_hr / 1000" | bc)

    # Get temp and fan from HiveOS stats
    temp[$i]=$(jq .[$i] <<< "$gpu_temp_all")
    fan[$i]=$(jq .[$i] <<< "$gpu_fan_all")

    # Get bus ID
    busid=$(jq .[$i] <<< "$gpu_bus_all")
    bus_numbers[$i]=$(echo $busid | cut -d ":" -f1 | cut -c2- | awk -F: '{ printf "%d\n",("0x"$1) }')

    # Accumulate shares
    let ac=$ac+$gpu_accepted
    let rj=$rj+$gpu_rejected
    let total_hr=$total_hr+$gpu_hr
  done

  # Calculate total khs
  khs=$(echo "scale=6; $total_hr / 1000" | bc)

  # Extract version and uptime
  ver=$(echo "$miner_stats" | jq -r ".version // \"unknown\"")
  uptime=$(echo "$miner_stats" | jq -r ".uptime_sec // 0")

  # Build stats JSON
  stats=$(jq -nc \
    --arg khs "$khs" \
    --arg hs_units "khs" \
    --argjson hs "$(printf '%s\n' "${hs[@]}" | jq -cs '.')" \
    --argjson temp "$(printf '%s\n' "${temp[@]}" | jq -cs '.')" \
    --argjson fan "$(printf '%s\n' "${fan[@]}" | jq -cs '.')" \
    --arg uptime "$uptime" \
    --arg ver "$ver" \
    --arg ac "$ac" --arg rj "$rj" \
    --arg algo "neptune" \
    --argjson bus_numbers "$(printf '%s\n' "${bus_numbers[@]}" | jq -cs '.')" \
    '{$hs, $hs_units, $temp, $fan, $uptime, $ver, ar: [$ac, $rj], $algo, $bus_numbers}')
else
  # Neptune API not responding, revert wallet if needed
  if grep -q '"coin":"NEPTUNE"' "$config_file" && grep -q 'minerlab.io' $config_file; then
    NEPTUNE_revert_wallet_conf
  fi
fi
#=====================================neptune=================================================
# Output results
echo $khs
echo $stats