# Copyright 2025 Chris Croome
#
# This file is part of the Webarchitects Valkey Ansible role.
#
# The Webarchitects Valkey Ansible role is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
#
# The Webarchitects Valkey Ansible role is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with the Webarchitects Valkey Ansible role. If not, see <https://www.gnu.org/licenses/>.
---
- name: Valkey packages present and absent
  block:

    - name: Update package facts
      ansible.builtin.package_facts:
        manager: apt

    - name: Set a fact for the packages present
      ansible.builtin.set_fact:
        valkey_pkgs_installed: "{{ ansible_facts.packages.keys() }}"

    - name: Gather distribution facts
      ansible.builtin.setup:
        gather_subset:
          - distribution
      when: ansible_facts.distribution_release is not defined

    - name: Distro packages need to be specified
      ansible.builtin.assert:
        that:
          - ansible_facts.distribution_release in (valkey_pkgs | community.general.json_query('[].name'))
        quiet: "{% if ansible_verbosity == 0 %}true{% else %}false{% endif %}"
        fail_msg: >-
          The distro {{ ansible_facts.distribution_release }} needs to be listed in the valkey_pkgs array, currently the array contains
          {{ (valkey_pkgs | community.general.json_query('[].name')) | join(', ') }}

    - name: Update apt cache
      ansible.builtin.apt:
        update_cache: true
      check_mode: false
      changed_when: false

    - name: Run apt-cache policy
      ansible.builtin.command: apt-cache policy
      check_mode: false
      changed_when: false
      register: valkey_apt_cache_policy

    - name: Debug packages absent JMESPath query
      ansible.builtin.debug:
        var: valkey_jpq.pkgs_absent
        verbosity: "{% if ansible_check_mode | bool or ansible_diff_mode | bool %}1{% else %}2{% endif %}"

    - name: Debug packages absent
      ansible.builtin.debug:
        var: valkey_pkgs | community.general.json_query(valkey_jpq.pkgs_absent)
        verbosity: "{% if ansible_check_mode | bool or ansible_diff_mode | bool %}0{% else %}1{% endif %}"

    - name: Debug backports packages present JMESPath query
      ansible.builtin.debug:
        var: valkey_jpq.pkgs_present_backports
        verbosity: "{% if ansible_check_mode | bool or ansible_diff_mode | bool %}1{% else %}2{% endif %}"

    - name: Debug backports packages present
      ansible.builtin.debug:
        var: valkey_pkgs | community.general.json_query(valkey_jpq.pkgs_present_backports)
        verbosity: "{% if ansible_check_mode | bool or ansible_diff_mode | bool %}0{% else %}1{% endif %}"

    - name: Debug valkey_pkgs
      ansible.builtin.debug:
        var: valkey_pkgs
        verbosity: "{% if ansible_check_mode | bool or ansible_diff_mode | bool %}1{% else %}2{% endif %}"

    - name: Debug packages present JMESPath query
      ansible.builtin.debug:
        var: valkey_jpq.pkgs_present
        verbosity: "{% if ansible_check_mode | bool or ansible_diff_mode | bool %}1{% else %}2{% endif %}"

    - name: Debug packages present
      ansible.builtin.debug:
        var: valkey_pkgs | community.general.json_query(valkey_jpq.pkgs_present)
        verbosity: "{% if ansible_check_mode | bool or ansible_diff_mode | bool %}0{% else %}1{% endif %}"

    - name: Check that lists of packages present and absent are defined
      ansible.builtin.assert:
        that:
          - (valkey_pkgs | community.general.json_query(valkey_jpq.pkgs_absent)) | type_debug == "list"
          - (valkey_pkgs | community.general.json_query(valkey_jpq.pkgs_present)) | type_debug == "list"
        quiet: "{% if ansible_check_mode or ansible_verbosity >= 1 %}false{% else %}true{% endif %}"

    - name: Backports checks
      block:

        - name: Check that backport packages present is a list when defined
          ansible.builtin.assert:
            that:
              - (valkey_pkgs | community.general.json_query(valkey_jpq.pkgs_present_backports)) | type_debug == "list"
            quiet: "{% if ansible_check_mode or ansible_verbosity >= 1 %}false{% else %}true{% endif %}"

        - name: Check that backports are available when backports packages are specified
          ansible.builtin.assert:
            that:
              - valkey_apt_backports in valkey_apt_cache_policy.stdout
            quiet: "{% if ansible_check_mode or ansible_verbosity >= 1 %}false{% else %}true{% endif %}"
          when: valkey_pkgs | community.general.json_query(valkey_jpq.pkgs_present_backports) != []

      when: valkey_pkgs | community.general.json_query(valkey_jpq.pkgs_present_backports) is defined

    - name: Valkey packages absent
      ansible.builtin.apt:
        pkg: "{{ valkey_pkgs | community.general.json_query(valkey_jpq.pkgs_absent) }}"
        state: absent
        update_cache: true
        cache_valid_time: 60
      register: valkey_apt_removed
      when: valkey_pkgs | community.general.json_query(valkey_jpq.pkgs_absent) != []

    - name: Valkey backports packages present
      ansible.builtin.apt:
        pkg: "{{ valkey_pkgs | community.general.json_query(valkey_jpq.pkgs_present_backports) }}"
        default_release: "{{ ansible_facts.distribution_release }}-backports"
        state: present
        update_cache: true
        cache_valid_time: 60
      register: valkey_apt_installed_backports
      when:
        - valkey_pkgs | community.general.json_query(valkey_jpq.pkgs_present_backports) is defined
        - valkey_pkgs | community.general.json_query(valkey_jpq.pkgs_present_backports) != []

    - name: Valkey packages present
      ansible.builtin.apt:
        pkg: "{{ valkey_pkgs | community.general.json_query(valkey_jpq.pkgs_present) }}"
        state: present
        update_cache: true
        cache_valid_time: 60
      register: valkey_apt_installed
      when: valkey_pkgs | community.general.json_query(valkey_jpq.pkgs_present) != []

    - name: Installed packages variable updated
      block:

        - name: Update package fact when packages have been installed or removed
          ansible.builtin.package_facts:
            manager: apt

        - name: Set a fact for the packages present
          ansible.builtin.set_fact:
            valkey_pkgs_installed: "{{ ansible_facts.packages.keys() }}"

        - name: Debug valkey_pkgs_installed
          ansible.builtin.debug:
            var: valkey_pkgs_installed
            verbosity: "{% if ansible_check_mode | bool or ansible_diff_mode | bool %}1{% else %}2{% endif %}"

      when: >-
        ( ( valkey_apt_installed_backports is defined ) and ( valkey_apt_installed_backports.changed | bool ) ) or
        ( ( valkey_apt_installed is defined ) and ( valkey_apt_installed.changed | bool ) ) or
        ( ( valkey_apt_removed is defined ) and ( valkey_apt_removed.changed | bool ) )

    - name: Valkey service enabled and started
      block:

        - name: Valkey service enabled
          ansible.builtin.systemd_service:
            name: valkey-server
            enabled: true
          notify: Systemd daemon-reload

        - name: Valkey service started
          ansible.builtin.systemd_service:
            name: valkey-server
            state: started

      when:
        - ( "valkey-server" in valkey_pkgs_installed )
        - valkey_enabled | bool

    - name: Valkey service disabled and stopped
      block:

        - name: Valkey service disabled
          ansible.builtin.systemd_service:
            name: valkey-server
            enabled: false
          notify: Systemd daemon-reload

        - name: Valkey service stopped
          ansible.builtin.systemd_service:
            name: valkey-server
            state: stopped

      when:
        - ( "valkey-server" in valkey_pkgs_installed )
        - not valkey_enabled | bool

  tags:
    - valkey
    - valkey_pkg
...