- name: Ensure `ansible_certs` directory exists
  ansible.builtin.file:
    path: /etc/ansible_certs
    state: directory
    owner: root
    group: root
    mode: "755"
  become: true

- name: Ensure `certs` sub-directory exists
  ansible.builtin.file:
    path: /etc/ansible_certs/certs
    state: directory
    owner: root
    group: root
    mode: "755"
  become: true

- name: Ensure sub-directory for the certificate exists
  ansible.builtin.file:
    path: "/etc/ansible_certs/certs/{{ item }}"
    state: directory
    owner: "{{ cert__owner }}"
    group: "{{ cert__group }}"
    mode: "755"
  become: true

- name: Ensure private key for certificate exists
  community.crypto.openssl_privatekey:
    path: "/etc/ansible_certs/certs/{{ item }}/privkey.pem"
    size: 4096
    type: RSA
    owner: "{{ cert__owner }}"
    group: "{{ cert__group }}"
    mode: "{{ cert__privkey_pem_permissions }}"
  become: true

- name: Ensure certificate signing request is created
  community.crypto.openssl_csr:
    path: "/etc/ansible_certs/certs/{{ item }}/csr.pem"
    privatekey_path: "/etc/ansible_certs/certs/{{ item }}/privkey.pem"
    common_name: "{{ item }}"
    owner: "{{ cert__owner }}"
    group: "{{ cert__group }}"
    mode: "0660"
  become: true
  register: cert__csr_result

- name: Ensure private key for ACME account exists
  community.crypto.openssl_privatekey:
    path: "/etc/ansible_certs/account_key.pem"
    size: 4096
    type: RSA
    owner: root
    group: root
    mode: "0600"
  become: true

- name: Check certificate status and create ACME challenge if needed
  community.crypto.acme_certificate:
    account_email: "{{ cert__acme_account_email }}"
    account_key_src: "/etc/ansible_certs/account_key.pem"
    acme_directory: https://acme-v02.api.letsencrypt.org/directory
    acme_version: 2
    remaining_days: 28
    terms_agreed: true
    challenge: dns-01
    csr: "/etc/ansible_certs/certs/{{ item }}/csr.pem"
    dest: "/etc/ansible_certs/certs/{{ item }}/cert.pem"
    fullchain_dest: "/etc/ansible_certs/certs/{{ item }}/fullchain.pem"
  become: true
  register: cert__acme_challenge

- name: Retrieve certificate and fulfill challenge if needed # noqa no-handler
  when: cert__acme_challenge.changed # Can't be put in a handler, because then the block "always" tasks won't be executed for some reason
  block:
    - name: Add file containing nsupdate commands for adding TXT record for DNS-01 challenge
      ansible.builtin.template:
        src: nsupdate_add_txt_record.j2
        dest: /root/nsupdate_add_txt_record
        owner: root
        group: root
        mode: "0600"
      vars:
        cert__nsupdate_domain: "{{ cert__acme_challenge.challenge_data[item]['dns-01'].record }}"
        cert__nsupdate_txt_data: "{{ cert__acme_challenge.challenge_data[item]['dns-01'].resource_value }}"
      become: true
      delegate_to: "{{ cert__bind_9_host }}"

    - name: Add DNS record to BIND 9 server via nsupdate  # noqa: no-changed-when
      ansible.builtin.command: /usr/bin/nsupdate -l /root/nsupdate_add_txt_record
      become: true
      delegate_to: "{{ cert__bind_9_host }}"

    - name: Retrieve certificate
      community.crypto.acme_certificate:
        account_email: "{{ cert__acme_account_email }}"
        account_key_src: "/etc/ansible_certs/account_key.pem"
        acme_directory: https://acme-v02.api.letsencrypt.org/directory
        acme_version: 2
        terms_agreed: true
        remaining_days: 28
        challenge: dns-01
        csr: "/etc/ansible_certs/certs/{{ item }}/csr.pem"
        dest: "/etc/ansible_certs/certs/{{ item }}/cert.pem"
        fullchain_dest: "/etc/ansible_certs/certs/{{ item }}/fullchain.pem"
        data: "{{ cert__acme_challenge }}"
      become: true
      notify: "{{ cert__handlers }}"
  always:
    - name: Remove file containing nsupdate commands for adding TXT record again
      ansible.builtin.file:
        path: /root/nsupdate_add_txt_record
        state: absent
      become: true
      delegate_to: "{{ cert__bind_9_host }}"

    - name: Remove TXT record again
      block:
        - name: Add file containing nsupdate commands for deleting TXT record for DNS-01 challenge
          ansible.builtin.template:
            src: nsupdate_delete_txt_record.j2
            dest: /root/nsupdate_delete_txt_record
            owner: root
            group: root
            mode: "0600"
          vars:
            cert__nsupdate_domain: "{{ cert__acme_challenge.challenge_data[item]['dns-01'].record }}"
            cert__nsupdate_txt_data: "{{ cert__acme_challenge.challenge_data[item]['dns-01'].resource_value }}"
          become: true
          delegate_to: "{{ cert__bind_9_host }}"

        - name: Remove DNS record from BIND 9 server via nsupdate  # noqa: no-changed-when
          ansible.builtin.command: /usr/bin/nsupdate -l /root/nsupdate_delete_txt_record
          become: true
          delegate_to: "{{ cert__bind_9_host }}"
      always:
        - name: Remove file containing nsupdate commands for deleting TXT record again
          ansible.builtin.file:
            path: /root/nsupdate_delete_txt_record
            state: absent
          become: true
          delegate_to: "{{ cert__bind_9_host }}"

- name: Ensure correct permissions for certificate are set
  ansible.builtin.file:
    path: "/etc/ansible_certs/certs/{{ item }}/cert.pem"
    owner: "{{ cert__owner }}"
    group: "{{ cert__group }}"
    mode: "{{ cert__cert_pem_permissions }}"
  become: true

- name: Ensure correct permissions for fullchain cert are set
  ansible.builtin.file:
    path: "/etc/ansible_certs/certs/{{ item }}/fullchain.pem"
    owner: "{{ cert__owner }}"
    group: "{{ cert__group }}"
    mode: "{{ cert__fullchain_pem_permissions }}"
  become: true

- name: Get content of cert.pem
  ansible.builtin.slurp:
    src: "/etc/ansible_certs/certs/{{ item }}/cert.pem"
  become: true
  register: cert__cert_slurp

- name: Get content of fullchain.pem
  ansible.builtin.slurp:
    src: "/etc/ansible_certs/certs/{{ item }}/fullchain.pem"
  become: true
  register: cert__fullchain_slurp

- name: Ensure chain.pem is created
  ansible.builtin.copy:
    content: "{{ cert__fullchain_slurp.content | b64decode | replace(cert__cert_slurp.content | b64decode, '') }}"
    dest: "/etc/ansible_certs/certs/{{ item }}/chain.pem"
    owner: "{{ cert__owner }}"
    group: "{{ cert__group }}"
    mode: "{{ cert__chain_pem_permissions }}"
  become: true