---
# Post-provisioning customizations for OpenClaw VMs
# Run after playbooks/install.yml to apply host-specific tweaks
#
# Usage:
#   ansible-playbook -i inventory.yml playbooks/customize.yml
#   ansible-playbook -i inventory.yml playbooks/customize.yml --limit zap
#
# Per-host variables (set in host_vars/<name>.yml):
#   brew_packages: []   # list of Homebrew packages to install

- name: OpenClaw VM customizations
  hosts: openclaw_servers
  become: true

  tasks:

    - name: Set vm.swappiness=5 (live)
      ansible.posix.sysctl:
        name: vm.swappiness
        value: "5"
        state: present
        reload: true

    - name: Persist vm.swappiness in /etc/sysctl.conf
      ansible.builtin.lineinfile:
        path: /etc/sysctl.conf
        regexp: '^vm\.swappiness'
        line: 'vm.swappiness=5'
        state: present

    # ── virtiofs shares ─────────────────────────────────────────────────────
    # Host: ~/lab/swarm          → Guest: /mnt/swarm
    # Host: ~/lab/swarm/swarm-common → Guest: /mnt/swarm-common
    # Mounted directly via virtiofs (no bindfs layer).
    # Host dirs have o+w so openclaw (UID 999) can write.

    - name: Create swarm virtiofs mount point
      ansible.builtin.file:
        path: /mnt/swarm
        state: directory
        mode: "0755"

    - name: Create swarm-common virtiofs mount point
      ansible.builtin.file:
        path: /mnt/swarm-common
        state: directory
        mode: "0755"

    - name: Add swarm virtiofs entry to fstab
      ansible.posix.mount:
        path: /mnt/swarm
        src: swarm
        fstype: virtiofs
        opts: defaults
        state: present

    - name: Add swarm-common virtiofs entry to fstab
      ansible.posix.mount:
        path: /mnt/swarm-common
        src: swarm-common
        fstype: virtiofs
        opts: defaults
        state: present

    - name: Ensure swarm share root is world-writable (for openclaw UID 999)
      ansible.builtin.file:
        path: /mnt/swarm
        mode: "0777"
        state: directory

    - name: Ensure swarm-common share root is world-writable (for openclaw UID 999)
      ansible.builtin.file:
        path: /mnt/swarm-common
        mode: "0777"
        state: directory

    - name: Ensure openclaw user lingering is enabled (for user systemd services)
      ansible.builtin.command:
        cmd: loginctl enable-linger openclaw
      changed_when: false

    # ── Homebrew ───────────────────────────────────────────────────────────

    - name: Install Homebrew dependencies
      ansible.builtin.apt:
        name:
          - build-essential
          - procps
          - curl
          - file
          - git
        state: present

    - name: Pre-create /home/linuxbrew owned by openclaw
      ansible.builtin.file:
        path: /home/linuxbrew
        state: directory
        owner: openclaw
        group: openclaw
        mode: "0755"

    - name: Install Homebrew (as openclaw user)
      ansible.builtin.shell: |
        NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
      become_user: openclaw
      args:
        creates: /home/linuxbrew/.linuxbrew/bin/brew

    - name: Add Homebrew to openclaw user PATH
      ansible.builtin.blockinfile:
        path: /home/openclaw/.bashrc
        marker: "# {mark} HOMEBREW"
        block: |
          eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
        owner: openclaw
        group: openclaw
        create: true

    - name: Install Homebrew packages
      ansible.builtin.shell: |
        brew list {{ item }} 2>/dev/null || brew install {{ item }}
      become_user: openclaw
      environment:
        HOME: /home/openclaw
        PATH: /home/linuxbrew/.linuxbrew/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
      loop: "{{ brew_packages | default([]) }}"
      register: brew_install
      changed_when: "'Installing' in brew_install.stdout"

    # ── Automatic security updates ─────────────────────────────────────────
    # The upstream role installs unattended-upgrades with security-only updates.
    # We extend it here to enable automatic reboots for kernel/libc updates,
    # scheduled at 04:00 — after the 03:00 backup and the Sunday 03:10 e2scrub.

    - name: Ensure unattended-upgrades is installed
      ansible.builtin.apt:
        name:
          - unattended-upgrades
          - apt-listchanges
        state: present

    - name: Configure unattended-upgrades
      ansible.builtin.copy:
        dest: /etc/apt/apt.conf.d/50unattended-upgrades
        mode: "0644"
        content: |
          // OpenClaw VM — automatic security updates
          Unattended-Upgrade::Allowed-Origins {
              "${distro_id}:${distro_codename}-security";
              "${distro_id}ESMApps:${distro_codename}-apps-security";
              "${distro_id}ESM:${distro_codename}-infra-security";
          };
          Unattended-Upgrade::Package-Blacklist {};
          Unattended-Upgrade::AutoFixInterruptedDpkg "true";
          Unattended-Upgrade::MinimalSteps "true";
          Unattended-Upgrade::Remove-Unused-Dependencies "true";
          Unattended-Upgrade::Remove-New-Unused-Dependencies "true";
          Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
          // Reboot at 04:00 if required (after 03:00 backup + Sunday 03:10 e2scrub)
          Unattended-Upgrade::Automatic-Reboot "true";
          Unattended-Upgrade::Automatic-Reboot-Time "04:00";
      notify: Restart unattended-upgrades

    - name: Enable daily apt update and upgrade triggers
      ansible.builtin.copy:
        dest: /etc/apt/apt.conf.d/20auto-upgrades
        mode: "0644"
        content: |
          APT::Periodic::Update-Package-Lists "1";
          APT::Periodic::Unattended-Upgrade "1";
          APT::Periodic::AutocleanInterval "7";

    - name: Ensure unattended-upgrades service is running and enabled
      ansible.builtin.systemd:
        name: unattended-upgrades
        state: started
        enabled: true

    # ── Agentmon telemetry hook ──────────────────────────────────────────────
    # Deploys the agentmon hook to OpenClaw's hooks directory so agent
    # activity (sessions, runs, tool calls, errors) is streamed to the
    # agentmon ingest gateway for monitoring.

    - name: Create agentmon hook directory
      ansible.builtin.file:
        path: "{{ openclaw_home }}/.openclaw/hooks/agentmon"
        state: directory
        owner: "{{ openclaw_user }}"
        group: "{{ openclaw_user }}"
        mode: "0755"

    - name: Deploy agentmon hook files
      ansible.builtin.copy:
        src: "files/agentmon-hook/{{ item }}"
        dest: "{{ openclaw_home }}/.openclaw/hooks/agentmon/{{ item }}"
        owner: "{{ openclaw_user }}"
        group: "{{ openclaw_user }}"
        mode: "0644"
      loop:
        - HOOK.md
        - handler.ts

    - name: Set AGENTMON_INGEST_URL in OpenClaw env
      ansible.builtin.lineinfile:
        path: "{{ openclaw_home }}/.openclaw/.env"
        regexp: '^AGENTMON_INGEST_URL='
        line: "AGENTMON_INGEST_URL={{ agentmon_ingest_url }}"
        create: true
        owner: "{{ openclaw_user }}"
        group: "{{ openclaw_user }}"
        mode: "0600"

    - name: Set AGENTMON_VM_NAME in OpenClaw env
      ansible.builtin.lineinfile:
        path: "{{ openclaw_home }}/.openclaw/.env"
        regexp: '^AGENTMON_VM_NAME='
        line: "AGENTMON_VM_NAME={{ inventory_hostname }}"
        create: true
        owner: "{{ openclaw_user }}"
        group: "{{ openclaw_user }}"
        mode: "0600"

  handlers:
    - name: Restart unattended-upgrades
      ansible.builtin.systemd:
        name: unattended-upgrades
        state: restarted
