#!/bin/zsh
set -e

CONTAINER_NAME="${CONTAINER_NAME:-zhctapp_v2_0}"
IMAGE_NAME="${IMAGE_NAME:-zhctapp:v2.0-node14-current-20260507_114848}"
HOST_PORT="${HOST_PORT:-80}"
PC_PORT="${PC_PORT:-8080}"
MOBILE_PORT="${MOBILE_PORT:-8081}"
SCREEN_PORT="${SCREEN_PORT:-8082}"
ACCESS_HOST="${ACCESS_HOST:-localhost}"
NETWORK_NAME="${NETWORK_NAME:-zhct_default}"
REDIS_CONTAINER_NAME="${REDIS_CONTAINER_NAME:-zhct-redis}"
REDIS_IMAGE="${REDIS_IMAGE:-redis:7-alpine}"
START_REDIS_CONTAINER="${START_REDIS_CONTAINER:-0}"
AUTO_START_FRONTENDS="${AUTO_START_FRONTENDS:-1}"
AUTO_NPM_INSTALL="${AUTO_NPM_INSTALL:-1}"
FORCE_RESTART_FRONTENDS="${FORCE_RESTART_FRONTENDS:-0}"
FRONTEND_READY_TIMEOUT="${FRONTEND_READY_TIMEOUT:-180}"
STRICT_API_CHECK="${STRICT_API_CHECK:-0}"
ZHCT_PROXY_TARGET="${ZHCT_PROXY_TARGET:-http://127.0.0.1}"

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
ZHCT_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"

echo "==> 正在启动 Docker Desktop..."
open -a Docker >/dev/null 2>&1 || true

echo "==> 等待 Docker daemon 就绪..."
for i in {1..30}; do
  if docker ps >/dev/null 2>&1; then
    echo "==> Docker 已就绪"
    break
  fi
  sleep 2
done

if ! docker ps >/dev/null 2>&1; then
  echo "==> Docker 启动超时，请稍后重试"
  exit 1
fi

mkdir -p "${ZHCT_ROOT}/zhctproject/store" \
  "${ZHCT_ROOT}/zhctproject/store20" \
  "${ZHCT_ROOT}/zhctproject/ai_api" \
  "${ZHCT_ROOT}/zhctproject/ai_store" \
  "${ZHCT_ROOT}/zhctproject/ai_app" \
  "${ZHCT_ROOT}/zhctlogs/wwwlogs"

patch_container_open_basedir() {
  echo "==> 修正容器 PHP open_basedir 和本地日志路径..."
  docker exec "${CONTAINER_NAME}" bash -lc '
set -e
extra="/workspace/zhct/zhctproject/store/:/workspace/zhct/zhctproject/ai_api/:/workspace/zhct/zhctproject/ai_store/:/workspace/zhct/zhctproject/ai_app/:"
for f in /usr/local/nginx/conf/fastcgi.conf /etc/nginx/fastcgi.conf; do
  [ -f "$f" ] || continue
  if ! grep -q "/workspace/zhct/zhctproject/ai_api/" "$f"; then
    sed -i "s|open_basedir=\$document_root/../:|open_basedir=\$document_root/../:${extra}|g" "$f"
  fi
done
if [ -f /workspace/zhct/zhctproject/ai_api/.env.local ]; then
  sed -i \
    -e "s|/workspace/wwwroot/log/aizhct/|/workspace/zhct/zhctlogs/log/aizhct/|g" \
    -e "s|/var/www/html/runtime/log/|/workspace/zhct/zhctlogs/log/aizhct/|g" \
    /workspace/zhct/zhctproject/ai_api/.env.local
fi
nginx -c /usr/local/nginx/conf/nginx.conf -t >/dev/null
nginx -c /usr/local/nginx/conf/nginx.conf -s reload >/dev/null 2>&1 || true
'
}

sync_container_nginx_config() {
  echo "==> 同步本地 Nginx 配置到容器..."
  docker cp "${SCRIPT_DIR}/config/nginx/conf/." "${CONTAINER_NAME}:/usr/local/nginx/conf/"
}

ensure_docker_network() {
  if ! docker network inspect "${NETWORK_NAME}" >/dev/null 2>&1; then
    echo "==> 创建 Docker 网络 ${NETWORK_NAME}..."
    docker network create "${NETWORK_NAME}" >/dev/null
  fi
}

