#!/bin/bash

# --workdir: work directory
# --tlsdir: work directory
# --cert-allowed-cn: cert allowed cn
# --binary: path to cdc test binary
# --logsuffix: log suffix
# --addr: address
# --pd: pd address
# --redact-info-log: log redaction mode (false|true|marker)
#                    Generates a config file with [security] redact-info-log setting
#                    Values: false (OFF, no redaction), true (ON, full redaction),
#                            marker (MARKER, wraps sensitive data with ‹› markers)
#                    Security note: Once enabled via API at runtime, redaction
#                    cannot be disabled to prevent accidental data exposure

set -e

workdir=
tls=
tls_dir=
certcn=
certcn_name="server"
binary=
logsuffix=
addr=
addr_url="127.0.0.1:8300"
pd_addr=
pwd=$pwd
log_level=debug
# Security feature: Log redaction mode (off|on|marker)
# Can be set at startup via config file. Once enabled via API at runtime, it cannot be disabled.
redact_log_mode=
restart=
failpoint=$GO_FAILPOINTS
config_path=
data_dir=
curl_status_cmd=
supposed_to_fail="no"
cluster_id="default"
newarch=

while [[ ${1} ]]; do
	case "${1}" in
	--workdir)
		workdir=${2}
		shift
		;;
	--tlsdir)
		tls_dir=${2}
		tls="--ca ${2}/ca.pem --cert ${2}/server.pem --key ${2}/server-key.pem"
		shift
		;;
	--cert-allowed-cn)
		certcn_name=${2}
		certcn="--cert-allowed-cn ${2}"
		shift
		;;
	--binary)
		binary=${2}
		shift
		;;
	--logsuffix)
		logsuffix=${2}
		shift
		;;
	--addr)
		addr_url=${2}
		addr="--addr ${2}"
		shift
		;;
	--pd)
		pd_addr="--pd ${2}"
		shift
		;;
	--loglevel)
		log_level=${2}
		shift
		;;
	--redact-info-log)
		redact_log_mode="${2}"
		shift
		;;
	--restart)
		restart=${2}
		shift
		;;
	--failpoint)
		failpoint=${2}
		shift
		;;
	--config)
		config_path="--config ${2}"
		shift
		;;
	--supposed-to-fail)
		supposed_to_fail="${2}"
		shift
		;;
	--data-dir)
		data_dir=${2}
		shift
		;;
	--cluster-id)
		cluster_id=${2}
		shift
		;;
	--newarch)
		newarch=${1}
		shift
		;;
	*)
		echo "Unknown parameter: ${1}" >&2
		exit 1
		;;
	esac

	if ! shift; then
		echo 'Missing parameter argument.' >&2
		exit 1
	fi
done

if [ -z "$data_dir" ]; then
	data_dir=${workdir}/cdc_data${logsuffix}
fi

# If redact_log_mode is set, generate a config file with security settings
if [ -n "$redact_log_mode" ]; then
	redact_config_file="${workdir}/cdc_redact${logsuffix}.toml"
	# Convert to recommended TOML format:
	# - "off" -> false (boolean)
	# - "on" -> true (boolean)
	# - "marker" -> "marker" (string, the only string-only option)
	case "$redact_log_mode" in
	off | OFF | false | 0)
		redact_toml_value="false"
		;;
	on | ON | true | 1)
		redact_toml_value="true"
		;;
	marker | MARKER)
		redact_toml_value="\"marker\""
		;;
	*)
		# Pass through as quoted string for other values (may be invalid, will be caught at runtime)
		redact_toml_value="\"$redact_log_mode\""
		;;
	esac
	cat >"$redact_config_file" <<EOF
[security]
redact-info-log = $redact_toml_value
EOF
	# If config_path is already set, we need to merge, otherwise just use this one
	if [ -z "$config_path" ]; then
		config_path="--config $redact_config_file"
	else
		# Append security config to existing config
		existing_config=$(echo "$config_path" | sed 's/--config //')
		cat "$existing_config" >>"$redact_config_file"
		config_path="--config $redact_config_file"
	fi
fi

echo "[$(date)] <<<<<< START cdc server in $TEST_NAME case >>>>>>"
cd $workdir
pid=$$
# Uncomment to turn on grpc versbose log.
# GRPC_GO_LOG_VERBOSITY_LEVEL=99 GRPC_GO_LOG_SEVERITY_LEVEL=debug \

set -x

if [[ "$restart" == "true" ]]; then
	while true; do
		GO_FAILPOINTS=$failpoint $binary -test.coverprofile="$OUT_DIR/cov.$TEST_NAME.$pid.out" server $newarch \
			--log-file $workdir/cdc$logsuffix.log \
			--log-level $log_level \
			--data-dir "$data_dir" \
			--cluster-id "$cluster_id" \
			$config_path \
			$tls \
			$certcn \
			$addr \
			$pd_addr >>$workdir/stdout$logsuffix.log 2>&1
		if [ $? -eq 143 ]; then
			break
		fi
		sleep 1
	done &
else
	GO_FAILPOINTS=$failpoint $binary -test.coverprofile="$OUT_DIR/cov.$TEST_NAME.$pid.out" server \
		--log-file $workdir/cdc$logsuffix.log \
		--log-level $log_level \
		--data-dir "$data_dir" \
		--cluster-id "$cluster_id" \
		$config_path \
		$tls \
		$certcn \
		$addr \
		$pd_addr >>$workdir/stdout$logsuffix.log 2>&1 &
fi

# Make sure cdc is ready to serve

# Because curl may encounter errors,
# it is acceptable and will retry, so you cannot quit.
set +e

# get_info_fail_msg="failed to get info:"
# etcd_info_msg="etcd info"
# # If tls is set, then we need to pass the certificate and use https.
# # Note that the certificate name may be specified.
# if [ -z "$tls_dir" ]; then
# 	curl_status_cmd="curl -vsL --max-time 20 http://$addr_url/api/v2/changefeeds --user ticdc:ticdc_secret -vsL"
# else
# 	curl_status_cmd="curl --cacert $tls_dir/ca.pem --cert $tls_dir/$certcn_name.pem --key $tls_dir/$certcn_name-key.pem --user ticdc:ticdc_secret -vsL --max-time 20 https://$addr_url/api/v2/changefeeds"
# fi

# If the command is supposed to fail (in check usage tips test), just exit without retry
if [[ "$supposed_to_fail" != "no" ]]; then
	set +x
	exit 0
fi

for ((i = 0; i <= 50; i++)); do
	# Check if curl returns HTTP 200 OK status code
	if [ -z "$tls_dir" ]; then
		http_code=$(curl -o /dev/null -s -w "%{http_code}" --max-time 20 "http://$addr_url/api/v2/changefeeds?keyspace=$KEYSPACE_NAME" --user ticdc:ticdc_secret)
	else
		http_code=$(curl -o /dev/null -s -w "%{http_code}" --cacert $tls_dir/ca.pem --cert $tls_dir/$certcn_name.pem --key $tls_dir/$certcn_name-key.pem --user ticdc:ticdc_secret --max-time 20 "https://$addr_url/api/v2/changefeeds?keyspace=$KEYSPACE_NAME")
	fi
	if [ "$http_code" = "200" ]; then
		break
	fi
	if [ "$i" -eq 50 ]; then
		echo 'Failed to start TiCDC'
		exit 1
	fi
	sleep 3
done

set +x

cd $pwd
