# 不用 `# syntax=docker/dockerfile:1`：该指令会让 BuildKit 去 pull
# docker/dockerfile 前端镜像，在无外网/仅代理的环境里会直接构建失败。
# 本文件未使用任何 BuildKit 专有语法，去掉后走内置前端即可。

# ── Stage 1: Go binaries ──
FROM golang:1.21-bookworm AS gobuild

WORKDIR /src/history
COPY history-server/ .
RUN GOPROXY=https://goproxy.cn,direct CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o /out/history-server .

WORKDIR /src/admin
COPY admin-server/ .
RUN GOPROXY=https://goproxy.cn,direct go mod tidy && CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o /out/admin-server .

# ── Stage 2: SearXNG from source ──
FROM debian:bookworm-slim AS searxng-build

# 需要代理时用 --build-arg 传入（默认不设，保证他人环境可直接构建）
ARG HTTP_PROXY=
ARG HTTPS_PROXY=

ENV DEBIAN_FRONTEND=noninteractive
ENV http_proxy=${HTTP_PROXY}
ENV https_proxy=${HTTPS_PROXY}
ENV HTTP_PROXY=${HTTP_PROXY}
ENV HTTPS_PROXY=${HTTPS_PROXY}

RUN apt-get -o Acquire::Retries=5 -o Acquire::http::Timeout=30 update \
    && apt-get -o Acquire::Retries=5 install -y --no-install-recommends \
    python3 python3-pip python3-venv git ca-certificates \
    && rm -rf /var/lib/apt/lists/*

# 打补丁：上游 duckduckgo_web 引擎抓取首页链接时把 timeout 硬编码成 2 秒
# （searx/engines/duckduckgo_web.py 的 _fetch_first_page_link）。经代理出网时这
# 段握手常需 2~3 秒，于是必然超时 -> 连续失败 -> 引擎被挂起，表现为「秒回 0 条
# 结果」。放宽到 8 秒。上游改动导致下面 test/grep 失配时构建会失败，属预期。
RUN git clone --depth 1 https://github.com/searxng/searxng.git /src/searxng \
    && python3 -m venv /opt/searxng-venv \
    && /opt/searxng-venv/bin/pip install --upgrade pip setuptools wheel msgspec \
    && cd /src/searxng \
    && /opt/searxng-venv/bin/pip install --no-cache-dir -r requirements.txt \
    && /opt/searxng-venv/bin/pip install --no-cache-dir --no-build-isolation . \
    && DDG_WEB=/opt/searxng-venv/lib/python3.11/site-packages/searx/engines/duckduckgo_web.py \
    && test "$(grep -c '^        timeout=2,$' $DDG_WEB)" = "1" \
    && sed -i 's/^        timeout=2,$/        timeout=8,/' $DDG_WEB \
    && grep -q '^        timeout=8,$' $DDG_WEB \
    && rm -rf /src/searxng

# ── Stage 3: browser extension packages ──
# 供 /extension/install.html 下载（Chromium 用 zip，Firefox 用 xpi）
FROM debian:bookworm-slim AS extpack

RUN apt-get -o Acquire::Retries=5 -o Acquire::http::Timeout=30 update \
    && apt-get -o Acquire::Retries=5 install -y --no-install-recommends zip ca-certificates \
    && rm -rf /var/lib/apt/lists/*

COPY extension/chrome /src/chrome
COPY extension/firefox /src/firefox
# Go 的 -o 会自动建父目录，zip 不会，所以这里必须显式创建 /out
RUN mkdir -p /out \
    && cd /src/chrome && zip -qr /out/navi-chrome.zip . \
    && cd /src/firefox && zip -qr /out/navi-firefox.xpi .

# ── Stage 3b: bundled acme.sh (for cert-agent) ──
# 为什么要内置：cert-agent 若在运行时安装 acme.sh，installer 会从
# raw.githubusercontent.com 拉源码，而该域名在境内直连超时
# （实测直连 8.2s 失败 / 经代理 0.53s 成功），导致首次启动静默失败。
# 内置一份让 cert-agent 彻底不依赖运行时下载。
FROM debian:bookworm-slim AS acmebuild

RUN apt-get -o Acquire::Retries=5 install -y --no-install-recommends \
    git ca-certificates curl openssl \
    && rm -rf /var/lib/apt/lists/*

RUN git clone --depth 1 https://github.com/acmesh-official/acme.sh /src/acme.sh \
    && chmod +x /src/acme.sh/acme.sh \
    && rm -rf /src/acme.sh/.git

# ── Stage 4: Runtime ──
FROM debian:bookworm-slim

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get -o Acquire::Retries=5 -o Acquire::http::Timeout=30 update \
    && apt-get -o Acquire::Retries=5 install -y --no-install-recommends \
    nginx python3 supervisor curl ca-certificates git \
    && rm -rf /var/lib/apt/lists/*

# Copy SearXNG venv + source
COPY --from=searxng-build /opt/searxng-venv /app/searxng-venv
COPY --from=searxng-build /usr/lib/python3.11 /usr/lib/python3.11
COPY --from=searxng-build /lib/x86_64-linux-gnu /lib/x86_64-linux-gnu
COPY --from=searxng-build /usr/lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu

# Dashy static files
COPY --from=lissy93/dashy:latest /app/dist /app/dashy

# Go binaries
COPY --from=gobuild /out/history-server /usr/local/bin/history-server
COPY --from=gobuild /out/admin-server /usr/local/bin/admin-server

# Config files
COPY nginx.conf /etc/nginx/nginx.conf
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
COPY searxng-settings.yml /etc/searxng/settings.yml
COPY conf.example.yml /app/defaults/conf.yml
COPY admin/index.html /app/admin/index.html
COPY portal /app/portal
# 站点图标：纸飞机。覆盖 Dashy 自带的 web-icons/favicon-*.png，
# 这样即使将来上游 index.html 变了、patch 失效，标签栏仍是我们的图标。
COPY portal/favicon.svg /app/dashy/favicon.svg
COPY portal/favicon.ico /app/dashy/favicon.ico
COPY portal/apple-touch-icon.png /app/dashy/apple-touch-icon.png
COPY portal/web-icons/ /app/dashy/web-icons/
# 见 zd-host.sh 同名注释：Dashy 前端 JS 运行时会把 icon link 改成
# /icons/favicon.ico，而镜像里没有 /icons/ 目录，静态改 index.html 无效。
COPY portal/favicon.ico /app/dashy/icons/favicon.ico
COPY portal/favicon.svg /app/dashy/icons/favicon.svg

# 浏览器扩展安装页与安装包（通过 /extension/ 访问）
COPY web/extension/install.html /app/dashy/extension/install.html
COPY --from=extpack /out/navi-chrome.zip /app/dashy/extension/navi-chrome.zip
COPY --from=extpack /out/navi-firefox.xpi /app/dashy/extension/navi-firefox.xpi

# 容器内自动续签（cert-agent）。脚本本身不含任何凭据，凭据只从环境变量读。
COPY deploy/cert-agent.sh /usr/local/bin/cert-agent
RUN chmod +x /usr/local/bin/cert-agent
# 内置 acme.sh：cert-agent 优先用它，避免运行时从 raw.githubusercontent.com
# 下载失败（该域名境内直连超时）。
COPY --from=acmebuild /src/acme.sh /usr/local/share/acme.sh

# Inject search script into Dashy
COPY web/navi.js /app/dashy/navi.js
COPY web/navi.css /app/dashy/navi.css
COPY web/patch-index.py /tmp/patch-index.py
# index.html 里不一定有 </body>，用脚本幂等注入，不能靠 sed 替换 </body>。
RUN python3 /tmp/patch-index.py /app/dashy/index.html

# Data directory
RUN mkdir -p /app/data/item-icons /app/data/gateway /app/data/certs /app/data/acme /var/log/supervisor /var/cache/searxng /run/nginx

VOLUME ["/app/data"]
EXPOSE 18080 3080 3081 8443
HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \
    CMD curl -fs http://localhost:18080/healthz || exit 1
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
