#! /bin/bash

[[ "$TRACE" ]] && set -x
set -eE

function usage()
{
    echo "usage: create_shard
        --db <xtable|xstore>
        --shard <shard number with leading zeroes, e.g. 04>
        --token <yc oauth token>
        --dc <comma-separated datacenter list, e.g man,vla,sas>
        --conn-limit <conn limit for xiva_user>
        --disk-size, --resource-preset - same as yc

    Check and modify postgres and pooler settings hardcoded in this script
    before running it.
    "
}

function call_yc()
{
    [[ "$YC_OAUTH" && "$YC_CLOUD_ID" && "$YC_FOLDER_ID" ]] || {
        echo "yc oauth/cloud_id/folder_id not set!"
        usage
        exit 1
    }
    yc managed-postgresql $1 \
        ${@:2} \
        --endpoint gw.db.yandex-team.ru:443 \
        --token "$YC_OAUTH" \
        --cloud-id "$YC_CLOUD_ID" \
        --folder-id "$YC_FOLDER_ID" \
        > /dev/null
}

function list_hosts()
{
    [[ "$YC_OAUTH" && "$YC_CLOUD_ID" && "$YC_FOLDER_ID" ]] || {
        echo "yc oauth/cloud_id/folder_id not set!"
        usage
        exit 1
    }
    yc managed-postgresql hosts list \
        --cluster-name "$1" \
        --format json \
        --endpoint gw.db.yandex-team.ru:443 \
        --token "$YC_OAUTH" \
        --cloud-id "$YC_CLOUD_ID" \
        --folder-id "$YC_FOLDER_ID" \
    | jq -r '[.[] | .name] | .[0] + "," + .[1] + "," + .[2]'
}

function get_pg_password()
{
    PG_USER=$1
    [[ "$PG_USER" ]] || {
        echo "no pg user specified!"
        usage
        exit 1
    }
    cat ~/.pgpass | fgrep ":$PG_USER:" | cut -d ':' -f 5
}

function add_hosts()
{
    DC_LIST=$(tr ',' ' ' <<< $1)
    for dc in $DC_LIST; do
        echo --host zone-id="$dc"
    done
}

# Hardcode values for mail/xiva, this is xiva/dba, after all.
YC_CLOUD_ID="foo5sqejtfl92l0d10bt"
YC_FOLDER_ID="foocn84l3bfvv91tsdkb"

while [[ -n "$1" ]]; do
case $1 in
        --db)
            shift
            DB_TYPE=$1
            ;;
        --shard)
            shift
            SHARD=$1
            ;;
        --description)
            shift
            CLUSTER_DESCRIPTION=$1
            ;;
        --token)
            shift
            YC_OAUTH=$1
            ;;
        --cloud-id)
            shift
            YC_CLOUD_ID=$1
            ;;
        --folder-id)
            shift
            YC_FOLDER_ID=$1
            ;;
        --dc)
            shift
            CLUSTER_DC=$1
            ;;
        --disk-size)
            shift
            CLUSTER_DISK_SIZE=$1
            ;;
        --resource-preset)
            shift
            CLUSTER_RESOURCE_PRESET=$1
            ;;
        --conn-limit)
            shift
            CLUSTER_CONN_LIMIT=$1
            ;;
        -h | --help)
            usage
            exit
            ;;
    esac
    shift
done

DB_NAME="${DB_TYPE}_${QLOUD_ENVIRONMENT}_${SHARD}"
CLUSTER_NAME="xiva_${DB_NAME}"

if [[ "$QLOUD_ENVIRONMENT" == "production" || "$QLOUD_ENVIRONMENT" == "corp" ]]; then
    YC_ENVIRONMENT="production"
else
    YC_ENVIRONMENT="prestable"
fi

echo 'Creating cluster...'
call_yc cluster create \
    --name "$CLUSTER_NAME" \
    --environment "$YC_ENVIRONMENT" \
    --network-id not_needed \
    $(add_hosts "$CLUSTER_DC") \
    --database name="$DB_NAME",owner=xiva_admin,lc-collate=C,lc-ctype=C \
    --user name=xiva_admin,password="$(get_pg_password xiva_admin)",permission="$DB_NAME",conn-limit=10 \
    --user name=xiva_user,password="$(get_pg_password xiva_user)",permission="$DB_NAME",conn-limit="$CLUSTER_CONN_LIMIT" \
    --user name=xiva_user_ro,password="$(get_pg_password xiva_user_ro)",permission="$DB_NAME",conn-limit=50 \
    --disk-size "$CLUSTER_DISK_SIZE"  \
    --disk-type local-ssd \
    --resource-preset "$CLUSTER_RESOURCE_PRESET"

# TODO: pick up custom settings automatically from shard 01
echo 'Setting custom pooler configuration...'
call_yc cluster update "$CLUSTER_NAME" \
    --connection-pool-discard=0

echo 'Setting custom postgres configuration...'
call_yc cluster update-config "$CLUSTER_NAME" \
    --set shared_buffers=34359738368 \
    --set vacuum_cost_page_hit=1 \
    --set vacuum_cost_page_miss=10 \
    --set vacuum_cost_page_dirty=20 \
    --set vacuum_cost_limit=200 \
    --set synchronous_commit=SYNCHRONOUS_COMMIT_OFF \
    --set checkpoint_timeout=1800000 \
    --set max_wal_size=68719476736 \
    --set min_wal_size=34359738368 \
    --set default_statistics_target=1000 \
    --set log_min_duration_statement=2000 \
    --set lock_timeout=1000

echo 'Granting roles...'
call_yc user update xiva_admin \
    --cluster-name "$CLUSTER_NAME" \
    --grants=mdb_admin,mdb_replication

call_yc user update xiva_user \
    --cluster-name "$CLUSTER_NAME" \
    --grants=mdb_admin

echo 'Initializing postgres extenstions...'
call_yc database update "$DB_NAME" \
    --cluster-name "$CLUSTER_NAME" \
    --extensions pg_stat_kcache=default,pg_stat_statements=default

echo 'Applying latest xivadb migration...'
ADMIN_CONNINFO="host=$(list_hosts $CLUSTER_NAME) \
    port=6432 \
    dbname=$DB_NAME \
    user=xiva_admin \
    sslmode=verify-full \
    target_session_attrs=read-write"
LATEST_MIGRATION=$(ls -1 /sql/xtable/migrations/ | tail -1 | egrep -o 'V[0-9]+' | tail -c +2)
migrate "$DB_TYPE" "$ADMIN_CONNINFO" "$LATEST_MIGRATION" 2>/dev/null

echo 'Done. Conninfo for hub config:'
echo $ADMIN_CONNINFO | sed 's/xiva_admin/xiva_user/'