ensure_redis_container() {
  if [[ "${START_REDIS_CONTAINER}" != "1" ]]; then
    ensure_docker_network
    echo "==> 跳过伴随 Redis 容器：START_REDIS_CONTAINER=${START_REDIS_CONTAINER}"
    return 0
  fi

  ensure_docker_network

  if ! docker ps -a --format '{{.Names}}' | grep -qx "${REDIS_CONTAINER_NAME}"; then
    echo "==> 创建 Redis 容器 ${REDIS_CONTAINER_NAME}..."
    docker run -d \
      --name "${REDIS_CONTAINER_NAME}" \
      --network "${NETWORK_NAME}" \
      --network-alias redis \
      "${REDIS_IMAGE}" >/dev/null
  else
    echo "==> 启动 Redis 容器 ${REDIS_CONTAINER_NAME}..."
    docker start "${REDIS_CONTAINER_NAME}" >/dev/null
    if ! docker inspect -f '{{range $name, $_ := .NetworkSettings.Networks}}{{println $name}}{{end}}' "${REDIS_CONTAINER_NAME}" | grep -qx "${NETWORK_NAME}"; then
      docker network connect --alias redis "${NETWORK_NAME}" "${REDIS_CONTAINER_NAME}" >/dev/null
    elif ! docker inspect -f '{{range $name, $network := .NetworkSettings.Networks}}{{if eq $name "'"${NETWORK_NAME}"'"}}{{range $network.Aliases}}{{println .}}{{end}}{{end}}{{end}}' "${REDIS_CONTAINER_NAME}" | grep -qx "redis"; then
      docker network disconnect "${NETWORK_NAME}" "${REDIS_CONTAINER_NAME}" >/dev/null 2>&1 || true
      docker network connect --alias redis "${NETWORK_NAME}" "${REDIS_CONTAINER_NAME}" >/dev/null
    fi
  fi
}

