---
- name: Capture all logical volume paritions on /boot device
  ansible.builtin.shell:
    cmd: |
      set -o pipefail
      lsblk -pl -o name,type {{ bigboot_boot_mount['device'][:-1] }} | grep -i lvm
    executable: /bin/bash
  changed_when: false
  failed_when: bigboot_adjacent_lvm['rc'] not in [0, 141]
  register: bigboot_adjacent_lvm

- name: Map the device to its mount point if applicable
  ansible.builtin.set_fact:
    bigboot_adjacent_lvm_devices: "{{ bigboot_adjacent_lvm_devices | default([]) \
      | combine({item | split(' ') | first: ansible_facts['mounts'] \
      | selectattr('device', 'equalto', item | split(' ') | first) \
      | map(attribute='mount')}) }}"
  loop: "{{ bigboot_adjacent_lvm['stdout_lines'] }}"

- name: Capture the device name of the mounted logical volumes
  ansible.builtin.set_fact:
    bigboot_lvm_mounts: "{{ bigboot_lvm_mounts | default([]) + [item['key']] }}"
  loop: "{{ bigboot_adjacent_lvm_devices | dict2items }}"
  when: item['value'] | regex_search('[/a-zA-Z]')

- name: Debug bigboot_lvm_mounts
  ansible.builtin.debug:
    var: bigboot_lvm_mounts
    verbosity: 1

- name: Set adjacent LVM device name
  ansible.builtin.set_fact:
    bigboot_adjacent_lvm_device: "{{ bigboot_lvm_mounts | first }}"

- name: Debug bigboot_adjacent_lvm_device
  ansible.builtin.debug:
    var: bigboot_adjacent_lvm_device
    verbosity: 1

- name: Get logical volume mount information
  ansible.builtin.set_fact:
    bigboot_lv_info: "{{ ansible_facts.mounts \
      | selectattr('device', 'equalto', bigboot_adjacent_lvm_device) | first }}"

# - name: Assert that there is space on the logical volume for shrinkage
#   ansible.builtin.assert:
#     that: bigboot_lv_info.size_available > bigboot_expansion_diff | int
#     fail_msg: There is not enough space available for LV shrinking.

- name: Capture UUID for target volume
  ansible.builtin.set_fact:
    bigboot_lv_uuid: "{{ ansible_facts['mounts'] | selectattr('device', 'equalto', bigboot_adjacent_lvm_device) | map(attribute='uuid') | first }}"

- name: Capture block device information for target logical volume
  ansible.builtin.set_fact:
    bigboot_lv_dm: "{{ ansible_device_links['uuids'] | dict2items | selectattr('value', 'contains', bigboot_lv_uuid) | map(attribute='key') | first }}"

- name: Set initial sizes for logical volume and fallback size target
  ansible.builtin.set_fact:
    bigboot_lv_partsize: "{{ ansible_devices[bigboot_lv_dm]['sectors'] | int * ansible_devices[bigboot_lv_dm]['sectorsize'] | int }}"
    bigboot_size_target_fallback: "{{ bigboot_size_target | human_to_bytes }}"

- name: Check available space and fallback to lower /boot size if required
  ansible.builtin.include_tasks: check_space_fallback.yml

- name: Capture shrink and fallback sizes
  ansible.builtin.set_fact:
    # we need to get the BLOCK size total, not the filesystem
    bigboot_lv_shrink_size: "{{ (bigboot_lv_partsize | int - bigboot_expansion_diff | int) | get_block_size_down_bytes }}"
    bigboot_size_target_fallback: "{{ bigboot_size_target_fallback | int | human_readable(unit='G') | regex_replace('\\sGB', 'G') }}"

- name: Debug bigboot_lv_shrink_size and bigboot_size_target_fallback
  ansible.builtin.debug:
    msg: "{{ bigboot_lv_shrink_size | int | human_readable(unit='G') }} ({{ bigboot_lv_shrink_size | int | human_readable(unit='M') | regex_replace('\\.\\d+\\s+MB') | int | get_block_size_down }}) <-> {{ bigboot_size_target_fallback }} | {{ bigboot_expansion_diff }}"

# - name: Kill the play
#   ansible.builtin.meta: end_host

- name: Capture logical volume name
  ansible.builtin.shell:
    cmd: |
      set -o pipefail
      lvdisplay {{ bigboot_adjacent_lvm_device }} | grep -i 'vg name'
    executable: /bin/bash
  changed_when: false
  register: bigboot_lv_vg_name

- name: Format logical volume name
  ansible.builtin.set_fact:
    bigboot_lv_vg_name: "{{ bigboot_lv_vg_name['stdout'] | regex_replace('VG\\s+Name\\s+(.*)$', '\\1') }}"

- name: Capture volume group free PE
  ansible.builtin.shell:
    cmd: |
      set -o pipefail
      vgdisplay {{ bigboot_lv_vg_name | trim }} | grep -i 'free'
    executable: /bin/bash
  changed_when: false
  register: bigboot_lv_vg_free_pe

- name: Capture the PV device
  ansible.builtin.set_fact:
    bigboot_pv: "{{ bigboot_boot_mount['device'][:-1] }}{{ bigboot_boot_mount['device'][-1:] | int + 1 }}"

- name: Format logical volume free PE
  ansible.builtin.set_fact:
    # Ex:
    #   Free  PE / Size       320 / 1.25 GiB"
    #   Free  PE / Size       189 / 756.00 MiB"
    #   Free  PE / Size       414 / <1.62 GiB
    #   Free  PE / Size       0 / 0
    bigboot_lv_vg_free_pe: "{{ bigboot_lv_vg_free_pe['stdout'] | regex_replace('^.*/.*/\\s+[<]?(.*)', '\\1') }}"

- name: Get size in MB for available PE
  ansible.builtin.set_fact:
    bigboot_lv_pe_size_in_mb:
      "{{ bigboot_lv_vg_free_pe | regex_replace('i|\\s+|<', '') | human_to_bytes | human_readable(unit='M') }}"

- name: Verify available PE for the volume group
  block:
    - name: Set variables required for shrinking the target LV
      ansible.builtin.set_fact:
        bigboot_execute_shrink_lv: false
        bigboot_expansion_diff_mb: "{{ bigboot_expansion_diff | int | human_readable(unit='M') }}"

    - name: Assert if we need to shrink the logical volume to gain PE
      ansible.builtin.assert:
        that: (bigboot_lv_pe_size_in_mb[:-3] | int) >= (bigboot_expansion_diff_mb[:-3] | int)
        fail_msg: Not enough PE to expand /boot. Will need to shrink target LV.

  rescue:
    - name: Set flag for Shrink_LV execution
      ansible.builtin.set_fact:
        bigboot_execute_shrink_lv: true
      when:
        - bigboot_execute_bigboot | bool
        - bigboot_expansion_diff | int > 0

