# Worker Zalo chạy bằng giao thức (zca-js) - không còn trình duyệt nào.
#
# Bản Playwright cũ nặng 3.6 GB vì phải kèm Chromium và toàn bộ thư viện hệ thống của nó.
# Bản này chỉ là Node + vài package thuần JS nên dùng được alpine.
#
# Build nhiều tầng: tầng build có devDependencies để chạy tsc, tầng chạy chỉ giữ
# dependencies production và mã đã biên dịch.

# ─── Tầng 1: cài đủ dependency để biên dịch ────────────────────────────────
FROM node:22-alpine AS deps

WORKDIR /app

COPY package.json package-lock.json* ./
# Bản vá zca-js phải có mặt TRƯỚC khi cài: `postinstall` chạy patch-package ngay sau đó.
COPY patches ./patches

# `npm ci` cài đúng bản đã khoá trong lock file. Không có lock thì rơi về `npm install`
# để build đầu tiên trên máy mới vẫn chạy được.
RUN if [ -f package-lock.json ]; then npm ci; else npm install; fi

# ─── Tầng 2: biên dịch TypeScript ──────────────────────────────────────────
FROM node:22-alpine AS build

WORKDIR /app

COPY --from=deps /app/node_modules ./node_modules
COPY package.json tsconfig.json ./
COPY src ./src

RUN npm run build

# ─── Tầng 3: chỉ dependency production ─────────────────────────────────────
FROM node:22-alpine AS prod-deps

WORKDIR /app

COPY package.json package-lock.json* ./
COPY patches ./patches

# `--omit=dev` vẫn phải áp được bản vá, nên `patch-package` nằm ở dependencies chứ không
# phải devDependencies. Thiếu nó thì image production chạy zca-js chưa vá.
RUN if [ -f package-lock.json ]; then npm ci --omit=dev; else npm install --omit=dev; fi \
    && npm cache clean --force

# ─── Tầng 4: image chạy thật ───────────────────────────────────────────────
FROM node:22-alpine AS runtime

# dumb-init để Node nhận đúng SIGTERM: worker cần chạy graceful shutdown, nếu không
# thì tin nhắn còn trong hàng đợi bị mất (không đọc lại được lịch sử chat 1-1).
# xzcat dùng để giải nén container ZDB4 của luồng đồng bộ tin nhắn cũ, thay native Zalo PC.
RUN apk add --no-cache dumb-init xz

ENV NODE_ENV=production

WORKDIR /app

COPY --from=prod-deps /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist
COPY package.json ./

# Thư mục credential phải thuộc về user `node`: container chạy không phải root.
RUN mkdir -p /app/storage/zalo-credentials /app/storage/zalo-mobile-sync \
    && chown -R node:node /app/storage

USER node

EXPOSE 3500

# Health check dùng chính endpoint /api/health (không cần token) để compose biết
# worker đã sẵn sàng nhận request chưa.
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
    CMD node -e "fetch('http://127.0.0.1:3500/api/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"

ENTRYPOINT ["dumb-init", "--"]
# `--experimental-sqlite` bật `node:sqlite`, dùng để đọc file .db giải mã được từ luồng
# đồng bộ tin nhắn cũ (`pull_mobile_msg`) - xem worker/src/zalo/sync-db-parser.ts.
CMD ["node", "--experimental-sqlite", "dist/server.js"]