validate_existing_container() {
  local expected_log_mount="${ZHCT_ROOT}/zhctlogs/wwwlogs"
  local existing_image
  local existing_root_mount
  local existing_log_mount
  local existing_host_ports
  local existing_pc_ports
  local existing_mobile_ports
  local existing_screen_ports
  local mismatch=0

  existing_image="$(docker inspect -f '{{.Config.Image}}' "${CONTAINER_NAME}")"
  existing_root_mount="$(docker inspect -f '{{range .Mounts}}{{if eq .Destination "/workspace/zhct"}}{{.Source}}{{end}}{{end}}' "${CONTAINER_NAME}")"
  existing_log_mount="$(docker inspect -f '{{range .Mounts}}{{if eq .Destination "/workspace/wwwlogs"}}{{.Source}}{{end}}{{end}}' "${CONTAINER_NAME}")"
  existing_host_ports="$(docker inspect -f '{{range $port, $bindings := .NetworkSettings.Ports}}{{if eq $port "80/tcp"}}{{range $bindings}}{{.HostPort}} {{end}}{{end}}{{end}}' "${CONTAINER_NAME}" | tr ' ' '\n' | sed '/^$/d' | sort -u | xargs)"
  existing_pc_ports="$(docker inspect -f '{{range $port, $bindings := .NetworkSettings.Ports}}{{if eq $port "8080/tcp"}}{{range $bindings}}{{.HostPort}} {{end}}{{end}}{{end}}' "${CONTAINER_NAME}" | tr ' ' '\n' | sed '/^$/d' | sort -u | xargs)"
  existing_mobile_ports="$(docker inspect -f '{{range $port, $bindings := .NetworkSettings.Ports}}{{if eq $port "8081/tcp"}}{{range $bindings}}{{.HostPort}} {{end}}{{end}}{{end}}' "${CONTAINER_NAME}" | tr ' ' '\n' | sed '/^$/d' | sort -u | xargs)"
  existing_screen_ports="$(docker inspect -f '{{range $port, $bindings := .NetworkSettings.Ports}}{{if eq $port "8082/tcp"}}{{range $bindings}}{{.HostPort}} {{end}}{{end}}{{end}}' "${CONTAINER_NAME}" | tr ' ' '\n' | sed '/^$/d' | sort -u | xargs)"

  if [[ "${existing_image}" != "${IMAGE_NAME}" ]]; then
    echo "==> 容器镜像不一致：当前 ${existing_image}，期望 ${IMAGE_NAME}"
    mismatch=1
  fi

  if [[ "${existing_root_mount}" != "${ZHCT_ROOT}" ]]; then
    echo "==> 项目挂载不一致：当前 ${existing_root_mount:-未挂载}，期望 ${ZHCT_ROOT}"
    mismatch=1
  fi

  if [[ "${existing_log_mount}" != "${expected_log_mount}" ]]; then
    echo "==> 日志挂载不一致：当前 ${existing_log_mount:-未挂载}，期望 ${expected_log_mount}"
    mismatch=1
  fi

  if [[ " ${existing_host_ports} " != *" ${HOST_PORT} "* ]]; then
    echo "==> 后台端口映射不一致：当前 ${existing_host_ports:-未映射}，期望 ${HOST_PORT}->80"
    mismatch=1
  fi

  if [[ " ${existing_pc_ports} " != *" ${PC_PORT} "* ]]; then
    echo "==> PC 端口映射不一致：当前 ${existing_pc_ports:-未映射}，期望 ${PC_PORT}->8080"
    mismatch=1
  fi

  if [[ " ${existing_mobile_ports} " != *" ${MOBILE_PORT} "* ]]; then
    echo "==> 移动端口映射不一致：当前 ${existing_mobile_ports:-未映射}，期望 ${MOBILE_PORT}->8081"
    mismatch=1
  fi

  if [[ " ${existing_screen_ports} " != *" ${SCREEN_PORT} "* ]]; then
    echo "==> 大屏端口映射不一致：当前 ${existing_screen_ports:-未映射}，期望 ${SCREEN_PORT}->8082"
    mismatch=1
  fi

  if [[ "${mismatch}" -eq 1 ]]; then
    echo "==> 容器 ${CONTAINER_NAME} 已存在，但配置与当前启动参数不一致。"
    echo "==> 可选处理："
    echo "    1. 按当前容器端口访问：后台 ${existing_host_ports:-未映射}，PC ${existing_pc_ports:-未映射}，移动端 ${existing_mobile_ports:-未映射}，大屏端 ${existing_screen_ports:-未映射}"
    echo "    2. 指定新的容器名启动：CONTAINER_NAME=${CONTAINER_NAME}_${HOST_PORT} HOST_PORT=${HOST_PORT} PC_PORT=${PC_PORT} MOBILE_PORT=${MOBILE_PORT} SCREEN_PORT=${SCREEN_PORT} ./start_zhct.sh"
    echo "    3. 确认旧容器不再需要后，手动删除重建：docker rm -f ${CONTAINER_NAME}"
    exit 1
  fi
}

