on:
  workflow_dispatch:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main, develop ]

permissions:
  contents: read

jobs:
  init:
    runs-on: ubuntu-latest
    outputs:
      ip: ${{ steps.config.outputs.ip }}
      id: ${{ steps.config.outputs.id }}
      hostname: ${{ steps.config.outputs.hostname }}
      cores: ${{ steps.config.outputs.cores }}
      memory: ${{ steps.config.outputs.memory }}
      swap: ${{ steps.config.outputs.swap }}
      disk: ${{ steps.config.outputs.disk }}
      boot: ${{ steps.config.outputs.boot }}
      mount: ${{ steps.config.outputs.mount }}
    steps:
      - name: Checkout repository
        uses: actions/checkout@v6
      - name: Set container.env
        id: config
        run: |
          echo "hostname=config" >> $GITHUB_OUTPUT
          source container.env
          echo "ip=127.0.0.1" >> $GITHUB_OUTPUT
          echo "id=$ID" >> $GITHUB_OUTPUT
          echo "cores=$CORES" >> $GITHUB_OUTPUT
          echo "memory=$MEMORY" >> $GITHUB_OUTPUT
          echo "swap=$SWAP" >> $GITHUB_OUTPUT
          echo "disk=$DISK" >> $GITHUB_OUTPUT
          echo "boot=$BOOT" >> $GITHUB_OUTPUT
          echo "mount=$MOUNT" >> $GITHUB_OUTPUT

  build:
    runs-on: ubuntu-latest
    needs: [init]
    steps:
      - name: Checkout repository
        uses: actions/checkout@v6
      - name: Build container
        run: |
          docker build --build-arg TARGETARCH=amd64 -t proxmox-gitops -f local/Dockerfile .
          docker run -d --name proxmox-container -v ${{ github.workspace }}:/workspace -w /workspace proxmox-gitops

  deploy:
    runs-on: ubuntu-latest
    needs: [init]
    steps:
      - name: Checkout repository
        uses: actions/checkout@v6

      - name: Mock bootstrapping
        env:
          IP: ${{ needs.init.outputs.ip }}
          ID: ${{ needs.init.outputs.id }}
        run: |
          sudo apt install -y systemd ansible 
          ssh-keygen -t ed25519 -f "${ID}" -N ''
          cat <<EOF > base.yml
          - hosts: localhost
            gather_facts: false
            connection: local
            become: true
            tasks:
              - name: Apply base configuration
                ansible.builtin.include_role:
                  name: base
          EOF
          sudo env ANSIBLE_ROLES_PATH="$(pwd)/base/roles" ansible-playbook -i localhost, -c local --become -e "ip=${IP} id=${ID}" -e "arch=$(arch="$(uname -m)"; case "$arch" in aarch64|arm64) echo arm64 ;; x86_64) echo amd64 ;; *) echo amd64 ;; esac)" -e "configure_ssh=0" -e "update_system=0" -e "private_key='$(cat ./${ID})\n'" -e "public_key='$(cat ./${ID}.pub)\n'" base.yml

      - name: Mock config.json
        run: |
          cat <<EOF > ./local/config.json
          {"proxmox":{"host":"localhost","user":"root@pam","password":"gitops.pm","node":"pve","gateway":"192.168.178.1","mask":"24","interface":"eth0","bridge":"vmbr0","storage":"local:vztmpl","template":"debian-13-standard_13.1-2"},"login":"proxmox","password":"gitops"}
          EOF

      - name: System installation
        env:
          IP: ${{ needs.init.outputs.ip }}
          ID: ${{ needs.init.outputs.id }}
          PWD: ${{ github.workspace }}
        run: |
          sudo env IP="$IP" ID="$ID" PWD="$PWD" HOME="/app" cinc-client -l info --local-mode --chef-license accept --config-option cookbook_path="." -j ./local/config.json -o config

      - name: Install libs
        env:
          IP: ${{ needs.init.outputs.ip }}
          ID: ${{ needs.init.outputs.id }}
          LOGIN: "proxmox"
          PASSWORD: "gitops"
        run: |
          for lib in $(ls libs); do
            if [ -f "libs/$lib/container.env" ]; then
              source "libs/$lib/container.env"
              cp -r config/libraries libs/$lib
            fi
            if [ "$lib" = "proxy" ]; then
              openssl req -x509 -nodes -newkey rsa:2048 -keyout /tmp/mock.key -out /tmp/mock.crt -days 1 -subj '/CN=127.0.0.1' -addext 'subjectAltName = IP:127.0.0.1' >/dev/null 2>&1
              nohup python3 -c 'import http.server,ssl,json,re,textwrap; s=""" 
              import http.server, ssl, json, re
              class H(http.server.BaseHTTPRequestHandler):
                  protocol_version = "HTTP/1.1"
                  def _r(self,d,code=200):
                      b=json.dumps(d).encode()
                      self.send_response(code)
                      self.send_header("Content-Type","application/json")
                      self.send_header("Content-Length",str(len(b)))
                      self.send_header("Connection","close")
                      self.end_headers()
                      self.wfile.write(b)
                  def do_POST(self):
                      if self.path.endswith("/access/ticket"): self._r({"data":{"ticket":"t","CSRFPreventionToken":"c"}}); return
                      self._r({"data":{}})
                  def do_GET(self):
                      p=self.path
                      if re.search(r"/api2/json/nodes/.*/lxc$",p): self._r({"data":[]}); return
                      if re.search(r"/api2/json/nodes/.*/lxc/\d+/config$",p): self._r({"data":{"net0":"name=eth0,ip=192.168.178.101/24"}}); return
                      if re.search(r"/api2/json/nodes/.*/lxc/\d+/status/current$",p): self._r({"data":{"status":"running"}}); return
                      self._r({"data":{}})
              c=ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
              c.load_cert_chain("/tmp/mock.crt","/tmp/mock.key")
              s=http.server.HTTPServer(("127.0.0.1",8006),H)
              s.socket=c.wrap_socket(s.socket,server_side=True)
              s.serve_forever()
              """; exec(textwrap.dedent(s))' >/dev/null 2>&1 &
            fi
            sudo env IP="127.0.0.1" ID="$ID" HOST="127.0.0.1" LOGIN="$LOGIN" PASSWORD="$PASSWORD" HOME="/app" cinc-client -l info --local-mode --chef-license accept --config-option cookbook_path="['$(pwd)', '$(pwd)/config','$(pwd)/libs']" -o "$lib"
          done

      - name: Idempotency
        env:
          IP: ${{ needs.init.outputs.ip }}
          ID: ${{ needs.init.outputs.id }}
          PWD: ${{ github.workspace }}
        run: |
          sudo env IP="$IP" ID="$ID" PWD="$PWD" HOME="/app" cinc-client -l info --local-mode --chef-license accept --config-option cookbook_path="." -j ./local/config.json -o config