#!/usr/bin/env bash
set -euo pipefail

DOMAIN="${1:-}"
EMAIL="${2:-}"
WEBROOT="${3:-/var/www/letsencrypt}"
AUTO_INSTALL_Nginx="${AUTO_INSTALL_Nginx:-0}"

# ----------------------- UI / Logging -----------------------
ts() { date '+%Y-%m-%d %H:%M:%S'; }

# 강한 구분(색상 + 굵은 라인). 색상 미지원 터미널이면 글자만 출력됨.
step() {
	echo
	echo -e "\033[1;35m════════════════════════════════════════════════════════════\033[0m"
	echo -e "\033[1;32m▶ STEP [$1]\033[0m"
	echo -e "\033[1;35m════════════════════════════════════════════════════════════\033[0m"
}

info() { echo -e "\033[1;36m[$(ts)]\033[0m $*"; }
ok() { echo -e "\033[1;32m[$(ts)] OK\033[0m $*"; }
warn() { echo -e "\033[1;33m[$(ts)] WARN\033[0m $*" >&2; }
fail() { echo -e "\033[1;31m[$(ts)] ERROR\033[0m $*" >&2; }

# 실패 지점/명령 출력
trap 'echo; fail "line=$LINENO cmd=$BASH_COMMAND (exit=$?)"' ERR

require_cmd() {
	command -v "$1" > /dev/null 2>&1 || {
		fail "command not found: $1"
		exit 2
	}
}

curl_check() {
	local url="$1"
	local mode="${2:-GET}" # GET or HEAD
	info "curl ${mode} ${url}"

	local code
	if [[ "$mode" == "HEAD" ]]; then
		code="$(curl -sSI --connect-timeout 5 --max-time 10 "$url" -o /dev/null -w "%{http_code}")"
	else
		code="$(curl -sS --connect-timeout 5 --max-time 10 "$url" -o /dev/null -w "%{http_code}")"
	fi

	if [[ "$code" == "000" ]]; then
		fail "curl failed (code 000) url=$url"
		return 1
	fi
	ok "curl OK (HTTP $code)"
}
# -----------------------------------------------------------

if [[ -z "$DOMAIN" || -z "$EMAIL" ]]; then
	echo "Usage: $0 <DomainName> <E-Mail> [WebrootDir]" >&2
	exit 2
fi

if [[ ! -d "$WEBROOT" ]]; then
	fail "WebrootDir not found: $WEBROOT"
	exit 2
fi

require_cmd nginx
require_cmd certbot
require_cmd curl
require_cmd openssl

ACME_PING_PATH="$WEBROOT/.well-known/acme-challenge/ping"
HTTP_PING_URL="http://$DOMAIN/.well-known/acme-challenge/ping"
HTTPS_URL="https://$DOMAIN"

step "1/7 nginx config test + reload"
info "nginx -t"
sudo nginx -t
info "systemctl reload nginx"
sudo systemctl reload nginx
ok "[1/7] DONE"

step "2/7 ACME webroot check (webroot 방식 전용)"
info "write ping file: $ACME_PING_PATH"
echo ok | sudo tee "$ACME_PING_PATH" > /dev/null
curl_check "$HTTP_PING_URL" "GET"
ok "[2/7] DONE"

step "3/7 Staging issue"
info "certbot certonly (staging) domain=$DOMAIN webroot=$WEBROOT email=$EMAIL"
sudo certbot certonly --webroot -w "$WEBROOT" -d "$DOMAIN" \
	--staging --no-eff-email --agree-tos -m "$EMAIL" -v
ok "[3/7] DONE"

step "4/7 Staging cert issuer check"
info "openssl x509 issuer (staging)"
sudo openssl x509 -in "/etc/letsencrypt/live/$DOMAIN/fullchain.pem" -noout -issuer
ok "[4/7] DONE"

