---
- ansible.builtin.debug:
    msg: "Dealing with SSL certificate retrieval for domain: {{ domain_name }}"

- ansible.builtin.set_fact:
    domain_name_certificate_path: "{{ matrix_ssl_config_dir_path }}/live/{{ domain_name }}/fullchain.pem"

- name: Check if a certificate for the domain already exists
  ansible.builtin.stat:
    path: "{{ domain_name_certificate_path }}"
  register: domain_name_certificate_path_stat

- ansible.builtin.set_fact:
    domain_name_needs_cert: "{{ not domain_name_certificate_path_stat.stat.exists }}"

- block:
    - name: Ensure required service for obtaining is started
      ansible.builtin.service:
        name: "{{ matrix_ssl_pre_obtaining_required_service_name }}"
        state: started
      register: matrix_ssl_pre_obtaining_required_service_start_result

    - name: Wait some time, so that the required service for obtaining can start
      ansible.builtin.wait_for:
        timeout: "{{ matrix_ssl_pre_obtaining_required_service_start_wait_time_seconds }}"
      when: "matrix_ssl_pre_obtaining_required_service_start_result.changed | bool"
  when: "domain_name_needs_cert | bool and matrix_ssl_pre_obtaining_required_service_name != ''"

# This will fail if there is something running on port 80 (like matrix-nginx-proxy).
# We suppress the error, as we'll try another method below.
- name: Attempt initial SSL certificate retrieval with standalone authenticator (directly)
  ansible.builtin.shell: >-
    {{ matrix_host_command_docker }} run
    --rm
    --name=matrix-certbot
    --user={{ matrix_user_uid }}:{{ matrix_user_gid }}
    --cap-drop=ALL
    -p {{ matrix_ssl_lets_encrypt_container_standalone_http_host_bind_port }}:8080
    --mount type=bind,src={{ matrix_ssl_config_dir_path }},dst=/etc/letsencrypt
    --mount type=bind,src={{ matrix_ssl_log_dir_path }},dst=/var/log/letsencrypt
    {{ matrix_ssl_lets_encrypt_certbot_docker_image }}
    certonly
    --non-interactive
    --work-dir=/tmp
    --http-01-port 8080
    {% if matrix_ssl_lets_encrypt_server %}--server={{ matrix_ssl_lets_encrypt_server|quote }}{% endif %}
    {% if matrix_ssl_lets_encrypt_staging %}--staging{% endif %}
    --key-type {{ matrix_ssl_lets_encrypt_key_type }}
    --standalone
    --preferred-challenges http
    --agree-tos
    --email={{ matrix_ssl_lets_encrypt_support_email }}
    -d {{ domain_name }}
  when: domain_name_needs_cert | bool
  register: result_certbot_direct
  ignore_errors: true

# If matrix-nginx-proxy is configured from a previous run of this playbook,
# and it's running now, it may be able to proxy requests to `matrix_ssl_lets_encrypt_certbot_standalone_http_port`.
- name: Attempt initial SSL certificate retrieval with standalone authenticator (via proxy)
  ansible.builtin.shell: >-
    {{ matrix_host_command_docker }} run
    --rm
    --name=matrix-certbot
    --user={{ matrix_user_uid }}:{{ matrix_user_gid }}
    --cap-drop=ALL
    -p 127.0.0.1:{{ matrix_ssl_lets_encrypt_certbot_standalone_http_port }}:8080
    --network={{ matrix_docker_network }}
    --mount type=bind,src={{ matrix_ssl_config_dir_path }},dst=/etc/letsencrypt
    --mount type=bind,src={{ matrix_ssl_log_dir_path }},dst=/var/log/letsencrypt
    {{ matrix_ssl_lets_encrypt_certbot_docker_image }}
    certonly
    --non-interactive
    --work-dir=/tmp
    --http-01-port 8080
    {% if matrix_ssl_lets_encrypt_server %}--server={{ matrix_ssl_lets_encrypt_server|quote }}{% endif %}
    {% if matrix_ssl_lets_encrypt_staging %}--staging{% endif %}
    --key-type {{ matrix_ssl_lets_encrypt_key_type }}
    --standalone
    --preferred-challenges http
    --agree-tos
    --email={{ matrix_ssl_lets_encrypt_support_email }}
    -d {{ domain_name }}
  when: "domain_name_needs_cert and result_certbot_direct.failed"
  register: result_certbot_proxy
  ignore_errors: true

- name: Fail if all SSL certificate retrieval attempts failed
  ansible.builtin.fail:
    msg: |
      Failed to obtain a certificate directly (by listening on port 80)
      and also failed to obtain by relying on the server at port 80 to proxy the request.
      See above for details.
      You may wish to set up proxying of /.well-known/acme-challenge to {{ matrix_ssl_lets_encrypt_certbot_standalone_http_port }} or,
      more easily, stop the server on port 80 while this playbook runs.
  when: "domain_name_needs_cert and result_certbot_direct.failed and result_certbot_proxy.failed"
