---
# Docker Stack Deployment Role
# Deploys docker-compose stacks to hosts
#
# Required variables:
#   stack_name: Name of the stack/directory
#   stack_compose_file: Path to the compose file (relative to repo root)
#
# Optional variables:
#   stack_env_file: Path to .env file (relative to repo root)
#   stack_config_files: List of additional config files to copy
#   stack_deploy: Whether to deploy the stack (default: true)
#   stack_pull_images: Whether to pull images first (default: true)

- name: Ensure stack directory exists
  ansible.builtin.file:
    path: "{{ docker_data_path }}/{{ stack_name }}"
    state: directory
    mode: '0755'
  become: "{{ ansible_become | default(false) }}"

- name: Ensure stack subdirectories exist
  ansible.builtin.file:
    path: "{{ docker_data_path }}/{{ stack_name }}/{{ item }}"
    state: directory
    mode: '0755'
  loop: "{{ stack_subdirs | default(['config', 'data']) }}"
  become: "{{ ansible_become | default(false) }}"

- name: Copy docker-compose file from repo
  ansible.builtin.copy:
    src: "{{ playbook_dir }}/../../{{ stack_compose_file }}"
    dest: "{{ docker_data_path }}/{{ stack_name }}/docker-compose.yml"
    mode: '0644'
    backup: true
  register: compose_file_result
  when: stack_compose_file is defined
  become: "{{ ansible_become | default(false) }}"

- name: Copy docker-compose content directly
  ansible.builtin.copy:
    content: "{{ stack_compose_content }}"
    dest: "{{ docker_data_path }}/{{ stack_name }}/docker-compose.yml"
    mode: '0644'
    backup: true
  register: compose_content_result
  when:
    - stack_compose_content is defined
    - stack_compose_file is not defined
  become: "{{ ansible_become | default(false) }}"

- name: Copy environment file from repo
  ansible.builtin.copy:
    src: "{{ playbook_dir }}/../../{{ stack_env_file }}"
    dest: "{{ docker_data_path }}/{{ stack_name }}/.env"
    mode: '0600'
    backup: true
  when: stack_env_file is defined
  become: "{{ ansible_become | default(false) }}"

- name: Copy environment content directly
  ansible.builtin.copy:
    content: "{{ stack_env_content }}"
    dest: "{{ docker_data_path }}/{{ stack_name }}/.env"
    mode: '0600'
  when:
    - stack_env_content is defined
    - stack_env_file is not defined
  become: "{{ ansible_become | default(false) }}"

- name: Copy additional config files
  ansible.builtin.copy:
    src: "{{ playbook_dir }}/../../{{ item.src }}"
    dest: "{{ docker_data_path }}/{{ stack_name }}/{{ item.dest }}"
    mode: "{{ item.mode | default('0644') }}"
    backup: true
  loop: "{{ stack_config_files | default([]) }}"
  when: stack_config_files is defined
  become: "{{ ansible_become | default(false) }}"

- name: Pull Docker images
  ansible.builtin.command:
    cmd: docker compose pull
    chdir: "{{ docker_data_path }}/{{ stack_name }}"
  register: pull_result
  when: stack_pull_images | default(true)
  changed_when: "'Downloaded' in pull_result.stdout"
  failed_when: false
  become: "{{ ansible_become | default(false) }}"

- name: Deploy stack with docker compose
  ansible.builtin.command:
    cmd: docker compose up -d --remove-orphans
    chdir: "{{ docker_data_path }}/{{ stack_name }}"
  register: deploy_result
  when: stack_deploy | default(true)
  changed_when:
    - "'Started' in deploy_result.stdout or 'Created' in deploy_result.stdout"
    - compose_file_result.changed | default(false) or compose_content_result.changed | default(false)
  become: "{{ ansible_become | default(false) }}"

- name: Wait for stack to be healthy
  ansible.builtin.pause:
    seconds: "{{ stack_health_wait | default(5) }}"
  when:
    - stack_deploy | default(true)
    - stack_health_wait | default(5) > 0
