---
- name: Install wireguard packages
  ansible.builtin.apt:
    name:
      - wireguard

- name: Check if wg_server is reachable
  ansible.builtin.command: echo "Test if wg_server is reachable"
  delegate_to: wireguard_server
  register: result
  changed_when: false

- name: Inform that wg_server is unreachable
  ansible.builtin.debug:
    msg: |
      Couldn't access wg_server. Possible reasons
      * server not reachable
      * no matching ssh-key
  changed_when: true
  when: result.unreachable is defined and result.unreachable

- name: Configure WG Server
  when: result.unreachable is not defined or not result.unreachable
  block:
    - name: Set facts wg_clientname
      ansible.builtin.set_fact:
        wg_clientname: "{{ ansible_hostname }}"

    - name: Get Wiregard-Privatekey from server
      ansible.builtin.shell:
        cmd: grep PrivateKey /etc/wireguard/wg0.conf | sed -En 's/.*=\s*(.+)/\1/p'
      register: wg_serverprivkey
      changed_when: false
      delegate_to: wireguard_server

    - name: Create public key (Server)
      ansible.builtin.command:
        cmd: "wg pubkey"
      args:
        stdin: "{{ wg_serverprivkey.stdout }}"
      changed_when: false
      register: wg_serverpubkey

    - name: Set facts wg_publickey (Server)
      ansible.builtin.set_fact:
        wg_serverpublickey: "{{ wg_serverpubkey.stdout }}"

    - name: Check if Wiregard-Config exists on server
      ansible.builtin.command:
        cmd: "grep -A 3 '# BEGIN ANSIBLE MANAGED BLOCK {{ wg_clientname }}' /etc/wireguard/wg0.conf"
      register: wg_serverconfig
      failed_when: false
      changed_when: false
      delegate_to: wireguard_server

    - name: Set facts wg_ip
      ansible.builtin.set_fact:
        wg_ip: "{{ wg_serverconfig.stdout | regex_search('AllowedIPs = ([0-9.]+)/32', '\\1', multiline=True) | first }}"
      when: wg_serverconfig.rc == 0 and wg_ip is not defined

    - name: Check if Wireguard exists on client
      ansible.builtin.stat:
        path: /etc/NetworkManager/system-connections/wg0.nmconnection
      register: wg_clientconfig

    - name: Search IP address in NetworkManager config
      ansible.builtin.command:
        cmd: cat /etc/NetworkManager/system-connections/wg0.nmconnection
      register: wg_address
      changed_when: false
      when: wg_clientconfig.stat.exists

    - name: Set facts wg_ip
      ansible.builtin.set_fact:
        wg_ip: "{{ wg_address.stdout | regex_search('address1=([0-9.]+)/.*', '\\1', multiline=True) | first }}"
      when: wg_address.rc is defined and wg_address.rc == 0 and wg_ip is not defined

    - name: Set facts wg_privatekey
      ansible.builtin.set_fact:
        wg_privatekey: "{{ wg_address.stdout | regex_search('private-key=(.*)$', '\\1', multiline=True) | first }}"
      when: wg_address.rc is defined and wg_address.rc == 0 and wg_privatekey is not defined

    - name: Search maximum AllowedIP
      ansible.builtin.shell:
        cmd: grep AllowedIPs /etc/wireguard/wg0.conf | sed -En 's/.*=\s*([0-9.]+)\/32.*/\1/p' | sort -t . -k 3,3n -k 4,4n | tail -n 1
      register: wg_ipmax
      changed_when: false
      delegate_to: wireguard_server
      when: wg_ip is not defined

    - name: Set facts wg_ip
      ansible.builtin.set_fact:
        wg_ip: "{{ wg_ipmax.stdout | ansible.utils.ipmath(1) }}"
      when: wg_ipmax.rc is defined and wg_ipmax.rc == 0 and wg_ipmax.stdout and wg_ip is not defined

    - name: Create private key
      ansible.builtin.command:
        cmd: "wg genkey"
      register: wg_genkey
      changed_when: false
      when: wg_privatekey is not defined

    - name: Set facts wg_privatekey
      ansible.builtin.set_fact:
        wg_privatekey: "{{ wg_genkey.stdout }}"
      when: wg_genkey.stdout is defined

    - name: Create Wireguard-Config
      ansible.builtin.template:
        src: wg0.nmconnection.j2
        dest: /etc/NetworkManager/system-connections/wg0.nmconnection
        mode: '0600'

    - name: Create public key
      ansible.builtin.command:
        cmd: "wg pubkey"
      args:
        stdin: "{{ wg_privatekey }}"
      register: wg_pubkey
      changed_when: false

    - name: Set facts wg_publickey
      ansible.builtin.set_fact:
        wg_publickey: "{{ wg_pubkey.stdout }}"

    - name: Print WG IP
      ansible.builtin.debug:
        msg: "{{ wg_publickey }} -- {{ wg_pubkey.stdout }}"

    - name: Set Wireguard Serverconfig
      ansible.builtin.blockinfile:
        marker: "# {mark} ANSIBLE MANAGED BLOCK {{ wg_clientname }}"
        path: /etc/wireguard/wg0.conf
        block: |
          [Peer]
          PublicKey = {{ wg_publickey }}
          AllowedIPs = {{ wg_ip }}/32
      delegate_to: wireguard_server