start_frontend_dev_server() {
  local label="$1"
  local container_dir="$2"
  local port="$3"
  local script_name="$4"
  local log_file="$5"
  local pid_file="$6"

  if [[ "${AUTO_START_FRONTENDS}" != "1" ]]; then
    echo "==> 跳过${label}开发服务自动启动：AUTO_START_FRONTENDS=${AUTO_START_FRONTENDS}"
    return 0
  fi

  echo "==> 启动${label}开发服务：0.0.0.0:${port}"
  docker exec \
    -e "APP_LABEL=${label}" \
    -e "APP_DIR=${container_dir}" \
    -e "APP_PORT=${port}" \
    -e "APP_SCRIPT=${script_name}" \
    -e "APP_LOG=${log_file}" \
    -e "APP_PID=${pid_file}" \
    -e "AUTO_NPM_INSTALL=${AUTO_NPM_INSTALL}" \
    -e "FORCE_RESTART_FRONTENDS=${FORCE_RESTART_FRONTENDS}" \
    -e "ZHCT_PROXY_TARGET=${ZHCT_PROXY_TARGET}" \
    "${CONTAINER_NAME}" bash -lc '
set -e

stop_pid_tree() {
  local root_pid="$1"
  local child_pid

  if [ -z "$root_pid" ] || ! kill -0 "$root_pid" 2>/dev/null; then
    return 0
  fi

  for child_pid in $(pgrep -P "$root_pid" 2>/dev/null || true); do
    stop_pid_tree "$child_pid"
  done

  kill "$root_pid" 2>/dev/null || true
}

if [ ! -d "$APP_DIR" ]; then
  echo "==> ${APP_LABEL}目录不存在：$APP_DIR"
  exit 1
fi

cd "$APP_DIR"

need_install=0
need_node_sass_rebuild=0
install_full_project_dependencies=0
install_reason=""
install_packages=""

ensure_node_sass_binding() {
  local node_sass_bin="node_modules/.bin/node-sass"
  local node_abi
  local vendor_dir
  local shared_binding
  local candidate

  if [ ! -d node_modules/node-sass ]; then
    return 0
  fi

  if node -e "require(\"node-sass\")" >/dev/null 2>&1; then
    return 0
  fi

  node_abi="$(node -p "process.platform + \"-\" + process.arch + \"-\" + process.versions.modules")"
  vendor_dir="node_modules/node-sass/vendor/${node_abi}"
  shared_binding="/usr/local/share/zhct/node-sass/${node_abi}/binding.node"
  mkdir -p "$vendor_dir"
  mkdir -p "$(dirname "$shared_binding")"

  if [ -f "$shared_binding" ]; then
    cp -f "$shared_binding" "${vendor_dir}/binding.node"
  else
    candidate="$(find /workspace/zhct/zhctproject/store/public \
      -path "*/node_modules/node-sass/vendor/${node_abi}/binding.node" \
      -type f 2>/dev/null | head -n 1)"
    if [ -n "$candidate" ]; then
      cp -f "$candidate" "${vendor_dir}/binding.node"
      cp -f "$candidate" "$shared_binding" 2>/dev/null || true
    fi
  fi

  if node -e "require(\"node-sass\")" >/dev/null 2>&1; then
    echo "==> ${APP_LABEL} node-sass binding 已复用：${node_abi}"
    return 0
  fi

  if [ "$AUTO_NPM_INSTALL" != "1" ]; then
    echo "==> ${APP_LABEL} node-sass binding 不可用，且 AUTO_NPM_INSTALL=${AUTO_NPM_INSTALL}"
    exit 1
  fi

  echo "==> ${APP_LABEL} node-sass binding 不可用，开始从源码编译，日志：${APP_LOG}.node-sass"
  npm config set python /usr/local/bin/python2 >/dev/null 2>&1 || true
  PYTHON=/usr/local/bin/python2 npm rebuild node-sass --build-from-source > "${APP_LOG}.node-sass" 2>&1
  cp -f "${vendor_dir}/binding.node" "$shared_binding" 2>/dev/null || true
  "$node_sass_bin" --version >/dev/null
}

if [ ! -d node_modules ]; then
  need_install=1
  install_full_project_dependencies=1
  install_reason="缺少 node_modules"
elif [ -f package.json ]; then
  set +e
  missing_deps="$(node - <<'"'"'NODE'"'"'
const fs = require("fs");
const path = require("path");
const pkg = JSON.parse(fs.readFileSync("package.json", "utf8"));
const deps = Object.assign({}, pkg.dependencies || {}, pkg.devDependencies || {});
const missing = [];

for (const depName of Object.keys(deps)) {
  const packageJsonPath = path.join(process.cwd(), "node_modules", ...depName.split("/"), "package.json");
  if (!fs.existsSync(packageJsonPath)) {
    missing.push(depName);
  }
}

if (missing.length > 0) {
  process.stdout.write(missing.join(" "));
  process.exit(1);
}
NODE
)"
  missing_status=$?
  set -e

  if [ "$missing_status" -ne 0 ]; then
    need_install=1
    install_full_project_dependencies=1
    install_reason="node_modules 依赖不完整：${missing_deps}"
  fi
fi

if [ "$APP_LABEL" = "PC 端" ] && [ -d node_modules ]; then
  if ! node -e "require(\"qrcode\")" >/dev/null 2>&1; then
    need_install=1
    install_reason="${install_reason:+${install_reason}；}缺少 PC 端必需依赖：qrcode"
    if [ "$install_full_project_dependencies" != "1" ]; then
      install_packages="${install_packages} qrcode@1.5.4"
    fi
  fi
fi

if [ -d node_modules/node-sass ] && ! node -e "require(\"node-sass\")" >/dev/null 2>&1; then
  need_node_sass_rebuild=1
  install_reason="${install_reason:+${install_reason}；}node-sass binding 不适配当前容器架构"
fi

