- name: Install and configure Colporteur
  block:
    - name: Create Colporteur system group
      ansible.builtin.group:
        name: "{{ colporteur_sys_group }}"
        system: true
        state: present

    - name: Create Colporteur system user
      ansible.builtin.user:
        name: "{{ colporteur_sys_user }}"
        group: "{{ colporteur_sys_group }}"
        shell: /usr/sbin/nologin
        home: "{{ colporteur_install_path }}"
        create_home: false
        system: true
        state: present

    - name: Create Colporteur installation directory
      ansible.builtin.file:
        path: "{{ colporteur_install_path }}"
        state: directory
        owner: "{{ colporteur_sys_user }}"
        group: "{{ colporteur_sys_group }}"
        mode: "0755"

    - name: Create Colporteur data directory
      ansible.builtin.file:
        path: "{{ colporteur_data_dir }}"
        state: directory
        owner: "{{ colporteur_sys_user }}"
        group: "{{ colporteur_sys_group }}"
        mode: "0711"

    - name: Create Colporteur feeds directory
      ansible.builtin.file:
        path: "{{ colporteur_feeds_dir }}"
        state: directory
        owner: "{{ colporteur_sys_user }}"
        group: "{{ colporteur_sys_group }}"
        mode: "0755"

    - name: Create Colporteur config directory
      ansible.builtin.file:
        path: "{{ colporteur_config_dir }}"
        state: directory
        owner: root
        group: "{{ colporteur_sys_group }}"
        mode: "0750"

    - name: Check if Colporteur version file exists
      ansible.builtin.stat:
        path: "{{ colporteur_install_path }}/version"
      register: colporteur_version_file

    - name: Read installed Colporteur version
      when: colporteur_version_file.stat.exists
      ansible.builtin.slurp:
        src: "{{ colporteur_install_path }}/version"
      register: colporteur_installed_version_raw

    - name: Set installed Colporteur version fact
      ansible.builtin.set_fact:
        colporteur_installed_version: >-
          {{ colporteur_installed_version_raw.content | b64decode | trim
             if colporteur_version_file.stat.exists else '' }}

    - name: Fetch Colporteur binary checksum
      when: colporteur_installed_version != colporteur_version
      become: false
      delegate_to: localhost
      register: colporteur_checksum_content
      ansible.builtin.uri:
        url: "{{ colporteur_checksum_url }}"
        return_content: true

    - name: Set Colporteur checksum fact
      when: colporteur_installed_version != colporteur_version
      ansible.builtin.set_fact:
        colporteur_checksum_sha256: "{{ colporteur_checksum_content.content.split() | first }}"

    - name: Download Colporteur binary archive
      when: colporteur_installed_version != colporteur_version
      ansible.builtin.get_url:
        url: "{{ colporteur_binary_url }}"
        dest: "/tmp/colporteur-{{ colporteur_version }}.tar.gz"
        mode: "0644"
        checksum: "sha256:{{ colporteur_checksum_sha256 }}"

    - name: Extract Colporteur binary archive
      when: colporteur_installed_version != colporteur_version
      ansible.builtin.unarchive:
        src: "/tmp/colporteur-{{ colporteur_version }}.tar.gz"
        dest: "{{ colporteur_install_path }}"
        remote_src: true
        owner: "{{ colporteur_sys_user }}"
        group: "{{ colporteur_sys_group }}"
        mode: "0755"
      notify: Restart colporteur

    - name: Ensure Colporteur binary permissions
      when: colporteur_installed_version != colporteur_version
      ansible.builtin.file:
        path: "{{ colporteur_install_path }}/colporteur"
        owner: "{{ colporteur_sys_user }}"
        group: "{{ colporteur_sys_group }}"
        mode: "0755"

    - name: Write installed version file
      when: colporteur_installed_version != colporteur_version
      ansible.builtin.copy:
        content: "{{ colporteur_version }}"
        dest: "{{ colporteur_install_path }}/version"
        owner: "{{ colporteur_sys_user }}"
        group: "{{ colporteur_sys_group }}"
        mode: "0644"

    - name: Process and deploy Colporteur config
      block:
        - name: Create temp directory for config processing
          ansible.builtin.tempfile:
            state: directory
          delegate_to: localhost
          become: false
          register: colporteur_config_tmpdir

        - name: Copy local config to temp for processing
          ansible.builtin.copy:
            src: "{{ colporteur_config_src }}"
            dest: "{{ colporteur_config_tmpdir.path }}/config.toml"
            mode: "0640"
          delegate_to: localhost
          become: false

        - name: Rewrite passwords to use sidecar secret files
          ansible.builtin.command:
            argv:
              - "{{ ansible_playbook_python }}"
              - "{{ role_path }}/files/rewrite-passwords.py"
              - "{{ colporteur_config_tmpdir.path }}/config.toml"
              - "{{ colporteur_config_dir }}/secrets"
          delegate_to: localhost
          become: false
          register: colporteur_rewrite_result
          changed_when: false

        - name: Parse account passwords from rewrite output
          ansible.builtin.set_fact:
            colporteur_account_passwords: "{{ colporteur_rewrite_result.stdout | from_json }}"

        - name: Deploy processed config file
          ansible.builtin.copy:
            src: "{{ colporteur_config_tmpdir.path }}/config.toml"
            dest: "{{ colporteur_config_dir }}/config.toml"
            owner: root
            group: "{{ colporteur_sys_group }}"
            mode: "0640"
          notify: Restart colporteur
      always:
        - name: Clean up temp directory
          ansible.builtin.file:
            path: "{{ colporteur_config_tmpdir.path }}"
            state: absent
          delegate_to: localhost
          become: false
          when: colporteur_config_tmpdir is defined and colporteur_config_tmpdir.path is defined

    - name: Create secrets directory
      ansible.builtin.file:
        path: "{{ colporteur_config_dir }}/secrets"
        state: directory
        owner: root
        group: "{{ colporteur_sys_group }}"
        mode: "0750"

    - name: Deploy account password sidecar files
      ansible.builtin.copy:
        content: "{{ item.value }}"
        dest: "{{ colporteur_config_dir }}/secrets/{{ item.key }}"
        owner: root
        group: "{{ colporteur_sys_group }}"
        mode: "0640"
      loop: "{{ colporteur_account_passwords | dict2items }}"
      loop_control:
        label: "{{ item.key }}"
      no_log: true
      notify: Restart colporteur

    - name: Deploy Colporteur systemd service file
      ansible.builtin.template:
        src: templates/colporteur.service.j2
        dest: /etc/systemd/system/colporteur.service
        owner: root
        group: root
        mode: "0644"
      notify: Restart colporteur

    - name: Deploy Colporteur systemd timer file
      ansible.builtin.template:
        src: templates/colporteur.timer.j2
        dest: /etc/systemd/system/colporteur.timer
        owner: root
        group: root
        mode: "0644"
      notify: Restart colporteur

    - name: Enable and start Colporteur timer
      ansible.builtin.systemd_service:
        name: colporteur.timer
        enabled: true
        state: started
        daemon_reload: true

    - name: Hash Colporteur feeds password
      ansible.builtin.command:
        argv:
          - caddy
          - hash-password
          - --plaintext
          - "{{ colporteur_feeds_password }}"
      register: colporteur_hashed_password
      changed_when: false
      no_log: true

    - name: Set Colporteur hashed password fact
      ansible.builtin.set_fact:
        colporteur_hashed_password: "{{ colporteur_hashed_password.stdout | trim }}"

    - name: Deploy Colporteur Caddyfile
      ansible.builtin.template:
        src: templates/Caddyfile.j2
        dest: "/etc/caddy/sites/{{ colporteur_domain }}.caddyfile"
        owner: root
        group: root
        mode: "0644"
      notify: Restart caddy

    - name: Sync Colporteur feeds to FreshRSS
      when: colporteur_freshrss_sync | bool
      block:
        - name: Deploy internal Caddyfile for localhost feed serving
          ansible.builtin.template:
            src: templates/Caddyfile-internal.j2
            dest: /etc/caddy/sites/colporteur-internal.caddyfile
            owner: root
            group: root
            mode: "0644"
          notify: Restart caddy

        - name: Flush handlers to ensure Caddy is reloaded
          ansible.builtin.meta: flush_handlers

        - name: Check if FreshRSS CLI exists
          ansible.builtin.stat:
            path: "{{ colporteur_freshrss_install_path }}/cli/import-for-user.php"
          register: colporteur_freshrss_cli_check

        - name: Generate OPML from Colporteur config
          when: colporteur_freshrss_cli_check.stat.exists
          ansible.builtin.command:
            argv:
              - "{{ colporteur_install_path }}/colporteur"
              - export-opml
              - --base-url
              - "http://localhost:{{ colporteur_internal_port }}"
          environment:
            XDG_CONFIG_HOME: /etc
            XDG_DATA_HOME: /var/lib
          become: true
          become_user: "{{ colporteur_sys_user }}"
          register: colporteur_opml_output
          changed_when: false

        - name: Create secure temp file for OPML
          when: colporteur_freshrss_cli_check.stat.exists
          ansible.builtin.tempfile:
            suffix: .opml
          register: colporteur_opml_tmpfile

        - name: Write OPML to temp file
          when: colporteur_freshrss_cli_check.stat.exists
          ansible.builtin.copy:
            content: "{{ colporteur_opml_output.stdout }}"
            dest: "{{ colporteur_opml_tmpfile.path }}"
            owner: "{{ colporteur_freshrss_user }}"
            mode: "0600"

        - name: Import OPML into FreshRSS
          when: colporteur_freshrss_cli_check.stat.exists
          ansible.builtin.command:
            argv:
              - php
              - "{{ colporteur_freshrss_install_path }}/cli/import-for-user.php"
              - "--user={{ admin_user_name }}"
              - "--filename={{ colporteur_opml_tmpfile.path }}"
          become: true
          become_user: "{{ colporteur_freshrss_user }}"
          register: colporteur_freshrss_import_result
          changed_when: "'imported' in colporteur_freshrss_import_result.stdout | default('')"
      always:
        - name: Clean up OPML temp file
          when: colporteur_opml_tmpfile is defined and colporteur_opml_tmpfile.path is defined
          ansible.builtin.file:
            path: "{{ colporteur_opml_tmpfile.path }}"
            state: absent

    - name: Ensure Cloudflare DNS A record exists for {{ colporteur_subdomain + '.' + domain }}
      ansible.builtin.include_role:
        name: dns_record
      vars:
        dns_record_subdomain: "{{ colporteur_subdomain }}"
        dns_record_domain: "{{ domain }}"
        dns_record_cloudflare_api_token: "{{ cloudflare_dns_api_token }}"
