# Phase 108.6 / T1 — imagem ÚNICA do bench unificado (CRM + ERP no MESMO site).
#
# Camada 2 de 2. A camada 1 é o build LAYERED oficial do frappe_docker, que compila os
# ASSETS de frappe/erpnext/crm/whitelabel (ver build.sh). Esta camada só acrescenta os
# apps PONOS, que são python-only (sem package.json ⇒ sem assets a compilar).
#
# ── Por que NÃO `docker commit` do spike ────────────────────────────────────────────
# O T0 provou que erpnext 15.40 roda sobre frappe 15.115, mas o instalou via
# `pip install -e` SEM assets (o `bench get-app` morre por falta de `yarn` na imagem de
# produção). Resultado medido: `sites/assets/` do spike tem `crm` mas NÃO tem `erpnext`
# ⇒ o Desk do ERPNext ficaria sem JS/CSS. Cada bench vivo hoje só tem os assets do
# próprio app (frappe-same-site: `crm` e `erpnext`). A imagem única precisa dos
# DOIS ⇒ o build TEM de passar pelo layered oficial (que tem node/yarn).
#
# ── Gotchas provados no T0 (não regredir) ───────────────────────────────────────────
# - `sites/apps.txt` vem SEM newline final ⇒ append ingênuo gruda os nomes
#   ("frappe" + "erpnext" = "frappeerpnext"). Sempre reescrever com \n explícito.
# - o python do bench é o do VENV (`env/bin/pip`), não `/usr/local/bin/python`.
# - `install-app` exige o app JÁ em `apps.txt`.

ARG LAYERED_IMAGE
ARG NODE_IMAGE=node:22-bookworm-slim@sha256:83f487e0a63425e5b4d146fb5e5be574bcbe1b7b843d3ebafdd95eaf7767a7e5
FROM ${NODE_IMAGE} AS node-tools

# Recompile only the CRM UI, reusing the installed dependencies of the pinned
# layered image. No dependency upgrade or complete upstream rebuild is required.
FROM ${LAYERED_IMAGE} AS crm-ui
USER root
COPY --from=node-tools /usr/local/bin/node /usr/local/bin/node
COPY --from=node-tools /opt/yarn-v1.22.22 /opt/yarn-v1.22.22
RUN ln -s /opt/yarn-v1.22.22/bin/yarn /usr/local/bin/yarn
COPY --chown=frappe:frappe deploy/unified/apply-crm-ui.py /tmp/ponos-crm-ui/apply-crm-ui.py
COPY --chown=frappe:frappe deploy/unified/crm-ui /tmp/ponos-crm-ui/crm-ui
COPY --chown=frappe:frappe deploy/unified/tests/ui /home/frappe/frappe-bench/apps/crm/frontend/ponos-tests/ui
USER frappe
WORKDIR /home/frappe/frappe-bench
RUN env/bin/python /tmp/ponos-crm-ui/apply-crm-ui.py apps/crm \
 && yarn --cwd apps/crm/frontend test:run --config ponos-tests/ui/vitest.config.mjs \
 && yarn --cwd apps/crm/frontend build

FROM ${LAYERED_IMAGE} AS runtime

USER root

# Os apps ponos são consumidos do repo (fonte de verdade: deploy/crm/ponos_crm e
# deploy/erp/ponos_erp). ⚠️ deploy/erp/ponos_erp é território da 108.5.x — aqui ele é
# apenas CONSUMIDO, nunca modificado.
COPY --chown=frappe:frappe deploy/crm/ponos_crm /home/frappe/frappe-bench/apps/ponos_crm
COPY --chown=frappe:frappe deploy/erp/ponos_erp /home/frappe/frappe-bench/apps/ponos_erp
# Ponos Análises (Frappe Insights): o `insights` vem do layered (tem assets Vue); o
# `ponos_insights` é python-only (SSO + fonte Site DB), como o ponos_erp.
COPY --chown=frappe:frappe deploy/analises/ponos_insights /home/frappe/frappe-bench/apps/ponos_insights
COPY --chown=frappe:frappe deploy/frappe/ponos_offers /home/frappe/frappe-bench/apps/ponos_offers
COPY --from=crm-ui --chown=frappe:frappe /home/frappe/frappe-bench/apps/crm/frontend/src /home/frappe/frappe-bench/apps/crm/frontend/src
COPY --from=crm-ui --chown=frappe:frappe /home/frappe/frappe-bench/apps/crm/frontend/auto-imports.d.ts /home/frappe/frappe-bench/apps/crm/frontend/auto-imports.d.ts
COPY --from=crm-ui --chown=frappe:frappe /home/frappe/frappe-bench/apps/crm/frontend/components.d.ts /home/frappe/frappe-bench/apps/crm/frontend/components.d.ts
COPY --from=crm-ui --chown=frappe:frappe /home/frappe/frappe-bench/apps/crm/crm/public/frontend /home/frappe/frappe-bench/apps/crm/crm/public/frontend
COPY --from=crm-ui --chown=frappe:frappe /home/frappe/frappe-bench/apps/crm/crm/www/crm.html /home/frappe/frappe-bench/apps/crm/crm/www/crm.html