if [ -f "$APP_PID" ]; then
  old_pid="$(cat "$APP_PID" 2>/dev/null || true)"
  if [ -n "$old_pid" ] && kill -0 "$old_pid" 2>/dev/null; then
    restart_reason=""
    if [ "$FORCE_RESTART_FRONTENDS" = "1" ]; then
      restart_reason="FORCE_RESTART_FRONTENDS=1"
    elif [ "$need_install" = "1" ] || [ "$need_node_sass_rebuild" = "1" ]; then
      restart_reason="$install_reason"
    elif [ -f "$APP_LOG" ] && grep -qa "Failed to compile" "$APP_LOG"; then
      restart_reason="最近一次编译失败"
    fi

    if [ -z "$restart_reason" ]; then
      echo "==> ${APP_LABEL}开发服务已在运行，PID ${old_pid}"
      exit 0
    fi

    echo "==> ${APP_LABEL}开发服务需要重启：${restart_reason}"
    stop_pid_tree "$old_pid"
    sleep 1
    if kill -0 "$old_pid" 2>/dev/null; then
      kill -9 "$old_pid" 2>/dev/null || true
    fi
  fi
  rm -f "$APP_PID"
fi

if [ "$need_install" = "1" ]; then
  if [ "$AUTO_NPM_INSTALL" != "1" ]; then
    echo "==> ${APP_LABEL}${install_reason}，且 AUTO_NPM_INSTALL=${AUTO_NPM_INSTALL}"
    exit 1
  fi
  echo "==> ${APP_LABEL}${install_reason}，开始 npm install，日志：${APP_LOG}.install"
  npm config set python /usr/local/bin/python2 >/dev/null 2>&1 || true
  if [ "$install_full_project_dependencies" = "1" ]; then
    npm install --no-save --package-lock=false > "${APP_LOG}.install" 2>&1
    if [ -n "$install_packages" ]; then
      npm install --no-save --package-lock=false ${install_packages} >> "${APP_LOG}.install" 2>&1
    fi
  else
    npm install --no-save --package-lock=false ${install_packages} > "${APP_LOG}.install" 2>&1
  fi
  if [ "$APP_LABEL" = "PC 端" ] && ! node -e "require(\"qrcode\")" >/dev/null 2>&1; then
    echo "==> ${APP_LABEL}补充安装 qrcode@1.5.4" >> "${APP_LOG}.install"
    npm install --no-save --package-lock=false qrcode@1.5.4 >> "${APP_LOG}.install" 2>&1
  fi
fi

ensure_node_sass_binding

rm -f "$APP_LOG"
nohup env HOST=0.0.0.0 PORT="$APP_PORT" BROWSER=none NODE_OPTIONS=--max_old_space_size=4096 \
  npm run "$APP_SCRIPT" > "$APP_LOG" 2>&1 &
echo $! > "$APP_PID"
echo "==> ${APP_LABEL}开发服务启动命令已提交，PID $(cat "$APP_PID")，日志：$APP_LOG"
'
}

wait_frontend_ready() {
  local label="$1"
  local url="$2"
  local log_file="$3"
  local elapsed=0
  local http_status

  echo "==> 等待${label}开发服务就绪：${url}"
  while [[ "${elapsed}" -lt "${FRONTEND_READY_TIMEOUT}" ]]; do
    if docker exec "${CONTAINER_NAME}" bash -lc "grep -qa 'Failed to compile' '${log_file}' 2>/dev/null"; then
      echo "==> ${label}开发服务编译失败，最近日志如下："
      docker exec "${CONTAINER_NAME}" bash -lc "tail -n 120 '${log_file}' 2>/dev/null || true"
      exit 1
    fi

    http_status="$(curl -sS -o /dev/null -w '%{http_code}' --max-time 3 "${url}" 2>/dev/null || true)"
    if [[ "${http_status}" != "000" && "${http_status}" -lt 500 ]] \
      && docker exec "${CONTAINER_NAME}" bash -lc "grep -qaE 'Compiled successfully|App running at|DONE  Compiled successfully' '${log_file}' 2>/dev/null"; then
      echo "==> ${label}开发服务已响应，HTTP ${http_status}"
      return 0
    fi
    sleep 2
    elapsed=$((elapsed + 2))
  done

  echo "==> ${label}开发服务启动超时，最近日志如下："
  docker exec "${CONTAINER_NAME}" bash -lc "tail -n 120 '${log_file}' 2>/dev/null || true"
  exit 1
}

