#!/bin/bash
# 安职通 一键部署脚本
# 部署到 154.8.162.18 -> /var/www/turbohr/ -> https://on.hr8ai.top/
#
# 用法: bash deploy.sh
# 首次部署: bash deploy.sh --init

set -e

# ===========================================
# 配置区
# ===========================================
REMOTE_HOST="154.8.162.18"
REMOTE_USER="root"
REMOTE_PASS="Why_701208"
REMOTE_DIR="/var/www/turbohr"
DOMAIN="on.hr8ai.top"
APP_NAME="turbohr"
BACKEND_PORT=3400
LOCAL_DIR="$(cd "$(dirname "$0")" && pwd)"

# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'

log() { echo -e "${GREEN}[deploy]${NC} $1"; }
warn() { echo -e "${YELLOW}[warn]${NC} $1"; }
err() { echo -e "${RED}[error]${NC} $1"; }

# 检查 sshpass
if ! command -v sshpass &> /dev/null; then
    err "请先安装 sshpass: macOS -> brew install hudochenkov/sshpass/sshpass"
    exit 1
fi

SSH_CMD="sshpass -p '$REMOTE_PASS' ssh -o StrictHostKeyChecking=no ${REMOTE_USER}@${REMOTE_HOST}"
SCP_CMD="sshpass -p '$REMOTE_PASS' scp -o StrictHostKeyChecking=no"

# ===========================================
# 远程执行命令的封装
# ===========================================
remote_exec() {
    sshpass -p "$REMOTE_PASS" ssh -o StrictHostKeyChecking=no "${REMOTE_USER}@${REMOTE_HOST}" "$1"
}

remote_copy() {
    sshpass -p "$REMOTE_PASS" scp -o StrictHostKeyChecking=no -r "$1" "${REMOTE_USER}@${REMOTE_HOST}:$2"
}

# ===========================================
# 首次初始化：创建数据库 + Nginx 配置（系统依赖已预装）
# ===========================================
init_server() {
    log "========== 首次初始化服务器 =========="

    remote_exec "
set -e

# 服务器已有: Node.js, PM2, PostgreSQL 15, Nginx, Redis, 宝塔面板
# 端口 3000-3300 已被占用，本应用使用端口 ${BACKEND_PORT}

echo '[1/4] 创建 PostgreSQL 数据库...'
sudo -u postgres psql -c \"CREATE DATABASE turbohr;\" 2>/dev/null || echo '  数据库 turbohr 已存在'
sudo -u postgres psql -c \"CREATE USER turbohr WITH PASSWORD 'turbohr2026';\" 2>/dev/null || echo '  用户 turbohr 已存在'
sudo -u postgres psql -c \"GRANT ALL PRIVILEGES ON DATABASE turbohr TO turbohr;\" 2>/dev/null || true
sudo -u postgres psql -c \"ALTER USER turbohr WITH SUPERUSER;\" 2>/dev/null || true
echo '  PostgreSQL 数据库 turbohr 就绪'

echo '[2/4] 创建部署目录...'
mkdir -p ${REMOTE_DIR}/backend
mkdir -p ${REMOTE_DIR}/frontend/dist
mkdir -p ${REMOTE_DIR}/backend/uploads

echo '[3/4] 配置 Nginx (conf.d)...'
cat > /etc/nginx/conf.d/${DOMAIN}.conf << 'NGINXEOF'
server {
    listen 80;
    server_name __DOMAIN__;

    # 前端静态文件
    location / {
        root __REMOTE_DIR__/frontend/dist;
        index index.html;
        try_files \$uri \$uri/ /index.html;

        # 静态资源缓存
        location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)\$ {
            expires 30d;
            add_header Cache-Control \"public, immutable\";
        }
    }

    # 后端 API 反向代理
    location /api/ {
        proxy_pass http://127.0.0.1:__BACKEND_PORT__;
        proxy_http_version 1.1;
        proxy_set_header Host \$host;
        proxy_set_header X-Real-IP \$remote_addr;
        proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto \$scheme;

        # SSE 流式输出支持（AI 对话）
        proxy_buffering off;
        proxy_cache off;
        proxy_set_header Connection '';

        # 超时设置（AI 生成可能较慢）
        proxy_read_timeout 300s;
        proxy_send_timeout 300s;

        # 文件上传
        client_max_body_size 10m;
    }

    # 上传文件访问
    location /uploads/ {
        alias __REMOTE_DIR__/backend/uploads/;
    }

    # 安全头
    add_header X-Frame-Options \"SAMEORIGIN\";
    add_header X-Content-Type-Options \"nosniff\";
    add_header X-XSS-Protection \"1; mode=block\";

    # Gzip 压缩
    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml text/javascript;
    gzip_min_length 1000;
}
NGINXEOF

