---
- name: Install and configure Paperless-ngx
  block:
    - name: Validate required credentials
      ansible.builtin.assert:
        that:
          - paperless_secret_key is defined
          - paperless_secret_key | length > 0
          - paperless_admin_user is defined
          - paperless_admin_user | length > 0
          - paperless_admin_password is defined
          - paperless_admin_password | length > 0
          - paperless_db_password is defined
          - paperless_db_password | length > 0
        fail_msg: "paperless_secret_key, paperless_admin_user, paperless_admin_password, and paperless_db_password must be defined"

    - name: Get Tailscale status
      ansible.builtin.command: tailscale status --json
      register: paperless_tailscale_status_raw
      changed_when: false
      failed_when: false

    - name: Parse Tailscale status
      ansible.builtin.set_fact:
        paperless_tailscale_status: "{{ paperless_tailscale_status_raw.stdout | from_json }}"
      when: paperless_tailscale_status_raw.rc == 0
      changed_when: false

    - name: Set Tailscale IPv4 fact
      ansible.builtin.set_fact:
        paperless_tailscale_ip: "{{ paperless_tailscale_status.Self.TailscaleIPs | select('match', '^[0-9]+\\.') | first }}"
      when:
        - paperless_tailscale_status_raw.rc == 0
        - paperless_tailscale_status is defined
        - paperless_tailscale_status.BackendState | default('') == "Running"
        - paperless_tailscale_status.Self is defined
        - paperless_tailscale_status.Self.TailscaleIPs is defined
        - paperless_tailscale_status.Self.TailscaleIPs | select('match', '^[0-9]+\\.') | list | length > 0
      changed_when: false

    - name: Fail if Tailscale not available
      ansible.builtin.fail:
        msg: "Tailscale is not running or no Tailscale IP available. Paperless-ngx requires Tailscale."
      when: paperless_tailscale_ip is not defined

    - name: Set bind address
      ansible.builtin.set_fact:
        paperless_bind_addr: "{{ paperless_tailscale_ip }}"
      changed_when: false

    - name: Display bind address
      ansible.builtin.debug:
        msg: "Paperless-ngx will bind to: {{ paperless_bind_addr }}"

    - name: Install system dependencies
      ansible.builtin.apt:
        name:
          - python3
          - python3-pip
          - python3-dev
          - python3-venv
          - build-essential
          - imagemagick
          - gnupg
          - libpq-dev
          - libmariadb-dev
          - pkg-config
          - fonts-liberation
          - libmagic-dev
          - poppler-utils
          - unpaper
          - ghostscript
          - icc-profiles-free
          - qpdf
          - libleptonica6
          - libxml2
          - pngquant
          - zlib1g
          - tesseract-ocr
          - tesseract-ocr-deu
          - tesseract-ocr-fra
          - tesseract-ocr-spa
          - tesseract-ocr-eng
          - redis-server
          - postgresql
          - postgresql-client
        state: present
        update_cache: true

    - name: Ensure Redis is running
      ansible.builtin.systemd_service:
        name: redis-server
        enabled: true
        state: started

    - name: Ensure PostgreSQL is running
      ansible.builtin.systemd_service:
        name: postgresql
        enabled: true
        state: started

    - name: Check if PostgreSQL user exists
      become: true
      become_user: postgres
      ansible.builtin.command:
        cmd: psql -tAc "SELECT 1 FROM pg_roles WHERE rolname='{{ paperless_db_user | replace("'", "''") }}'"
      register: paperless_pg_user_check
      changed_when: false

    - name: Create PostgreSQL user
      become: true
      become_user: postgres
      ansible.builtin.command:
        cmd: psql -c "CREATE USER \"{{ paperless_db_user | replace('\"', '\"\"') }}\" WITH PASSWORD '{{ paperless_db_password | replace("'", "''") }}'"
      when: paperless_pg_user_check.stdout | trim != "1"
      changed_when: true
      no_log: true

    - name: Check if PostgreSQL database exists
      become: true
      become_user: postgres
      ansible.builtin.command:
        cmd: psql -tAc "SELECT 1 FROM pg_database WHERE datname='{{ paperless_db_name | replace("'", "''") }}'"
      register: paperless_pg_db_check
      changed_when: false

    - name: Create PostgreSQL database
      become: true
      become_user: postgres
      ansible.builtin.command:
        cmd: psql -c "CREATE DATABASE \"{{ paperless_db_name | replace('\"', '\"\"') }}\" OWNER \"{{ paperless_db_user | replace('\"', '\"\"') }}\""
      when: paperless_pg_db_check.stdout | trim != "1"
      changed_when: true

    - name: Create Paperless system group
      ansible.builtin.group:
        name: "{{ paperless_sys_group }}"
        system: true
        state: present

    - name: Create Paperless system user
      ansible.builtin.user:
        name: "{{ paperless_sys_user }}"
        group: "{{ paperless_sys_group }}"
        shell: /usr/sbin/nologin
        home: "{{ paperless_install_path }}"
        create_home: false
        system: true
        state: present

    - name: Check installed version
      ansible.builtin.stat:
        path: "{{ paperless_install_path }}/version"
      register: paperless_version_file

    - name: Read installed version
      when: paperless_version_file.stat.exists
      ansible.builtin.slurp:
        src: "{{ paperless_install_path }}/version"
      register: paperless_installed_version_raw

    - name: Set installed version fact
      ansible.builtin.set_fact:
        paperless_installed_version: >-
          {{ paperless_installed_version_raw.content | b64decode | trim
             if paperless_version_file.stat.exists else '' }}

    - name: Create directories
      ansible.builtin.file:
        path: "{{ item }}"
        state: directory
        owner: "{{ paperless_sys_user }}"
        group: "{{ paperless_sys_group }}"
        mode: "0750"
      loop:
        - "{{ paperless_install_path }}"
        - "{{ paperless_data_dir }}"
        - "{{ paperless_media_root }}"
        - "{{ paperless_consumption_dir }}"
        - "{{ paperless_scratch_dir }}"

    - name: Download and extract Paperless-ngx release
      when: paperless_installed_version != paperless_version
      block:
        - name: Download release tarball
          ansible.builtin.get_url:
            url: "{{ paperless_release_url }}"
            dest: /tmp/paperless-ngx.tar.xz
            mode: "0644"

        - name: Extract release tarball
          ansible.builtin.unarchive:
            src: /tmp/paperless-ngx.tar.xz
            dest: "{{ paperless_install_path }}"
            remote_src: true
            extra_opts:
              - --strip-components=1
            owner: "{{ paperless_sys_user }}"
            group: "{{ paperless_sys_group }}"

        - name: Remove tarball
          ansible.builtin.file:
            path: /tmp/paperless-ngx.tar.xz
            state: absent

    - name: Create Python virtual environment
      ansible.builtin.command:
        cmd: python3 -m venv {{ paperless_install_path }}/venv
        creates: "{{ paperless_install_path }}/venv/bin/python3"
      become: true
      become_user: "{{ paperless_sys_user }}"

    - name: Install Python dependencies
      ansible.builtin.pip:
        requirements: "{{ paperless_install_path }}/requirements.txt"
        virtualenv: "{{ paperless_install_path }}/venv"
      become: true
      become_user: "{{ paperless_sys_user }}"

    - name: Detect ImageMagick policy path
      ansible.builtin.command: find /etc -maxdepth 2 -name policy.xml -path "*/ImageMagick-*" -print -quit
      register: paperless_imagemagick_policy
      changed_when: false
      failed_when: paperless_imagemagick_policy.stdout | length == 0

    - name: Configure ImageMagick PDF policy
      ansible.builtin.lineinfile:
        path: "{{ paperless_imagemagick_policy.stdout }}"
        regexp: 'pattern="PDF"'
        line: '  <policy domain="coder" rights="read" pattern="PDF" />'

    - name: Deploy paperless.conf
      ansible.builtin.template:
        src: paperless.conf.j2
        dest: "{{ paperless_install_path }}/paperless.conf"
        owner: "{{ paperless_sys_user }}"
        group: "{{ paperless_sys_group }}"
        mode: "0600"
      notify: Restart all paperless services

    - name: Run database migrations
      ansible.builtin.command:
        cmd: "{{ paperless_install_path }}/venv/bin/python3 manage.py migrate --no-input"
        chdir: "{{ paperless_install_path }}/src"
      become: true
      become_user: "{{ paperless_sys_user }}"
      environment:
        PAPERLESS_CONFIGURATION_PATH: "{{ paperless_install_path }}/paperless.conf"
      register: paperless_migrate_result
      changed_when: "'No migrations to apply' not in paperless_migrate_result.stdout"

    - name: Create admin superuser
      ansible.builtin.command:
        cmd: "{{ paperless_install_path }}/venv/bin/python3 manage.py createsuperuser --noinput"
        chdir: "{{ paperless_install_path }}/src"
      become: true
      become_user: "{{ paperless_sys_user }}"
      environment:
        PAPERLESS_CONFIGURATION_PATH: "{{ paperless_install_path }}/paperless.conf"
        DJANGO_SUPERUSER_USERNAME: "{{ paperless_admin_user }}"
        DJANGO_SUPERUSER_PASSWORD: "{{ paperless_admin_password }}"
        DJANGO_SUPERUSER_EMAIL: "{{ admin_user_email }}"
      register: paperless_createsuperuser_result
      changed_when: "'Superuser created' in paperless_createsuperuser_result.stdout"
      failed_when:
        - paperless_createsuperuser_result.rc != 0
        - "'already taken' not in paperless_createsuperuser_result.stderr"
      no_log: true

    - name: Deploy systemd services
      ansible.builtin.template:
        src: "{{ item }}.j2"
        dest: "/etc/systemd/system/{{ item }}"
        owner: root
        group: root
        mode: "0644"
      loop:
        - paperless-webserver.service
        - paperless-consumer.service
        - paperless-task-queue.service
        - paperless-scheduler.service
      notify: Restart all paperless services

    - name: Enable and start all Paperless services
      ansible.builtin.systemd_service:
        name: "{{ item }}"
        enabled: true
        state: started
        daemon_reload: true
      loop:
        - paperless-webserver
        - paperless-consumer
        - paperless-task-queue
        - paperless-scheduler

    - name: Write installed version
      when: paperless_installed_version != paperless_version
      ansible.builtin.copy:
        content: "{{ paperless_version }}"
        dest: "{{ paperless_install_path }}/version"
        owner: "{{ paperless_sys_user }}"
        group: "{{ paperless_sys_group }}"
        mode: "0644"
      notify: Restart all paperless services

    - name: Display deployment summary
      ansible.builtin.debug:
        msg:
          - "==================================="
          - "Paperless-ngx Deployment Complete!"
          - "==================================="
          - "Version: {{ paperless_version }}"
          - "Bind: {{ paperless_bind_addr }}:{{ paperless_port }}"
          - "Data: {{ paperless_data_dir }}"
          - "Media: {{ paperless_media_root }}"
          - "Consume: {{ paperless_consumption_dir }}"
          - ""
          - "Access: http://{{ paperless_bind_addr }}:{{ paperless_port }}"
          - "Admin: {{ paperless_admin_user }}"
          - ""
          - "Services:"
          - "  systemctl status paperless-webserver"
          - "  systemctl status paperless-consumer"
          - "  systemctl status paperless-task-queue"
          - "  systemctl status paperless-scheduler"