verify_pc_route_contract() {
  local root_content_type
  local restaurant_api_content_type
  local restaurant_api_body

  echo "==> 验证 PC 端页面/接口路径约定..."
  root_content_type="$(curl -sS -D - -o /dev/null --max-time 5 "${PC_URL}/" 2>/dev/null | awk -F': ' 'tolower($1)=="content-type"{print tolower($2)}' | tr -d '\r' | head -n 1)"
  restaurant_api_content_type="$(curl -sS -D - -o /dev/null --max-time 5 "${PC_URL}/p/Restaurant/index" 2>/dev/null | awk -F': ' 'tolower($1)=="content-type"{print tolower($2)}' | tr -d '\r' | head -n 1)"
  restaurant_api_body="$(curl -sS --max-time 5 "${PC_URL}/p/Restaurant/index" 2>/dev/null || true)"

  if [[ "${root_content_type}" != *"text/html"* ]]; then
    echo "==> PC 端根入口返回类型异常：${root_content_type:-未获取到 Content-Type}"
    exit 1
  fi

  if [[ "${restaurant_api_content_type}" != *"application/json"* ]]; then
    echo "==> 提醒：${PC_URL}/p/Restaurant/index 当前未返回 JSON，Content-Type=${restaurant_api_content_type:-未获取到 Content-Type}"
  elif [[ "${restaurant_api_body}" == *'"code":100'* ]]; then
    echo "==> ${PC_URL}/p/Restaurant/index 是后端接口，当前返回未登录业务状态 code=100，不能当页面入口访问"
  else
    echo "==> ${PC_URL}/p/Restaurant/index 是后端接口，当前返回 JSON"
  fi
}

if ! docker ps -a --format '{{.Names}}' | grep -qx "${CONTAINER_NAME}"; then
  ensure_redis_container
  echo "==> 正在创建容器 ${CONTAINER_NAME}..."
  docker run -d \
    --name "${CONTAINER_NAME}" \
    --network "${NETWORK_NAME}" \
    -e "USE_LOCAL_REDIS=${START_REDIS_CONTAINER}" \
    -p "${HOST_PORT}:80" \
    -p "${PC_PORT}:8080" \
    -p "${MOBILE_PORT}:8081" \
    -p "${SCREEN_PORT}:8082" \
    -v "${ZHCT_ROOT}:/workspace/zhct" \
    -v "${ZHCT_ROOT}/zhctlogs/wwwlogs:/workspace/wwwlogs" \
    -v "${SCRIPT_DIR}/scripts/entrypoint.sh:/usr/local/bin/entrypoint.sh:ro" \
    "${IMAGE_NAME}" >/dev/null
else
  ensure_redis_container
  validate_existing_container
  if docker ps --format '{{.Names}}' | grep -qx "${CONTAINER_NAME}"; then
    echo "==> 容器 ${CONTAINER_NAME} 已在运行"
  else
    echo "==> 正在启动容器 ${CONTAINER_NAME}..."
    docker start "${CONTAINER_NAME}" >/dev/null
  fi
  docker network connect "${NETWORK_NAME}" "${CONTAINER_NAME}" >/dev/null 2>&1 || true
fi

echo "==> 等待 ${CONTAINER_NAME} 容器运行..."
for i in {1..30}; do
  if docker ps --format '{{.Names}}' | grep -qx "${CONTAINER_NAME}"; then
    echo "==> ${CONTAINER_NAME} 已运行"
    break
  fi
  sleep 1
done

if ! docker ps --format '{{.Names}}' | grep -qx "${CONTAINER_NAME}"; then
  echo "==> ${CONTAINER_NAME} 启动失败，请执行 docker logs --tail 100 ${CONTAINER_NAME} 查看原因"
  exit 1
fi

if ! docker inspect -f '{{range $name, $_ := .NetworkSettings.Networks}}{{println $name}}{{end}}' "${CONTAINER_NAME}" | grep -qx "${NETWORK_NAME}"; then
  echo "==> 正在把 ${CONTAINER_NAME} 接入网络 ${NETWORK_NAME}..."
  docker network connect "${NETWORK_NAME}" "${CONTAINER_NAME}"
fi

sync_container_nginx_config
patch_container_open_basedir

BASE_URL="http://${ACCESS_HOST}:${HOST_PORT}"
PC_URL="http://${ACCESS_HOST}:${PC_PORT}"
MOBILE_URL="http://${ACCESS_HOST}:${MOBILE_PORT}"
SCREEN_URL="http://${ACCESS_HOST}:${SCREEN_PORT}"
AIZHCT_DISH_CATE_PATH="/aizhct/index.php?s=api/dishes.dishes/cate"

