#!/bin/bash

# This program is to be launched manually to recompute statistics and history
# PREREQUISITE: Create a .pgpass file with the credentials to the xivo_stats database for asterisk on localhost
#    echo "localhost:5443:xivo_stats:asterisk:proformatique" >> /root/.pgpass
#    chmod 600 /root/.pgpass

# ARGUMENTS:
#       FROM date (day) the data needs to be recomputed with format : YYYY-MM-DD
#
# It will stop full_stats then delete following tables for a start date until now before launching the recompilation of same tables
# after a confirmation !
# This script do not launch automatically the stats_specific recompilation but invite user to do it manually at the end

# Tables recomputed with this script :
# - attached_data
# - call_data
# - call_on_queue
# - call_element
# - stat_agent_periodic
# - stat_*_periodic
# - xc_call_channel
# - xc_call_conversation
# - xc_call_transfer
# - xc_queue_call
#

readonly progname="${0##*/}"


psql_cmd() {
    local req="${1}"; shift

    local psql_res=""

    if psql_res=$(psql -h localhost -p 5443 -U asterisk -w xivo_stats -qtc "${req}"); then
        echo "${psql_res}"
    fi
}


ask_to_continue() {
    local answer
    echo -e -n "\n\e[31mWould you really want to recompute call history [Y/n]?\e[0m "
    read -r answer
    answer="${answer:-Y}"
    if [ "$answer" != 'y' ] && [ "$answer" != 'Y' ]; then
        exit
    fi
}

print_result() {
    local min_id=${1:-0}; shift
    local count=${1:-0}; shift
    local table=${1}; shift

    echo ""
    echo "Recomputation for ${table} will start at id: ${min_id}"
    echo "The number of row to recompute in ${table} is: ${count}"
}

get_cel() {
    local date=${1}; shift
    local table="cel"
    local min="select min(id) from ${table} where eventtime >= '${date}'"
    local cnt="select count(*) from ${table} where eventtime >= '${date}'"

    local min_id
    min_id=$(psql_cmd "${min}")

    local count_nb
    count_nb=$(psql_cmd "${cnt}")
    echo "${min_id}|${count_nb}"
}

get_queue_log() {
    local date=${1}; shift
    local table="queue_log"
    local min="select min(id) from ${table} where time >= '${date}'"
    local cnt="select count(*) from ${table} where time >= '${date}'"

    local min_id
    min_id=$(psql_cmd "${min}")

    local count_nb
    count_nb=$(psql_cmd "${cnt}")
    echo "${min_id}|${count_nb}"
}


delete_attached_data() {
    local date=${1}; shift
    local table="attached_data"
    echo -n "Purging table ${table} from ${date}"
    psql_cmd "DELETE FROM ${table} WHERE id_call_data IN (SELECT id FROM call_data WHERE start_time >= '${date}')"
}

delete_call_element() {
    local date=${1}; shift
    local table="call_element"
    echo -n "Purging table ${table} from ${date}"
    psql_cmd "DELETE FROM ${table} WHERE call_data_id IN (SELECT id FROM call_data WHERE start_time >= '${date}')"
}

delete_call_data() {
    local date=${1}; shift
    local table="call_data"
    echo -n "Purging table ${table} from ${date}"
    psql_cmd "DELETE FROM ${table} WHERE start_time >= '${date}'"
}

delete_call_on_queue() {
    local date=${1}; shift
    local table="call_on_queue"
    echo -n  "Purging table ${table} from ${date}"
    psql_cmd "DELETE FROM ${table} WHERE queue_time >= '${date}'"
}

delete_xc_tables() {
    local date=${1}; shift
    local table="xc_call_transfer"
    echo -n "Purging table ${table} from ${date}"
    psql_cmd "DELETE FROM ${table} WHERE initial_call_id IN (SELECT id FROM xc_call_channel WHERE start_time >= '${date}')"
    table="xc_call_conversation"
    echo -n "Purging table ${table} from ${date}"
    psql_cmd "DELETE FROM ${table} WHERE caller_call_id IN (SELECT id FROM xc_call_channel WHERE start_time >= '${date}')"
    table="xc_queue_call"
    echo -n "Purging table ${table} from ${date}"
    psql_cmd "DELETE FROM ${table} WHERE start_time >= '${date}'"
    table="xc_call_channel"
    echo -n "Purging table ${table} from ${date}"
    psql_cmd "DELETE FROM ${table} WHERE start_time >= '${date}'"
}


delete_periodic_tables() {
    local date=${1}; shift
    local table="stat_agent_periodic"
    echo -n "Purging table ${table} from ${date}"
    psql_cmd "DELETE FROM ${table} WHERE time >= '${date}'"

    table="stat_queue_periodic"
    echo -n "Purging table ${table} from ${date}"
    psql_cmd "DELETE FROM ${table} WHERE time >= '${date}'"
}



set_last_recompute_id() {
    local last_cel_id=${1}; shift
    local last_queue_log_id=${1}; shift

    echo -e "\nset last_cel_id to: ${last_cel_id}"
    psql_cmd "UPDATE last_cel_id SET id=${last_cel_id}"
    echo -e "set last_queue_log_id to: ${last_queue_log_id}"
    psql_cmd "UPDATE last_queue_log_id SET id=${last_queue_log_id}"
}

give_new_progress() {
    local start="${1}"; shift
    local total="${1}"; shift
    local current
    current=$(psql_cmd "select id from last_cel_id")

    echo $(( (current - start + 1) * 100 / total ))
}

