---
# --- Каталоги и файлы ----------------------------------------------------
- name: Создать каталог развёртывания
  ansible.builtin.file:
    path: "{{ deploy_dir }}"
    state: directory
    owner: root
    group: root
    mode: "0750"
  tags: [env]

- name: Скопировать docker-compose.yaml
  ansible.builtin.copy:
    src: "{{ deploy_src_root }}/docker-compose.yaml"
    dest: "{{ deploy_dir }}/docker-compose.yaml"
    mode: "0640"

# nginx монтирует ./nginx/templates и ./nginx/certs — без шаблонов nginx не
# стартует, поэтому копируем конфигурацию рядом с compose.
- name: Скопировать шаблоны nginx
  ansible.builtin.copy:
    src: "{{ deploy_src_root }}/nginx/templates/"
    dest: "{{ deploy_dir }}/nginx/templates/"
    mode: "0644"

# backend монтирует ./backend/uwsgi.ini (http-socket + 4 воркера) и
# ./backend/production.py (классическая JWT-аутентификация)
- name: Скопировать конфиги backend (uwsgi.ini, production.py)
  ansible.builtin.copy:
    src: "{{ deploy_src_root }}/backend/"
    dest: "{{ deploy_dir }}/backend/"
    mode: "0644"

# --- Секреты: генерация с персистом на control-node (идемпотентно) --------
- name: Сгенерировать/загрузить пароли (persist в secrets_store, gitignored)
  ansible.builtin.set_fact:
    sarex_secrets: >-
      {{ sarex_secrets | default({}) | combine({
        item: lookup('password',
          secrets_store ~ '/' ~ inventory_hostname ~ '/' ~ item
          ~ ' length=' ~ secret_length ~ ' chars=ascii_letters,digits')
      }) }}
  loop: "{{ sarex_secret_vars }}"
  no_log: true
  tags: [env]

# RSA-ключи JWT (RS512): генерируем на control-node, persist в secrets_store.
- name: Сгенерировать приватный RSA-ключ JWT
  ansible.builtin.command: "openssl genrsa -out {{ jwt_private_key_path }} 4096"
  args:
    creates: "{{ jwt_private_key_path }}"
  delegate_to: localhost
  become: false
  tags: [env]

- name: Извлечь публичный RSA-ключ JWT
  ansible.builtin.command: "openssl rsa -in {{ jwt_private_key_path }} -pubout -out {{ jwt_public_key_path }}"
  args:
    creates: "{{ jwt_public_key_path }}"
  delegate_to: localhost
  become: false
  tags: [env]

- name: Собрать словарь переопределений для .env (пароли + домены + JWT)
  ansible.builtin.set_fact:
    env_overrides: >-
      {{ sarex_secrets | combine({
        'PLATFORM_DOMAIN': platform_domain,
        'ADMIN_DOMAIN': admin_domain,
        'MINIO_DOMAIN': minio_domain,
        'SAREX_MINIO_CONSOLE_URL': 'https://' ~ minio_domain,
        'SAREX_JWT_PRIVATE_KEY': "'" ~ (lookup('file', jwt_private_key_path) | replace('\n', '\\n')) ~ "'",
        'SAREX_JWT_PUBLIC_KEY': "'" ~ (lookup('file', jwt_public_key_path) | replace('\n', '\\n')) ~ "'",
      }) }}
  no_log: true
  tags: [env]

- name: Отрендерить .env из .env.example с переопределениями
  ansible.builtin.template:
    src: env.j2
    dest: "{{ deploy_dir }}/.env"
    owner: root
    group: root
    mode: "0600"
  no_log: true
  tags: [env]

# --- Самоподписанный TLS-сертификат для трёх доменов ----------------------
- name: Создать каталог для сертификатов
  ansible.builtin.file:
    path: "{{ cert_dir }}"
    state: directory
    mode: "0750"

- name: Сгенерировать самоподписанный сертификат (SAN на все домены)
  ansible.builtin.shell:
    # umask 077 → приватный ключ создаётся сразу с правами 0600
    cmd: >-
      umask 077 && openssl req -x509 -nodes -newkey rsa:2048 -days {{ cert_days }}
      -keyout {{ cert_dir }}/selfsigned.key
      -out {{ cert_dir }}/selfsigned.crt
      -subj "/CN={{ platform_domain }}"
      -addext "subjectAltName=DNS:{{ platform_domain }},DNS:{{ admin_domain }},DNS:{{ minio_domain }}"
    creates: "{{ cert_dir }}/selfsigned.crt"