if [[ "${HOST_PORT}" == "80" ]]; then
  DISPLAY_BASE_URL="http://${ACCESS_HOST}"
else
  DISPLAY_BASE_URL="${BASE_URL}"
fi
DISPLAY_AIZHCT_URL="${DISPLAY_BASE_URL}/aizhct"

echo "==> 等待 Web 服务就绪：${BASE_URL}"
for i in {1..30}; do
  http_status="$(curl -sS -o /dev/null -w '%{http_code}' --max-time 3 "${BASE_URL}/" 2>/dev/null || true)"
  if [[ "${http_status}" != "000" && "${http_status}" -lt 500 ]]; then
    echo "==> Web 服务已响应，HTTP ${http_status}"
    break
  fi
  sleep 1
done

http_status="$(curl -sS -o /dev/null -w '%{http_code}' --max-time 3 "${BASE_URL}/" 2>/dev/null || true)"
if [[ "${http_status}" == "000" || "${http_status}" -ge 500 ]]; then
  echo "==> Web 服务启动异常，HTTP ${http_status}，请执行 docker logs --tail 100 ${CONTAINER_NAME} 查看原因"
  exit 1
fi

echo "==> 验证主项目访问 ${BASE_URL}/ ..."
curl -i --max-time 10 "${BASE_URL}/" || exit 1

echo ""
echo "==> 验证 AI 项目访问 ${BASE_URL}/aizhct/ ..."
curl -i --max-time 10 "${BASE_URL}/aizhct/" || exit 1

echo ""
echo "==> 验证 AI 菜品分类接口 ${BASE_URL}${AIZHCT_DISH_CATE_PATH} ..."
aizhct_dish_cate_response="$(curl -sS -i --max-time 10 "${BASE_URL}${AIZHCT_DISH_CATE_PATH}")" || exit 1
echo "${aizhct_dish_cate_response}"
if [[ "${aizhct_dish_cate_response}" != *'"status":200'* ]]; then
  echo "==> AI 菜品分类接口返回异常，未发现业务状态 status=200"
  if [[ "${STRICT_API_CHECK}" == "1" ]]; then
    exit 1
  fi
  echo "==> STRICT_API_CHECK=${STRICT_API_CHECK}，继续启动前端开发服务"
fi

start_frontend_dev_server "PC 端" \
  "/workspace/zhct/zhctproject/store/public/static" \
  "${PC_PORT}" \
  "dev" \
  "/tmp/store-static.log" \
  "/tmp/store-static.pid"

start_frontend_dev_server "移动端" \
  "/workspace/zhct/zhctproject/store/public/mobile" \
  "${MOBILE_PORT}" \
  "serve" \
  "/tmp/store-mobile.log" \
  "/tmp/store-mobile.pid"

start_frontend_dev_server "大屏端" \
  "/workspace/zhct/zhctproject/store/public/screen" \
  "${SCREEN_PORT}" \
  "dev" \
  "/tmp/store-screen.log" \
  "/tmp/store-screen.pid"

wait_frontend_ready "PC 端" "${PC_URL}/" "/tmp/store-static.log"
wait_frontend_ready "移动端" "${MOBILE_URL}/" "/tmp/store-mobile.log"
wait_frontend_ready "大屏端" "${SCREEN_URL}/" "/tmp/store-screen.log"
verify_pc_route_contract

echo ""
echo "==> 项目启动流程执行完成"
echo "==> 本机访问入口："
echo "    后台：${DISPLAY_BASE_URL}"
echo "    AI 项目：${DISPLAY_AIZHCT_URL}"
echo "    PC 端：${PC_URL}/#/login"
echo "    PC 餐厅管理页面：${PC_URL}/#/restaurantManagement/restaurantManagement"
echo "    移动端：${MOBILE_URL}"
echo "    大屏端：${SCREEN_URL}"
echo "==> 注意：${PC_URL}/p/Restaurant/index 是后端接口路径，不是 PC 页面入口；未登录时返回 JSON code=100 属于正常鉴权结果。"
echo "==> 默认启动 Node14 store 三端：zhctprompt/docker/scripts/start_store_frontends.sh"
echo "==> 切换启动 Node20 store20 三端：zhctprompt/docker/scripts/start_store20_frontends.sh"
