---
- name: Развернуть file-1C telemetry uploader на Windows
  hosts: aw_windows
  gather_facts: false

  vars:
    aw_windows_repo_root: "{{ playbook_dir | dirname }}"
    aw_windows_state_root: "C:\\ProgramData\\AWatch-rus"
    aw_windows_deploy_root: "C:\\Program Files\\AWatch-rus"
    aw_windows_file_1c_target_user: "igor"
    aw_windows_file_1c_auto_upload_interval_hours: 6
    aw_windows_file_1c_auto_upload_task_name: "ActivityWatch File1C Upload"
    aw_windows_file_1c_remote_root: "/opt/activitywatch/clickhouse-1c/landing"
    aw_windows_file_1c_remote_key_path: ""
    aw_windows_file_1c_registry_workbook_path: "E:\\USER1\\СПИСОК ПРЕДПРИЯТИЙ И ИХ РАСПРЕДЕЛЕНИЕ.xlsx"
    aw_windows_upload_key_private_path: /tmp/awops_ed25519
    aw_windows_upload_key_public_path: /tmp/awops_ed25519.pub

  tasks:
    - name: Вычислить inventory host analytics node по умолчанию
      ansible.builtin.set_fact:
        aw_analytics_inventory_host_effective: "{{ (groups['proxmox'] | default([]) | first) | default('', true) }}"

    - name: Вычислить effective host для file-1C analytics
      ansible.builtin.set_fact:
        aw_windows_file_1c_target_host_effective: >-
          {{
            aw_windows_file_1c_target_host
            | default(
                (
                  hostvars[aw_analytics_inventory_host_effective].ansible_host
                  | default(aw_analytics_inventory_host_effective, true)
                )
                if (aw_analytics_inventory_host_effective | length) > 0
                else '',
                true
              )
          }}

    - name: Проверить обязательные переменные file-1C telemetry
      ansible.builtin.assert:
        that:
          - aw_windows_file_1c_target_host_effective | length > 0
        fail_msg: "Не удалось вычислить host file-1C analytics для Windows uploader."

    - name: Создать каталоги file-1C telemetry на Windows
      ansible.windows.win_file:
        path: "{{ item }}"
        state: directory
      loop:
        - "{{ aw_windows_state_root }}"
        - "{{ aw_windows_deploy_root }}\\windows"
        - "{{ aw_windows_state_root }}\\ssh"

    - name: Установить private key для Windows file-1C uploader
      ansible.windows.win_copy:
        src: "{{ aw_windows_upload_key_private_path }}"
        dest: "{{ aw_windows_state_root }}\\ssh\\awops_ed25519"

    - name: Установить public key для Windows file-1C uploader
      ansible.windows.win_copy:
        src: "{{ aw_windows_upload_key_public_path }}"
        dest: "{{ aw_windows_state_root }}\\ssh\\awops_ed25519.pub"

    - name: Загрузить file-1C telemetry script в toolkit
      ansible.windows.win_copy:
        src: "{{ aw_windows_repo_root }}/windows/export-upload-file-1c-telemetry.ps1"
        dest: "{{ aw_windows_deploy_root }}\\windows\\export-upload-file-1c-telemetry.ps1"

    - name: Загрузить file-1C telemetry script в state root
      ansible.windows.win_copy:
        src: "{{ aw_windows_repo_root }}/windows/export-upload-file-1c-telemetry.ps1"
        dest: "{{ aw_windows_state_root }}\\export-upload-file-1c-telemetry.ps1"

    - name: Обновить deployment-config.json блоком analytics.file1cAutomation
      ansible.windows.win_powershell:
        script: |
          $ErrorActionPreference = 'Stop'
          $configPath = "{{ aw_windows_state_root }}\deployment-config.json"
          $config = Get-Content -Raw -LiteralPath $configPath | ConvertFrom-Json

          if ($config.PSObject.Properties.Name -notcontains 'paths') {
            $config | Add-Member -NotePropertyName 'paths' -NotePropertyValue ([pscustomobject]@{})
          }
          if ($config.paths.PSObject.Properties.Name -contains 'file1cTelemetryScript') {
            $config.paths.file1cTelemetryScript = "{{ aw_windows_state_root }}\export-upload-file-1c-telemetry.ps1"
          } else {
            $config.paths | Add-Member -NotePropertyName 'file1cTelemetryScript' -NotePropertyValue "{{ aw_windows_state_root }}\export-upload-file-1c-telemetry.ps1"
          }

          if ($config.PSObject.Properties.Name -notcontains 'analytics') {
            $config | Add-Member -NotePropertyName 'analytics' -NotePropertyValue ([pscustomobject]@{})
          }

          $automation = [pscustomobject]@{
            enabled = $true
            intervalHours = {{ aw_windows_file_1c_auto_upload_interval_hours | int }}
            taskName = "{{ aw_windows_file_1c_auto_upload_task_name }}"
            targetHost = "{{ aw_windows_file_1c_target_host_effective }}"
            targetUser = "{{ aw_windows_file_1c_target_user }}"
            remoteRoot = "{{ aw_windows_file_1c_remote_root }}"
            registryWorkbookPath = "{{ aw_windows_file_1c_registry_workbook_path }}"
            remoteKeyPath = "{{ aw_windows_file_1c_remote_key_path }}"
          }

          if ($config.analytics.PSObject.Properties.Name -contains 'file1cAutomation') {
            $config.analytics.file1cAutomation = $automation
          } else {
            $config.analytics | Add-Member -NotePropertyName 'file1cAutomation' -NotePropertyValue $automation
          }

          $json = $config | ConvertTo-Json -Depth 12
          Set-Content -LiteralPath $configPath -Value $json -Encoding UTF8

    - name: Разложить file-1C upload key по локальным пользовательским профилям
      ansible.windows.win_powershell:
        script: |
          $ErrorActionPreference = 'Stop'
          $src = "{{ aw_windows_state_root }}\ssh\awops_ed25519"
          if (-not (Test-Path -LiteralPath $src)) {
            throw "Не найден private key uploader: $src"
          }

          $statePath = "{{ aw_windows_state_root }}\file1c-telemetry-state.json"
          if (-not (Test-Path -LiteralPath $statePath)) {
            '{}' | Set-Content -LiteralPath $statePath -Encoding UTF8
          }

          $profiles = Get-CimInstance Win32_UserProfile |
            Where-Object { -not $_.Special -and $_.LocalPath -like 'C:\Users\*' } |
            Sort-Object LocalPath

          foreach ($profile in $profiles) {
            $user = Split-Path $profile.LocalPath -Leaf
            $sshDir = Join-Path $profile.LocalPath '.ssh'
            $dst = Join-Path $sshDir 'awops_ed25519'
            $grantDir = 'SHARKON2025\' + $user + ':(OI)(CI)(F)'
            $grantRead = 'SHARKON2025\' + $user + ':(R)'
            $grantModify = 'SHARKON2025\' + $user + ':(M)'

            New-Item -ItemType Directory -Path $sshDir -Force | Out-Null
            & icacls.exe $sshDir /grant $grantDir | Out-Null
            & icacls.exe $statePath /grant $grantModify | Out-Null

            if (-not (Test-Path -LiteralPath $dst)) {
              Copy-Item -LiteralPath $src -Destination $dst -Force
            }

            & icacls.exe $dst /inheritance:r /grant:r $grantRead '*S-1-5-18:(R)' '*S-1-5-32-544:(R)' | Out-Null
          }

    - name: Создать scheduled task file-1C upload
      ansible.windows.win_powershell:
        script: |
          $ErrorActionPreference = 'Stop'
          $taskName = "{{ aw_windows_file_1c_auto_upload_task_name }}"
          $powerShellExe = Join-Path $env:SystemRoot 'System32\WindowsPowerShell\v1.0\powershell.exe'
          $taskCommand = "`"$powerShellExe`" -NoProfile -ExecutionPolicy Bypass -File `"{{ aw_windows_state_root }}\export-upload-file-1c-telemetry.ps1`" -ConfigPath `"{{ aw_windows_state_root }}\deployment-config.json`""
          $existingTask = Get-ScheduledTask -TaskName $taskName -ErrorAction SilentlyContinue
          if ($existingTask) {
            $action = New-ScheduledTaskAction -Execute $powerShellExe -Argument "-NoProfile -ExecutionPolicy Bypass -File `"{{ aw_windows_state_root }}\export-upload-file-1c-telemetry.ps1`" -ConfigPath `"{{ aw_windows_state_root }}\deployment-config.json`""
            try {
              Set-ScheduledTask -TaskName $taskName -Action $action -ErrorAction Stop | Out-Null
            } catch {
              Write-Host "skip task action update for $taskName because the existing principal requires stored credentials: $($_.Exception.Message)"
            }
          } else {
            & schtasks.exe /Create /TN $taskName /TR $taskCommand /SC HOURLY /MO {{ aw_windows_file_1c_auto_upload_interval_hours | int }} /ST 00:00 /RU SYSTEM /RL HIGHEST /F | Out-Null
            if ($LASTEXITCODE -ne 0) {
              throw "Не удалось создать scheduled task $taskName"
            }
          }
