---
# Update_Rest_WMT_client – Push standard WMT client files to target devices
# ──────────────────────────────────────────────────────────────────────────
# What this playbook does (in order):
#
#   1. Verify that WMT_project exists on the controller
#   2. Kill any running WMT app.py on the target
#   3. Remove previous WMT_old (if any) and rename WMT → WMT_old
#   4. Copy WMT_project → fresh WMT on the target
#   5. Fix execute permissions on scripts
#   6. Migrate config values: old config.txt → new config.txt
#        Rules:
#          • For every key that exists in BOTH old and new config  → use old value
#          • Key exists only in new config (new feature)           → keep new default
#          • Key exists only in old config (removed key)          → skip / ignore
#        File structure, comments, and new keys are always from
#        the new template (WMT_project/data/config.txt).
#   7. Restore runtime data files (log.txt, tag.txt) from WMT_old
#   8. Delete WMT_old (migration complete, backup no longer needed)
#   9. Reboot the target host
#
# Run via: Ansible > Playbooks > "Update_Rest_WMT_client" or
#          POST /api/ansible/execute  { "playbook": "Update_Rest_WMT_client.yml" }
# ──────────────────────────────────────────────────────────────────────────

- name: Update WMT client files on target devices
  hosts: all
  gather_facts: false
  become: false

  tasks:

    # ── 1. Verify source exists on the controller ─────────────────────────
    - name: Check WMT_project source folder exists on controller
      delegate_to: localhost
      stat:
        path: /home/pi/Desktop/WMT_project
      register: wmt_project_stat

    - name: Fail if WMT_project is missing on the controller
      delegate_to: localhost
      fail:
        msg: >
          /home/pi/Desktop/WMT_project not found on the Ansible controller.
          Ensure the WMT_project folder is present before running this playbook.
      when: not wmt_project_stat.stat.exists

    # ── 2. Kill any running WMT app.py ────────────────────────────────────
    - name: Stop running WMT app.py (if any)
      shell: pkill -f "python3.*WMT/app.py"
      ignore_errors: true
      changed_when: false

    - name: Wait for process to terminate
      wait_for:
        timeout: 4

    # ── 3a. Remove previous WMT_old backup (if one exists from a prior run)
    - name: Check if WMT_old already exists
      stat:
        path: /home/pi/Desktop/WMT_old
      register: wmt_old_stat

    - name: Remove previous WMT_old folder
      file:
        path: /home/pi/Desktop/WMT_old
        state: absent
      when: wmt_old_stat.stat.exists

    # ── 3b. Rename current WMT → WMT_old ─────────────────────────────────
    - name: Check if WMT folder currently exists
      stat:
        path: /home/pi/Desktop/WMT
      register: wmt_stat

    - name: Rename WMT to WMT_old
      command: mv /home/pi/Desktop/WMT /home/pi/Desktop/WMT_old
      when: wmt_stat.stat.exists

    # ── 4. Copy fresh WMT_project → WMT ──────────────────────────────────
    - name: Copy WMT_project to target as /home/pi/Desktop/WMT
      copy:
        src: /home/pi/Desktop/WMT_project/
        dest: /home/pi/Desktop/WMT/
        owner: pi
        group: pi
        mode: preserve
        force: true

    - name: Ensure WMT/data directory exists
      file:
        path: /home/pi/Desktop/WMT/data
        state: directory
        owner: pi
        group: pi
        mode: '0755'

    # ── 5. Fix execute permissions ────────────────────────────────────────
    - name: Ensure app.py is executable
      file:
        path: /home/pi/Desktop/WMT/app.py
        owner: pi
        group: pi
        mode: '0755'

    - name: Ensure setup_port_capability.sh is executable
      file:
        path: /home/pi/Desktop/WMT/setup_port_capability.sh
        state: file
        owner: pi
        group: pi
        mode: '0755'
      ignore_errors: true

    # ── 6. Migrate config values from old config.txt into new template ────
    #
    #   Strategy (line-preserving Python migration):
    #     • Read WMT_old/data/config.txt  → source of device-specific values
    #     • Read WMT/data/config.txt      → new template (correct keys & comments)
    #     • Walk the new template line by line:
    #         - Keep all comment lines and blank lines unchanged
    #         - For each key=value line:
    #             If old config has the SAME section + key → replace value with old value
    #             If old config does NOT have that key    → keep new default value
    #         - Keys only in old config are silently ignored (removed features)
    #     • Write the result back to WMT/data/config.txt
    #
    - name: Check if old config.txt exists in WMT_old
      stat:
        path: /home/pi/Desktop/WMT_old/data/config.txt
      register: old_cfg_stat

    - name: Migrate config values (old → new template)
      shell: |
        python3 << 'PYEOF'
        import configparser, os, re, sys

        old_path = '/home/pi/Desktop/WMT_old/data/config.txt'
        new_path = '/home/pi/Desktop/WMT/data/config.txt'

        if not os.path.exists(old_path):
            print('No old config.txt found – keeping new defaults as-is')
            sys.exit(0)

        if not os.path.exists(new_path):
            print('New config.txt missing – nothing to migrate into')
            sys.exit(1)

        # Parse old config to get existing values
        old = configparser.ConfigParser()
        old.read(old_path)

        # Walk new template line by line, replacing values where old config has them
        current_section = None
        output_lines = []
        migrated = []
        kept_new = []

        with open(new_path, 'r') as f:
            for line in f:
                stripped = line.rstrip('\n')

                # Detect section header  e.g.  [device]
                section_match = re.match(r'^\s*\[([^\]]+)\]\s*$', stripped)
                if section_match:
                    current_section = section_match.group(1)
                    output_lines.append(line)
                    continue

                # Detect key = value line (skip comments and blank lines)
                kv_match = re.match(r'^([^#;\s][^=]*?)\s*=\s*(.*)', stripped)
                if kv_match and current_section:
                    key = kv_match.group(1).strip()
                    new_val = kv_match.group(2)

                    if old.has_section(current_section) and old.has_option(current_section, key):
                        old_val = old.get(current_section, key)
                        if old_val != new_val:
                            output_lines.append(f'{key}={old_val}\n')
                            migrated.append(f'  [{current_section}] {key} = {old_val!r}  (was: {new_val!r})')
                        else:
                            output_lines.append(line)
                    else:
                        output_lines.append(line)
                        kept_new.append(f'  [{current_section}] {key} = {new_val!r}  (new key – keeping default)')
                else:
                    output_lines.append(line)

        with open(new_path, 'w') as f:
            f.writelines(output_lines)

        print('=== Config migration complete ===')
        if migrated:
            print(f'Migrated {len(migrated)} value(s) from old config:')
            for m in migrated:
                print(m)
        if kept_new:
            print(f'Kept {len(kept_new)} new default(s) (not in old config):')
            for k in kept_new:
                print(k)
        PYEOF
      register: cfg_migration_result
      when: old_cfg_stat.stat.exists
      changed_when: true

    - name: Show config migration output
      debug:
        msg: "{{ cfg_migration_result.stdout_lines }}"
      when: old_cfg_stat.stat.exists

    - name: Note – no old config found, new defaults kept
      debug:
        msg: "WMT_old/data/config.txt not found – new WMT_project defaults will be used."
      when: not old_cfg_stat.stat.exists

    # ── 7. Restore runtime data files from WMT_old ───────────────────────
    - name: Check if log.txt exists in WMT_old
      stat:
        path: /home/pi/Desktop/WMT_old/data/log.txt
      register: old_log_stat

    - name: Restore log.txt from WMT_old
      copy:
        src: /home/pi/Desktop/WMT_old/data/log.txt
        dest: /home/pi/Desktop/WMT/data/log.txt
        owner: pi
        group: pi
        mode: '0644'
        remote_src: true
      when: old_log_stat.stat.exists

    - name: Check if tag.txt exists in WMT_old
      stat:
        path: /home/pi/Desktop/WMT_old/data/tag.txt
      register: old_tag_stat

    - name: Restore tag.txt from WMT_old (pending card posts)
      copy:
        src: /home/pi/Desktop/WMT_old/data/tag.txt
        dest: /home/pi/Desktop/WMT/data/tag.txt
        owner: pi
        group: pi
        mode: '0644'
        remote_src: true
      when: old_tag_stat.stat.exists

    # ── 8. Remove WMT_old now that migration is complete ─────────────────
    - name: Remove WMT_old folder (migration done, no longer needed)
      file:
        path: /home/pi/Desktop/WMT_old
        state: absent

    # ── 9. Show final config and reboot ───────────────────────────────────
    - name: Show final config.txt on target
      command: cat /home/pi/Desktop/WMT/data/config.txt
      register: final_cfg
      changed_when: false

    - name: Display final config.txt
      debug:
        msg: "{{ final_cfg.stdout_lines }}"

    - name: Show updated app.py version
      command: head -1 /home/pi/Desktop/WMT/app.py
      register: app_version
      changed_when: false

    - name: Report update summary
      debug:
        msg: >
          ✓ WMT updated on {{ inventory_hostname }} – {{ app_version.stdout }}.
          Rebooting now to apply changes.

    - name: Reboot target to apply all changes
      become: true
      reboot:
        msg: "Rebooting after WMT client update"
        reboot_timeout: 180
        pre_reboot_delay: 3
        post_reboot_delay: 15