step "5/7 Production issue (force-renewal)"
info "certbot certonly (production) domain=$DOMAIN webroot=$WEBROOT email=$EMAIL"
sudo certbot certonly --webroot -w "$WEBROOT" -d "$DOMAIN" \
	--force-renewal --no-eff-email --agree-tos -m "$EMAIL" -v
ok "[5/7] DONE"

step "6/7 nginx SSL apply policy"
if [[ "$AUTO_INSTALL_Nginx" == "1" ]]; then
	warn "AUTO_INSTALL_Nginx=1: certbot install 을 수행함 (nginx 설정 파일 변경 가능)"
	sudo certbot install --cert-name "$DOMAIN"
	ok "[6/7] DONE (certbot install)"
else
	info "운영 표준: nginx 설정에 아래 인증서 경로를 수동 반영"
	echo "ssl_certificate     /etc/letsencrypt/live/$DOMAIN/fullchain.pem;"
	echo "ssl_certificate_key /etc/letsencrypt/live/$DOMAIN/privkey.pem;"
	ok "[6/7] DONE (manual apply mode)"
fi

step "7/7 nginx reload + HTTPS check"
info "nginx -t"
sudo nginx -t
info "systemctl reload nginx"
sudo systemctl reload nginx

info "HTTPS check (status code only): $HTTPS_URL"
HTTP_CODE="$(curl -sSI --connect-timeout 5 --max-time 10 "$HTTPS_URL" -o /dev/null -w "%{http_code}")" || {
	warn "HTTPS check failed (connect/timeout). 아래로 원인 확인:"
	warn "  - curl -vI --max-time 15 $HTTPS_URL"
	warn "  - sudo ss -lntp | grep ':443'"
	warn "  - sudo tail -n 200 /var/log/nginx/error.log"
	exit 1
}

# 000은 보통 연결 실패/핸드셰이크 실패 케이스인데, 위에서 이미 잡히는 게 일반적임.
if [[ "$HTTP_CODE" == "000" ]]; then
	warn "HTTPS responded with code 000 (likely handshake/connect issue)"
	exit 1
fi

ok "HTTPS reachable (HTTP $HTTP_CODE)"

info "TLS handshake + cert check (openssl)"
if openssl s_client -help 2>&1 | grep -q -- '-brief'; then
	echo | openssl s_client -connect "$DOMAIN:443" -servername "$DOMAIN" -brief 2> /dev/null | head -n 20
else
	echo | openssl s_client -connect "$DOMAIN:443" -servername "$DOMAIN" 2> /dev/null | head -n 20
fi

echo | openssl s_client -connect "$DOMAIN:443" -servername "$DOMAIN" 2> /dev/null | openssl x509 -noout -issuer -subject

ok "TLS handshake OK (openssl)"

ok "Done."

exit 0

# =============================================================================
# 권한:
# 	sudo chmod 700 ./ssl-webroot.sh
#
# Windows CRLF / UTF-8 BOM 제거가 필요한 경우:
# 	sudo sed -i '1s/^\xEF\xBB\xBF//' ./ssl-webroot.sh
# 	sudo sed -i 's/\r$//' ./ssl-webroot.sh
#
# 문법 확인:
# 	sudo bash -n ./ssl-webroot.sh
#
# 사용법:
#   sudo bash ./ssl-webroot.sh <DomainName> <E-Mail> [WebrootDir]
#   sudo AUTO_INSTALL_Nginx=1 bash ./ssl-webroot.sh <DomainName> <E-Mail> [WebrootDir]
#
# Examples:
#   sudo bash ./ssl-webroot.sh api.sncompany.com sn.dev.manager@sncompany.com
#   sudo bash ./ssl-webroot.sh api.sncompany.com sn.dev.manager@sncompany.com /var/www/letsencrypt
#   sudo AUTO_INSTALL_Nginx=1 bash ./ssl-webroot.sh api.sncompany.com sn.dev.manager@sncompany.com