display_progress_bar() {
    local progress="${1}"; shift
    local progress_step="${1}"; shift
    local elapsed_time="${1}"; shift

    local percentage
    local trailer
    local eta

    echo -n "[ "
    for ((i = 0 ; i <= progress; i++)); do
        if [ "$progress" -le 10 ]; then
            echo -en "\e[31m#\e[0m";
        elif [ "$progress" -gt 10 ] && [ "$progress" -le 30 ]; then
            echo -en "\e[35m#\e[0m";
        elif [ "$progress" -gt 30 ] && [ "$progress" -le 60 ]; then
            echo -en "\e[34m#\e[0m";
        elif [ "$progress" -gt 60 ] && [ "$progress" -le 99 ]; then
            echo -en "\e[36m#\e[0m";
        else
            echo -en "\e[32m#\e[0m";
        fi
    done
    for ((j = i ; j <= 100 ; j++)); do
        echo -n ".";
    done

    percentage=$((progress * progress_step))
    if [ "$progress" -eq 0 ]; then
        trailer="(ETA: N.A.)"
    elif [ "$progress" -eq 100 ]; then
        trailer="(Took: ${elapsed_time}s)"
    else
        eta=$(( (elapsed_time * 100) / (progress * progress_step) ))
        trailer="(ETA: ~${eta}s)"
    fi
    echo -n " ] "
    echo -n "$percentage % $trailer" $'\r'

}

display_progress() {
    local cel_start="${1}"; shift
    local cel_nb_to_process="${1}"; shift

    local display_step="${1:-10}"; shift
    local update_interval="${1:-30}"; shift

    local percentage_complete
    local elapsed_time

    local nb_loop_run=0
    for ((k = 0; k <= 100 ; k = k + display_step))
    do
        percentage_complete=$(give_new_progress "${cel_start}" "${cel_nb_to_process}")
        k=$(( percentage_complete / display_step ))

        elapsed_time=$(( nb_loop_run * update_interval ))
        display_progress_bar "${k}" "$display_step" "${elapsed_time}"

        sleep "${update_interval}"
        nb_loop_run=$((nb_loop_run + 1))
    done
    echo
}

usage() {
    echo -e "\e[1;33m${progname} -d FROM\e[0m"
    echo -e "This script force recomputation of call history and call statistics: Use with Caution !"
    echo -e "Note: this script needs a valid .pgpass file to be able to connect to stats db as asterisk user"
    echo -e "\t -d FROM in date format YYYY-MM-DD"
}

exit_abnormally() {
    usage
    exit 1
}

stop_containers() {
    echo "Stopping containers..."
    xivocc-dcomp stop xivo_stats
    xivocc-dcomp stop pack_reporting
}


start_container() {
    echo -e "\nStarting container..."
    xivocc-dcomp start xivo_stats
}

main() {
    if [ ! -f "${HOME}/.pgpass" ]; then
        echo "ERROR: ${progname} needs a valid .pgpass file to work and to be able to connect to stats db as asterisk user"
        exit_abnormally
    fi
    if [[ $# -eq 0 ]]; then
        echo "ERROR: ${progname} needs at least date YYYY-MM-DD argument -d FROM"
        exit_abnormally
    fi

    # Script defaults
    local date
    local expected_opts=":d:"
    while getopts ${expected_opts} opt; do
        case "${opt}" in
            d)
                date="${OPTARG}"
            ;;
            *)
            ;;
        esac
    done

    echo -e "\nFrom ${date}:"
    local get_cel_res
    local cel_min_id
    local cel_count_nb
    get_cel_res=$(get_cel "${date}")
    cel_min_id=$(echo "${get_cel_res}"|cut -d'|' -f1)
    cel_count_nb=$(echo "${get_cel_res}"|cut -d'|' -f2)

    print_result "${cel_min_id}" "${cel_count_nb}" "cel"

    local get_queue_log_res
    local queue_log_min_id
    local queue_log_count_nb
    get_queue_log_res=$(get_queue_log "${date}")
    queue_log_min_id=$(echo "${get_queue_log_res}"|cut -d'|' -f1)
    queue_log_count_nb=$(echo "${get_queue_log_res}"|cut -d'|' -f2)

    print_result "${queue_log_min_id}" "${queue_log_count_nb}" "queue_log"
    ask_to_continue

    stop_containers

    set_last_recompute_id "${cel_min_id}" "${queue_log_min_id}"
    delete_attached_data "${date}"
    delete_call_element "${date}"
    delete_call_data "${date}"
    delete_call_on_queue "${date}"
    delete_xc_tables "${date}"
    delete_periodic_tables "${date}"

    start_container

    echo -e "\nRecomputation is launched. Check logs via:"
    echo -e "  \e[1;33mtail -f /var/log/xivocc/xivo-full-stats/xivo-full-stats.log\e[0m"
    echo

    display_progress "${cel_min_id}" "${cel_count_nb}" 1 30

    echo
    echo -e "\e[32mRecompilation complete !\e[0m"

    echo
    echo -e "Once recomputation of call history is done, you can relaunch pack-reporting docker through"
    echo -e "  \e[1;33mxivocc-dcomp start pack_reporting\e[0m"
    echo -e "(Optional) if you want to recompute the aggregated tables for SpagoBi sample stats reports"
    echo -e "  \e[1;33msee: https://gitlab.com/xivo.solutions/pack-reporting#recalculate-statistics\e[0m"
}

main "${@}"