# 替换占位符
sed -i 's|__DOMAIN__|${DOMAIN}|g' /etc/nginx/conf.d/${DOMAIN}.conf
sed -i 's|__REMOTE_DIR__|${REMOTE_DIR}|g' /etc/nginx/conf.d/${DOMAIN}.conf
sed -i 's|__BACKEND_PORT__|${BACKEND_PORT}|g' /etc/nginx/conf.d/${DOMAIN}.conf

nginx -t && systemctl reload nginx

echo '[4/4] 检查 certbot...'
if ! command -v certbot &> /dev/null; then
    echo '  certbot 未安装，SSL 将在部署后手动配置'
else
    echo '  certbot 已安装'
fi

echo ''
echo '========================================='
echo '  系统初始化完成!'
echo '  数据库: turbohr (用户: turbohr)'
echo '  端口: ${BACKEND_PORT} (避开 3000-3300)'
echo '  Nginx: ${DOMAIN} -> :80 (conf.d)'
echo '========================================='
    "

    log "系统初始化完成"
}

# ===========================================
# 构建前端
# ===========================================
build_frontend() {
    log "========== 构建前端 =========="

    cd "${LOCAL_DIR}/frontend"

    if [ ! -d node_modules ]; then
        log "安装前端依赖..."
        npm install
    fi

    log "构建前端..."
    npm run build

    if [ ! -d dist ]; then
        err "前端构建失败，dist 目录不存在"
        exit 1
    fi

    log "前端构建完成: dist/ ($(du -sh dist | cut -f1))"
}

# ===========================================
# 构建后端
# ===========================================
build_backend() {
    log "========== 构建后端 =========="

    cd "${LOCAL_DIR}/backend"

    if [ ! -d node_modules ]; then
        log "安装后端依赖..."
        npm install
    fi

    log "生成 Prisma Client..."
    npx prisma generate

    # 服务器用 tsx 直接运行 TS 源码，跳过 tsc 编译
    log "跳过 tsc 编译（服务器使用 tsx 运行）"
}

# ===========================================
# 部署到服务器
# ===========================================
deploy_files() {
    log "========== 部署文件到服务器 =========="

    # 同步后端（排除 node_modules、.env、uploads、备份文件）
    log "[1/4] 同步后端代码..."
    sshpass -p "$REMOTE_PASS" rsync -avz --delete \
        --exclude='node_modules' \
        --exclude='.env' \
        --exclude='uploads/*' \
        --exclude='*.dump' \
        --exclude='backups' \
        "${LOCAL_DIR}/backend/" "${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_DIR}/backend/"

    # 同步后端 package.json 和 prisma（确保依赖和 schema 同步）
    log "[2/4] 同步前端静态文件..."
    sshpass -p "$REMOTE_PASS" rsync -avz --delete \
        "${LOCAL_DIR}/frontend/dist/" "${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_DIR}/frontend/dist/"

    # 在服务器上安装后端依赖 + 生成 Prisma Client
    log "[3/4] 服务器端安装依赖..."
    remote_exec "cd ${REMOTE_DIR}/backend && npm install --production=false 2>&1 | tail -5"

    log "[4/4] 生成 Prisma Client..."
    remote_exec "cd ${REMOTE_DIR}/backend && npx prisma generate 2>&1 | tail -3"
}