USER frappe
WORKDIR /home/frappe/frappe-bench

# ── whitelabel: aqui, e NÃO no apps.json do layered ──────────────────────────────────
# O `bench init` do layered instala os apps com **uv**, e o `whitelabel` declara
# `frappe>=15.0,<16.dev0` no seu pyproject. Isso faz o uv tentar RESOLVER o frappe do
# PyPI, e o frappe puxa `pypika` como **URL dependency** (git+https://.../pypika@...),
# que o uv rejeita:
#     × Failed to resolve dependencies for `frappe` (v15.115.0)
#     ╰─▶ Package `pypika` was included as a URL dependency.
# (erpnext e crm não declaram frappe ⇒ passam batido.)
# Como o whitelabel é **python-only e sem assets** (o frappe-same-site VIVO não tem
# `assets/whitelabel`), ele não precisa do layered: entra aqui com **--no-deps**, que
# pula a resolução do frappe (que já está instalado no bench).
RUN git clone --filter=blob:none --no-checkout \
      https://github.com/bhavesh95863/whitelabel apps/whitelabel \
 && git -C apps/whitelabel fetch --depth 1 origin 7b25341ad1e82609007d1428651ea47d6fa60388 \
 && git -C apps/whitelabel checkout --detach 7b25341ad1e82609007d1428651ea47d6fa60388 \
 && env/bin/pip install --no-cache-dir --no-deps -e apps/whitelabel

RUN env/bin/pip install --no-cache-dir -e apps/ponos_offers \
 && env/bin/pip install --no-cache-dir -e apps/ponos_crm \
 && env/bin/pip install --no-cache-dir -e apps/ponos_erp \
 && env/bin/pip install --no-cache-dir -e apps/ponos_insights \
 && env/bin/python -c "import ponos_offers, ponos_crm, ponos_erp, ponos_insights, whitelabel; print('ponos + whitelabel OK')"

# 108.5.7: o ponos_erp passou a ter assets públicos (css do wordmark + imgs). O pip
# install NÃO cria o link em `assets/` (só o `bench build` faz, e ele não roda aqui) —
# sem o link, `/assets/ponos_erp/*` dá 404 e o CSS do `.app-logo` (wordmark) não carrega.
# `sites/assets` é symlink pro `assets/` IMAGE-LOCAL de cada container ⇒ o link tem de
# nascer NA IMAGEM (criar à mão num container vivo morre no próximo recreate).
RUN ln -sfn /home/frappe/frappe-bench/apps/ponos_erp/ponos_erp/public assets/ponos_erp \
 && test -f assets/ponos_erp/css/ponos_erp.css

# apps.txt com newline final EXPLÍCITO (o gotcha acima). A ordem importa: frappe 1º.
RUN printf 'frappe\nerpnext\ncrm\ninsights\nponos_offers\nponos_crm\nponos_erp\nponos_insights\nwhitelabel\n' > sites/apps.txt \
 && cat -A sites/apps.txt

# Gate de sanidade: os assets dos DOIS apps de UI têm de existir na imagem — é
# exatamente o que o `docker commit` do spike não teria.
#
# ⚠️ Os assets NÃO ficam em `sites/assets` na imagem: o layered Containerfile faz
#     cp -r sites/assets -> assets && rm -rf sites/assets
# e o entrypoint os LINKA no volume `sites` na inicialização do container ("This
# entrypoint script link build assets of the image to the mounted sites volume").
# Por isso o gate olha `assets/`, não `sites/assets/` — checar o lugar errado dava
# falso-negativo (e foi o que aconteceu na 1ª tentativa).
RUN test -d assets/erpnext || (echo "FALHA: assets/erpnext ausente — o Desk do ERPNext ficaria sem JS" && exit 1) \
 && test -d assets/crm || (echo "FALHA: assets/crm ausente" && exit 1) \
 && test -d assets/insights || (echo "FALHA: assets/insights ausente — o Ponos Análises ficaria sem UI" && exit 1) \
 && echo "assets OK: erpnext + crm + insights presentes"
