#!/usr/bin/env bash
set -Eeuo pipefail

export DEBIAN_FRONTEND=noninteractive
BASE="/opt/dailoios/canon-lbp2900"
STATE="/var/lib/dailoios-canon-lbp2900"
LOG="/var/log/dailoios-canon-lbp2900.log"

mkdir -p "$STATE"
exec >>"$LOG" 2>&1
echo
echo "===== $(date -Is) Canon LBP2900 One-Click ====="

# Chờ trình cài đồ họa/dpkg chính nhả khóa hoàn toàn.
for i in $(seq 1 90); do
  if ! fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1 &&
     ! fuser /var/lib/dpkg/lock >/dev/null 2>&1; then
    break
  fi
  sleep 2
done

dpkg --add-architecture i386 || true

shopt -s nullglob
DEBS=("$BASE"/debs/*.deb)
if (( ${#DEBS[@]} == 0 )); then
  echo "LỖI: Không có payload .deb."
  exit 1
fi

# Tuyệt đối không hỏi người dùng về file cấu hình.
DPKG_OPTS=(
  --force-confnew
  --force-confdef
  --force-overwrite
)

# Cài nhiều lượt để tự giải quyết thứ tự phụ thuộc trong bộ offline.
for pass in 1 2 3 4; do
  echo "Lượt cài offline $pass..."
  dpkg "${DPKG_OPTS[@]}" -i "${DEBS[@]}" || true
  dpkg "${DPKG_OPTS[@]}" --configure -a || true
done

# Khôi phục PPD/model.
if [[ -d "$BASE/backup/model" ]]; then
  mkdir -p /usr/share/cups/model
  cp -a "$BASE/backup/model/." /usr/share/cups/model/ || true
fi
if [[ -d "$BASE/backup/ppd" ]]; then
  mkdir -p /usr/share/ppd
  cp -a "$BASE/backup/ppd/." /usr/share/ppd/ || true
fi
if [[ -d "$BASE/backup/etc-cups-ppd" ]]; then
  mkdir -p /etc/cups/ppd
  cp -a "$BASE/backup/etc-cups-ppd/." /etc/cups/ppd/ || true
  chmod 755 /etc/cups/ppd
  chmod 640 /etc/cups/ppd/*.ppd 2>/dev/null || true
fi

# Dịch vụ Canon CAPT.
cat > /etc/systemd/system/ccpd.service <<'SERVICE'
[Unit]
Description=Canon CAPT Daemon
Requires=cups.service
After=cups.service

[Service]
Type=forking
ExecStart=/usr/sbin/ccpd
ExecStop=/usr/bin/killall ccpd
Restart=on-failure
RestartSec=3

[Install]
WantedBy=multi-user.target
SERVICE

systemctl daemon-reload
systemctl enable --now cups.service
systemctl enable ccpd.service

# Xóa hàng đợi lỗi/cũ rồi tạo lại hoàn toàn tự động.
lpadmin -x LBP2900 2>/dev/null || true
ccpdadmin -x LBP2900 2>/dev/null || true

PPD=""
while IFS= read -r f; do
  PPD="$f"
  break
done < <(find /usr/share/cups/model /usr/share/ppd \
  -type f \( -iname '*LBP2900*.ppd' -o -iname '*LBP2900*.ppd.gz' \
  -o -iname '*2900*CAPT*.ppd' -o -iname '*2900*CAPT*.ppd.gz' \) \
  2>/dev/null)

if [[ -z "$PPD" ]]; then
  echo "LỖI: Không tìm thấy PPD Canon LBP2900."
  exit 1
fi

echo "PPD: $PPD"
lpadmin -p LBP2900 -E -v ccp://localhost:59687 -P "$PPD"
lpadmin -d LBP2900 || true

# Canon có thể xuất hiện ở /dev/usb/lp0 hoặc symlink /dev/canonLBP2900.
DEVICE="/dev/usb/lp0"
[[ -e /dev/canonLBP2900 ]] && DEVICE="/dev/canonLBP2900"

ccpdadmin -p LBP2900 -o "$DEVICE"

systemctl restart cups.service
systemctl restart ccpd.service || true

# Tạo udev rule để tự sửa cổng khi cắm máy in Canon.
cat > /etc/udev/rules.d/99-dailoios-canon-lbp2900.rules <<'UDEV'
SUBSYSTEM=="usb", ATTR{idVendor}=="04a9", MODE="0666", GROUP="lp"
KERNEL=="lp[0-9]*", SUBSYSTEM=="usb", MODE="0666", GROUP="lp", SYMLINK+="canonLBP2900"
UDEV
udevadm control --reload-rules || true
udevadm trigger || true

touch "$STATE/installed"
echo "Hoàn tất cài Canon LBP2900."
echo "===== $(date -Is) DONE ====="