# --- Логин в приватный реестр образов (json_key) --------------------------
- name: Проверить, выполнен ли вход в реестр
  ansible.builtin.command: grep -q "{{ registry_host }}" /root/.docker/config.json
  register: registry_login_state
  changed_when: false
  failed_when: false
  tags: [login]

- name: Скопировать ключ реестра на хост (временно)
  ansible.builtin.copy:
    src: "{{ registry_key_src }}"
    dest: /root/.registry-key.json
    mode: "0600"
  when: registry_login_state.rc != 0
  no_log: true
  tags: [login]

- name: docker login в приватный реестр
  ansible.builtin.shell: >-
    set -o pipefail && cat /root/.registry-key.json
    | docker login --username {{ registry_username }} --password-stdin {{ registry_host }}
  args:
    executable: /bin/bash
  when: registry_login_state.rc != 0
  register: registry_login_result
  changed_when: "'Login Succeeded' in registry_login_result.stdout"
  no_log: true
  tags: [login]

- name: Удалить временный ключ реестра с хоста
  ansible.builtin.file:
    path: /root/.registry-key.json
    state: absent
  tags: [login]

# --- Поднять сервисы приложения ------------------------------------------
- name: Поднять сервисы приложения (docker compose up -d)
  ansible.builtin.command:
    cmd: "{{ compose_cmd }} up -d {{ sarex_services | join(' ') }}"
    chdir: "{{ deploy_dir }}"
  when: sarex_compose_up | bool
  changed_when: true
  tags: [up]

# --- Django-суперпользователь: генерация логина+пароля, создание -----------
# Только по явной команде (uv run poe superuser передаёт sarex_create_superuser=true),
# чтобы обычный deploy не дёргал backend. Логин/пароль персистятся в secrets_store
# (переиспользуются при повторе — идемпотентно).
- name: Сгенерировать логин суперпользователя
  ansible.builtin.set_fact:
    superuser_name: "{{ lookup('password', secrets_store ~ '/' ~ inventory_hostname ~ '/SAREX_SUPERUSER_NAME chars=ascii_lowercase,digits length=10') }}"
  when: sarex_create_superuser | default(false) | bool
  no_log: true
  tags: [superuser]

- name: Сгенерировать пароль суперпользователя
  ansible.builtin.set_fact:
    superuser_password: "{{ lookup('password', secrets_store ~ '/' ~ inventory_hostname ~ '/SAREX_SUPERUSER_PASSWORD chars=ascii_letters,digits length=' ~ secret_length) }}"
  when: sarex_create_superuser | default(false) | bool
  no_log: true
  tags: [superuser]

- name: Создать/обновить Django-суперпользователя в backend
  when: sarex_create_superuser | default(false) | bool
  ansible.builtin.command:
    argv:
      - "{{ compose_cmd.split()[0] }}"
      - exec
      - -e
      - "SU_NAME={{ superuser_name }}"
      - -e
      - "SU_PASS={{ superuser_password }}"
      - -e
      - "SU_EMAIL={{ superuser_name }}@{{ platform_domain }}"
      - sarex-backend
      - python
      - manage.py
      - shell
      - -c
      - >-
        import os;
        from django.contrib.auth import get_user_model;
        U = get_user_model();
        u, c = U.objects.get_or_create(username=os.environ['SU_NAME'], defaults={'email': os.environ['SU_EMAIL']});
        u.is_staff = True; u.is_superuser = True; u.set_password(os.environ['SU_PASS']); u.save();
        print('created' if c else 'updated')
  register: superuser_result
  changed_when: true
  no_log: true
  tags: [superuser]

- name: Показать учётные данные суперпользователя
  ansible.builtin.debug:
    msg: "Django superuser  →  login: {{ superuser_name }}   password: {{ superuser_password }}"
  when: sarex_create_superuser | default(false) | bool
  tags: [superuser]