- name: Update WMT client files on target devices
  hosts: all
  gather_facts: false
  become: false

  tasks:

    # ── 1. Confirm WMT_project source exists on the controller ────────────
    - name: Check that WMT_project source folder exists on controller
      delegate_to: localhost
      stat:
        path: /home/pi/Desktop/WMT_project
      register: wmt_project_stat

    - name: Fail if WMT_project is missing on the controller
      delegate_to: localhost
      fail:
        msg: >
          /home/pi/Desktop/WMT_project was not found on the Ansible controller.
          Make sure the WMT_project folder is present before running this playbook.
      when: not wmt_project_stat.stat.exists

    # ── 2. Ensure WMT destination directory exists on target ─────────────
    - name: Ensure /home/pi/Desktop/WMT directory exists
      file:
        path: /home/pi/Desktop/WMT
        state: directory
        owner: pi
        group: pi
        mode: '0755'

    # ── 3. Kill any running WMT app.py process ────────────────────────────
    - name: Stop running WMT app.py (if any)
      shell: pkill -f "python3.*WMT/app.py"
      ignore_errors: true
      changed_when: false

    - name: Wait for process to terminate
      wait_for:
        timeout: 3

    # ── 4. Copy WMT_project → WMT, preserving device-specific data files ─
    - name: Copy WMT_project files to target (excluding device-specific data)
      copy:
        src: /home/pi/Desktop/WMT_project/
        dest: /home/pi/Desktop/WMT/
        owner: pi
        group: pi
        mode: preserve
        force: true
        # Exclude device-specific files that must never be overwritten
        # Note: Ansible's copy module does not support 'exclude' natively;
        # we restore the originals in step 4b–4e below.

    # ── 4b-4e. Restore device-specific data files from the target backup ──
    #   Strategy: before overwriting we slurp the existing files, then
    #   write them back so the 'copy' above cannot clobber them.

    - name: Check if device config.txt exists (pre-copy)
      stat:
        path: /home/pi/Desktop/WMT/data/config.txt
      register: cfg_stat

    - name: Slurp existing config.txt (if present)
      slurp:
        src: /home/pi/Desktop/WMT/data/config.txt
      register: cfg_backup
      when: cfg_stat.stat.exists

    - name: Restore config.txt after copy (device config must not be overwritten)
      copy:
        content: "{{ cfg_backup.content | b64decode }}"
        dest: /home/pi/Desktop/WMT/data/config.txt
        owner: pi
        group: pi
        mode: '0644'
      when: cfg_stat.stat.exists

    # idmasa.txt is a legacy Prezenta file – not used by WMT, not restored

    - name: Check if log.txt exists
      stat:
        path: /home/pi/Desktop/WMT/data/log.txt
      register: log_stat

    - name: Slurp existing log.txt (if present)
      slurp:
        src: /home/pi/Desktop/WMT/data/log.txt
      register: log_backup
      when: log_stat.stat.exists

    - name: Restore log.txt after copy
      copy:
        content: "{{ log_backup.content | b64decode }}"
        dest: /home/pi/Desktop/WMT/data/log.txt
        owner: pi
        group: pi
        mode: '0644'
      when: log_stat.stat.exists

    - name: Check if tag.txt exists
      stat:
        path: /home/pi/Desktop/WMT/data/tag.txt
      register: tag_stat

    - name: Slurp existing tag.txt (if present)
      slurp:
        src: /home/pi/Desktop/WMT/data/tag.txt
      register: tag_backup
      when: tag_stat.stat.exists

    - name: Restore tag.txt after copy
      copy:
        content: "{{ tag_backup.content | b64decode }}"
        dest: /home/pi/Desktop/WMT/data/tag.txt
        owner: pi
        group: pi
        mode: '0644'
      when: tag_stat.stat.exists

    # ── 5. Fix execute permissions on scripts ─────────────────────────────
    - name: Ensure app.py is executable
      file:
        path: /home/pi/Desktop/WMT/app.py
        owner: pi
        group: pi
        mode: '0755'

    - name: Ensure setup_port_capability.sh is executable
      file:
        path: /home/pi/Desktop/WMT/setup_port_capability.sh
        state: file
        owner: pi
        group: pi
        mode: '0755'
      ignore_errors: true

    # ── 6. Ensure WMT/data directory is intact ────────────────────────────
    - name: Ensure WMT/data directory exists
      file:
        path: /home/pi/Desktop/WMT/data
        state: directory
        owner: pi
        group: pi
        mode: '0755'

    # ── 7. Restart WMT app in a new lxterminal session ────────────────────
    - name: Launch WMT app.py in background lxterminal
      shell: >
        DISPLAY=:0 lxterminal -e
        "bash -c 'cd /home/pi/Desktop/WMT; python3 app.py; exec bash'" &
      environment:
        DISPLAY: ":0"
      ignore_errors: true
      changed_when: true

    - name: Wait for WMT app to start
      wait_for:
        timeout: 5

    # ── 8. Confirm update on target ───────────────────────────────────────
    - name: Show updated app.py version line
      command: head -1 /home/pi/Desktop/WMT/app.py
      register: app_version
      changed_when: false

    - name: Report update result
      debug:
        msg: >
          ✓ WMT client updated on {{ inventory_hostname }} ({{ ansible_host }}).
          Version: {{ app_version.stdout }}
