---
- name: Check if cloud-init is installed
  command: which cloud-init
  register: cloud_init_binary
  changed_when: false
  failed_when: false

- name: Wait for cloud-init to finish first-boot tasks
  command: cloud-init status --wait
  register: cloud_init_wait
  changed_when: false
  failed_when: >-
    cloud_init_wait.rc not in [0, 1, 2] or
    (
      'status: done' not in cloud_init_wait.stdout and
      'status: error' not in cloud_init_wait.stdout and
      'status: disabled' not in cloud_init_wait.stdout
    )
  when: cloud_init_binary.rc == 0

- name: Report non-blocking cloud-init error status
  debug:
    msg: |
      cloud-init completed with status error on {{ inventory_hostname }}; continuing because SSH is reachable and Ansible owns package setup.
      {{ cloud_init_wait.stdout | default('') }}
      {{ cloud_init_wait.stderr | default('') }}
  when:
    - cloud_init_binary.rc == 0
    - "'status: error' in (cloud_init_wait.stdout | default(''))"

- name: Persist primary interface MTU for registry egress
  copy:
    dest: /etc/netplan/99-k8s-mtu.yaml
    content: |
      network:
        version: 2
        ethernets:
          {{ ansible_default_ipv4.interface | default('eth0') }}:
            mtu: {{ common_node_mtu }}
    mode: "0600"
  register: k8s_mtu_netplan
  when: common_node_mtu | int > 0

- name: Apply primary interface MTU immediately
  command: ip link set dev {{ ansible_default_ipv4.interface | default('eth0') }} mtu {{ common_node_mtu }}
  changed_when: false
  when: common_node_mtu | int > 0

- name: Apply persisted MTU netplan
  command: netplan apply
  changed_when: true
  when:
    - common_node_mtu | int > 0
    - k8s_mtu_netplan.changed

- name: Update apt cache
  apt:
    update_cache: true
    cache_valid_time: 3600
    lock_timeout: 600

- name: Upgrade packages
  apt:
    upgrade: dist
    lock_timeout: 600
  when: common_upgrade_packages | default(false)

- name: Install required packages
  apt:
    name:
      - apt-transport-https
      - ca-certificates
      - curl
      - gnupg
      - lsb-release
      - software-properties-common
      - jq
      - nfs-common
      - htop
      - vim
    state: present
    lock_timeout: 600

- name: Check active swap
  command: swapon --noheadings
  register: active_swap
  changed_when: false
  failed_when: false

- name: Disable swap
  command: swapoff -a
  changed_when: true
  when: active_swap.stdout | trim | length > 0

- name: Remove swap from fstab
  lineinfile:
    path: /etc/fstab
    regexp: '^\s*[^#]\S+\s+\S+\s+swap\s+.*$'
    state: absent

- name: Load br_netfilter module
  modprobe:
    name: br_netfilter
    state: present

- name: Persist br_netfilter module
  copy:
    dest: /etc/modules-load.d/k8s.conf
    content: |
      br_netfilter
      overlay
    mode: "0644"

- name: Configure sysctl for Kubernetes
  sysctl:
    name: "{{ item.name }}"
    value: "{{ item.value }}"
    state: present
    reload: true
  loop:
    - { name: net.bridge.bridge-nf-call-iptables, value: 1 }
    - { name: net.bridge.bridge-nf-call-ip6tables, value: 1 }
    - { name: net.ipv4.ip_forward, value: 1 }

- name: Check if tailscale is installed
  command: which tailscale
  register: tailscale_binary
  changed_when: false
  failed_when: false
  when: tailscale_auth_key | length > 0

- name: Install tailscale
  shell: curl -fsSL https://tailscale.com/install.sh | sh
  register: tailscale_install
  until: tailscale_install.rc == 0
  retries: 5
  delay: 15
  when:
    - tailscale_auth_key | length > 0
    - tailscale_binary.rc != 0
  changed_when: true

- name: Check tailscale connection state
  command: tailscale status --json
  register: tailscale_status
  changed_when: false
  failed_when: false
  when: tailscale_auth_key | length > 0

- name: Parse tailscale connection state
  set_fact:
    tailscale_backend_state: "{{ (tailscale_status.stdout | from_json).BackendState | default('') }}"
  when:
    - tailscale_auth_key | length > 0
    - tailscale_status.rc == 0
    - tailscale_status.stdout | length > 0

- name: Connect node to tailnet
  command: tailscale up --authkey {{ tailscale_auth_key }} --hostname {{ inventory_hostname }} --ssh={{ tailscale_ssh | ternary('true', 'false') }} --accept-routes={{ tailscale_accept_routes | ternary('true', 'false') }}
  register: tailscale_up
  until: tailscale_up.rc == 0
  retries: 5
  delay: 15
  no_log: true
  when:
    - tailscale_auth_key | length > 0
    - tailscale_status.rc != 0 or (tailscale_backend_state | default('')) != 'Running'
  changed_when: true