# ===========================================
# 配置 .env（首次或更新）
# ===========================================
setup_env() {
    log "========== 配置环境变量 =========="

    # 检查远程是否已有 .env，如果没有则创建
    remote_exec "
if [ ! -f ${REMOTE_DIR}/backend/.env ]; then
    echo '创建 .env 文件...'
    cat > ${REMOTE_DIR}/backend/.env << 'ENVEOF'
# 数据库
DATABASE_URL=postgresql://turbohr:turbohr2026@localhost:5432/turbohr?schema=public

# JWT
JWT_SECRET=turbohr-jwt-secret-2026-change-me
JWT_REFRESH_SECRET=turbohr-refresh-secret-2026-change-me

# DashScope (通义千问) - 请填写实际 API Key
DASHSCOPE_API_KEY=sk-xxx
DASHSCOPE_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1

# 加密
ENCRYPTION_KEY=turbohr-32byte-encryption-key-here

# 存储
SUPABASE_URL=
SUPABASE_KEY=

# 部署
PORT=${BACKEND_PORT}
CORS_ORIGIN=https://${DOMAIN}
ENVEOF
    echo '.env 已创建，请编辑 ${REMOTE_DIR}/backend/.env 填写实际配置'
else
    echo '.env 已存在，跳过创建'
fi
    "
}

# ===========================================
# 数据库迁移
# ===========================================
migrate_db() {
    log "========== 数据库迁移 =========="
    remote_exec "cd ${REMOTE_DIR}/backend && npx prisma db push --accept-data-loss 2>&1 | tail -10"
    log "数据库 schema 同步完成"
}

# ===========================================
# 配置 PM2 + 启动服务
# ===========================================
start_service() {
    log "========== 启动服务 =========="

    remote_exec "
cd ${REMOTE_DIR}/backend

# 停止旧进程
pm2 delete ${APP_NAME} 2>/dev/null || true

# 使用 tsx 运行 TypeScript 源码（避免 ESM 扩展名问题）
pm2 start npx --name ${APP_NAME} --max-memory-restart 512M -- tsx src/index.ts

# 保存 PM2 配置
pm2 save

# 配置开机自启
pm2 startup systemd -u root --hp /root 2>/dev/null | tail -3

echo 'PM2 进程:'
pm2 list
    "

    log "服务已启动"
}

# ===========================================
# 配置 SSL 证书
# ===========================================
setup_ssl() {
    log "========== 配置 SSL 证书 =========="

    remote_exec "
# 使用 --nginx 插件自动配置 SSL
certbot --nginx -d ${DOMAIN} --non-interactive --agree-tos --register-unsafely-without-email --redirect 2>&1 && echo 'SSL 证书配置成功' || echo 'SSL 证书配置失败，可稍后手动执行: certbot --nginx -d ${DOMAIN}'
    "
}

# ===========================================
# 验证部署
# ===========================================
verify() {
    log "========== 验证部署 =========="

    # 检查后端
    BACKEND_CODE=$(remote_exec "curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:${BACKEND_PORT}/api/v1/health 2>/dev/null || echo '000'")
    log "后端 /api/v1/health -> HTTP ${BACKEND_CODE}"

    # 检查前端
    FRONTEND_CODE=$(remote_exec "curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1/ 2>/dev/null || echo '000'")
    log "前端 (Nginx) -> HTTP ${FRONTEND_CODE}"

    # 检查域名
    DOMAIN_CODE=$(curl -s -o /dev/null -w '%{http_code}' "https://${DOMAIN}/" 2>/dev/null || echo '000')
    log "域名 https://${DOMAIN} -> HTTP ${DOMAIN_CODE}"

    # PM2 状态
    remote_exec "pm2 describe ${APP_NAME} 2>/dev/null | grep -E 'status|restarts|uptime|pid'"

    echo ""
    echo "========================================="
    echo "  安职通 部署完成!"
    echo "  访问地址: https://${DOMAIN}/"
    echo "  后端 API: https://${DOMAIN}/api/v1/"
    echo "  PM2 管理: pm2 list (服务器上)"
    echo "========================================="
}

# ===========================================
# 主流程
# ===========================================
IS_INIT=false
if [ "$1" = "--init" ]; then
    IS_INIT=true
fi

log "开始部署 安职通 到 ${REMOTE_HOST}"
log "域名: ${DOMAIN}  目录: ${REMOTE_DIR}"
echo ""

if [ "$IS_INIT" = true ]; then
    init_server
    setup_env
    echo ""
    warn "首次初始化完成，请先编辑服务器上的 ${REMOTE_DIR}/backend/.env 填写实际配置"
    warn "然后重新运行: bash deploy.sh"
    exit 0
fi

build_frontend
build_backend
deploy_files
setup_env
migrate_db
start_service
verify
