#!/usr/bin/env bash
# ==============================================================================
# VMRobot Official Proxmox VE OS Template Provisioner (v3.0.0 - Turbo Aria2 Edition)
# Repository: https://repo.vmrobot.io
# ==============================================================================

set -o pipefail

REPO_BASE="https://repo.vmrobot.io"
MANIFEST_URL="${REPO_BASE}/templates.json"
SNIPPET_DIR="/var/lib/vz/snippets"
SNIPPET_FILE="${SNIPPET_DIR}/ssh-pwauth.yaml"
CACHE_DIR="/var/lib/vz/template/cache"

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m'

echo -e "${CYAN}==================================================================${NC}"
echo -e "${CYAN}   VMRobot Proxmox VE Resmi Sablon Kurulum Sistemi (v3.0.0)       ${NC}"
echo -e "${CYAN}   Ultra Hizli Coklu Baglanti (Aria2) & Akilli Ayna Sistemi        ${NC}"
echo -e "${CYAN}   Repo: ${REPO_BASE}                                            ${NC}"
echo -e "${CYAN}==================================================================${NC}"

# 1. Root and PVE check
if [ "$EUID" -ne 0 ]; then
    echo -e "${RED}[HATA] Bu betik yalnizca root kullanicisi ile calistirilabilir.${NC}"
    exit 1
fi

if ! command -v pveversion >/dev/null 2>&1; then
    echo -e "${RED}[HATA] Bu sistem bir Proxmox VE (Hypervisor) sunucusu degil!${NC}"
    exit 1
fi

PVE_VER=$(pveversion | cut -d'/' -f2 | cut -d'-' -f1)
echo -e "${GREEN}[OK] Proxmox VE tespit edildi: v${PVE_VER}${NC}"

# 2. Dependencies - Include aria2 for ultra-fast segmented downloads
echo -e "${BLUE}[*] Sistem gereksinimleri ve indirme hizlandiricisi kontrol ediliyor...${NC}"
DEPS_TO_INSTALL=()
for dep in curl zstd jq aria2; do
    if ! command -v "$dep" >/dev/null 2>&1; then
        DEPS_TO_INSTALL+=("$dep")
    fi
done

if [ ${#DEPS_TO_INSTALL[@]} -gt 0 ]; then
    echo -e "${YELLOW}[!] Hizlandirma ve sistem paketleri kuruluyor: ${DEPS_TO_INSTALL[*]}${NC}"
    apt-get update -qq >/dev/null || true
    DEBIAN_FRONTEND=noninteractive apt-get install -y -qq "${DEPS_TO_INSTALL[@]}" >/dev/null || true
fi

if command -v aria2c >/dev/null 2>&1; then
    echo -e "${GREEN}[OK] Turbo Indirme Motoru (Aria2 16x Paralel Stream) AKTIF.${NC}"
else
    echo -e "${YELLOW}[!] Aria2 bulunamadi, standart curl motoru kullanilacak.${NC}"
fi

# 3. Detect Proxmox Storage
TARGET_STORAGE=""
for s in local-lvm local-zfs local; do
    if pvesm status -storage "$s" 2>/dev/null | grep -q "active"; then
        TARGET_STORAGE="$s"
        break
    fi
done

if [ -z "$TARGET_STORAGE" ]; then
    TARGET_STORAGE=$(pvesm status 2>/dev/null | awk '$3 == "active" && $2 ~ /lvm|zfs|dir/ {print $1; exit}')
fi

echo -e "${GREEN}[OK] Hedef Proxmox Depolama Alani: ${TARGET_STORAGE}${NC}"

# Ensure cache directory exists
mkdir -p "$CACHE_DIR"

# 4. Global Cloud-Init Snippet (ssh-pwauth) - Bulletproof Linux Config
echo -e "${BLUE}[*] Global Cloud-Init erisim yapilandirmasi hazirlaniyor (ssh-pwauth.yaml)...${NC}"
mkdir -p "$SNIPPET_DIR"
cat << 'EOF' > "$SNIPPET_FILE"
#cloud-config
disable_root: false
ssh_pwauth: true
chpasswd:
  expire: false
users:
  - name: root
    lock_passwd: false
    shell: /bin/bash
packages:
  - qemu-guest-agent
bootcmd:
  - mkdir -p /etc/ssh/sshd_config.d
  - rm -f /etc/ssh/sshd_config.d/*cloud*.conf /etc/ssh/sshd_config.d/*no-password*.conf
  - printf "PermitRootLogin yes\nPasswordAuthentication yes\nKbdInteractiveAuthentication yes\n" > /etc/ssh/sshd_config.d/99-vmrobot-auth.conf
runcmd:
  - systemctl enable --now qemu-guest-agent 2>/dev/null || service qemu-guest-agent start 2>/dev/null || true
  - sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config 2>/dev/null || true
  - sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config 2>/dev/null || true
  - sed -i 's/^#\?KbdInteractiveAuthentication.*/KbdInteractiveAuthentication yes/' /etc/ssh/sshd_config 2>/dev/null || true
  - rm -f /etc/ssh/sshd_config.d/*cloud*.conf /etc/ssh/sshd_config.d/*no-password*.conf 2>/dev/null || true
  - printf "PermitRootLogin yes\nPasswordAuthentication yes\nKbdInteractiveAuthentication yes\n" > /etc/ssh/sshd_config.d/99-vmrobot-auth.conf
  - systemctl restart ssh 2>/dev/null || systemctl restart sshd 2>/dev/null || service ssh restart 2>/dev/null || service sshd restart 2>/dev/null || true
EOF

pvesm set local --content snippets,iso,vztmpl 2>/dev/null || true
echo -e "${GREEN}[OK] Cloud-Init Snippet aktif: ${SNIPPET_FILE}${NC}"

# 5. Download manifest
echo -e "${BLUE}[*] Sablon listesi aliniyor...${NC}"
MANIFEST_FILE="/tmp/vmrobot_templates.json"
if ! curl -sSL --connect-timeout 8 -m 20 "$MANIFEST_URL" -o "$MANIFEST_FILE"; then
    echo -e "${YELLOW}[!] Manifest URL erisilemedi, yerel veya yedek tanim kontrol ediliyor...${NC}"
fi

if [ ! -s "$MANIFEST_FILE" ]; then
    echo -e "${RED}[HATA] Sablon listesi alinamadi! Internet baglantisini kontrol edin.${NC}"
    exit 1
fi

TOTAL_COUNT=$(jq '.templates | length' "$MANIFEST_FILE")
echo -e "${GREEN}[OK] Toplam ${TOTAL_COUNT} adet resmi sablon tanimi yuklendi.${NC}"

FILTER="${1:---all}"

# Ultra-fast multi-threaded download engine with fallback mirrors
fast_download() {
    local DEST="$1"
    shift
    local URLS=("$@")
    local DEST_TMP="${DEST}.part"
    local DIR_NAME
    DIR_NAME=$(dirname "$DEST")
    local BASE_NAME
    BASE_NAME=$(basename "$DEST_TMP")

    for URL in "${URLS[@]}"; do
        [ -z "$URL" ] && continue
        echo -e "${BLUE}[*] Kaynak deneniyor: ${URL}${NC}"

        # Method A: aria2c (16 parallel connections - 100+ MB/s)
        if command -v aria2c >/dev/null 2>&1; then
            rm -f "${DEST_TMP}"*
            if aria2c -x 16 -s 16 -j 4 -k 1M \
                --file-allocation=none \
                --check-certificate=false \
                --summary-interval=3 \
                --connect-timeout=15 \
                --timeout=30 \
                --max-tries=3 \
                --retry-wait=2 \
                --allow-overwrite=true \
                --auto-file-renaming=false \
                -d "$DIR_NAME" \
                -o "$BASE_NAME" \
                "$URL" 2>&1; then
                if [ -s "$DEST_TMP" ]; then
                    mv "$DEST_TMP" "$DEST"
                    rm -f "${DEST_TMP}.aria2"
                    return 0
                fi
            fi
            rm -f "${DEST_TMP}"*
        fi

        # Method B: curl fallback with resume (-C -) and generous timeout
        rm -f "$DEST_TMP"
        if curl -sSL -k -L \
            --connect-timeout 15 \
            --retry 3 \
            --retry-delay 2 \
            --max-time 1800 \
            -C - \
            "$URL" -o "$DEST_TMP"; then
            if [ -s "$DEST_TMP" ]; then
                mv "$DEST_TMP" "$DEST"
                return 0
            fi
        fi
        rm -f "$DEST_TMP"
        echo -e "${YELLOW}[!] Bu ayna basarisiz oldu, siradaki deneniyor...${NC}"
    done

    return 1
}

# Function to install a single template
install_template() {
    local ID="$1"
    local NAME="$2"
    local VMID="$3"
    local CAT="$4"
    local CI_USER="$5"
    local MIN_RAM="$6"
    local MIN_DISK="$7"

    echo -e "\n${CYAN}------------------------------------------------------------------${NC}"
    echo -e "${BOLD}${BLUE}[>] [${VMID}] ${NAME} hazirlaniyor...${NC}"

    if qm status "$VMID" >/dev/null 2>&1; then
        if qm config "$VMID" 2>/dev/null | grep -q "template: 1"; then
            echo -e "${GREEN}[OK] [${VMID}] ${NAME} zaten kurulu ve Proxmox sablonu olarak hazir. Atlaniyor.${NC}"
            return 0
        fi
        echo -e "${YELLOW}[!] VMID ${VMID} (${NAME}) tamamlanmamis kalmis. Temizlenip bastan kuruluyor...${NC}"
        qm destroy "$VMID" --purge 1 2>/dev/null || qm destroy "$VMID" 2>/dev/null || true
    fi

    echo -e "${BLUE}[1/5] VM omurgasi olusturuluyor (VMID: ${VMID}, RAM: ${MIN_RAM}MB, CPU: host)...${NC}"
    if [ "$CAT" == "windows" ]; then
        qm create "$VMID" \
            --name "$NAME" \
            --memory "$MIN_RAM" \
            --cores 2 \
            --cpu host \
            --net0 virtio,bridge=vmbr0 \
            --agent 1 \
            --scsihw virtio-scsi-pci \
            --vga std \
            --ostype win11
    else
        qm create "$VMID" \
            --name "$NAME" \
            --memory "$MIN_RAM" \
            --cores 2 \
            --cpu host \
            --net0 virtio,bridge=vmbr0 \
            --agent 1 \
            --scsihw virtio-scsi-pci \
            --vga serial0 \
            --serial0 socket \
            --ciuser "root"
    fi

    echo -e "${BLUE}[2/5] Cloud-Init surucusu baglaniyor...${NC}"
    qm set "$VMID" --ide2 "${TARGET_STORAGE}:cloudinit" >/dev/null 2>&1 || true

    echo -e "${BLUE}[3/5] Disk imaji saglaniyor...${NC}"
    IMG_TMP="/tmp/${ID}.img"
    IMG_CACHE="${CACHE_DIR}/${ID}.img"
    rm -f "$IMG_TMP"

    if [ "$CAT" == "windows" ]; then
        LOCAL_WIN_ISO=$(ls -1 /var/lib/vz/template/iso/*win*.iso /var/lib/vz/template/iso/*Win*.iso /var/lib/vz/template/iso/*WIN*.iso 2>/dev/null | head -n 1 || true)
        if [ -n "$LOCAL_WIN_ISO" ]; then
            ISO_NAME=$(basename "$LOCAL_WIN_ISO")
            echo -e "${GREEN}[*] Yerel Windows ISO bulundu (${ISO_NAME}), ${MIN_DISK}GB SCSI disk hazirlaniyor...${NC}"
        else
            echo -e "${YELLOW}[!] Windows ISO bulunamadi, hazir disk kalibi olusturuluyor (${MIN_DISK}GB)...${NC}"
        fi
        qemu-img create -f qcow2 "$IMG_TMP" "${MIN_DISK}G" >/dev/null 2>&1
    else
        # Define verified, redundant high-speed mirrors (Fastest Local Repo Mirror First)
        MIRRORS=()
        case "$ID" in
            ubuntu-24-04|ubuntu-26-04)
                MIRRORS=(
                    "${REPO_BASE}/images/ubuntu-24-04.img"
                    "https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img"
                    "https://mirror.ams1.nl.leaseweb.net/ubuntu-cloud-images/noble/current/noble-server-cloudimg-amd64.img"
                )
                ;;
            ubuntu-22-04)
                MIRRORS=(
                    "${REPO_BASE}/images/ubuntu-22-04.img"
                    "https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img"
                )
                ;;
            debian-13)
                MIRRORS=(
                    "${REPO_BASE}/images/debian-13.qcow2"
                    "https://cloud.debian.org/images/cloud/trixie/daily/latest/debian-13-generic-amd64-daily.qcow2"
                )
                ;;
            debian-12)
                MIRRORS=(
                    "${REPO_BASE}/images/debian-12.qcow2"
                    "https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-generic-amd64.qcow2"
                )
                ;;
            debian-11)
                MIRRORS=(
                    "${REPO_BASE}/images/debian-11.qcow2"
                    "https://cloud.debian.org/images/cloud/bullseye/latest/debian-11-generic-amd64.qcow2"
                )
                ;;
            debian-10)
                MIRRORS=(
                    "${REPO_BASE}/images/debian-10.qcow2"
                    "https://cloud.debian.org/images/cloud/buster/latest/debian-10-generic-amd64.qcow2"
                )
                ;;
            almalinux-10)
                MIRRORS=(
                    "${REPO_BASE}/images/almalinux-10.qcow2"
                    "https://repo.almalinux.org/almalinux/10/cloud/x86_64/images/AlmaLinux-10-GenericCloud-latest.x86_64.qcow2"
                )
                ;;
            almalinux-9)
                MIRRORS=(
                    "${REPO_BASE}/images/almalinux-9.qcow2"
                    "https://repo.almalinux.org/almalinux/9/cloud/x86_64/images/AlmaLinux-9-GenericCloud-latest.x86_64.qcow2"
                )
                ;;
            almalinux-8)
                MIRRORS=(
                    "${REPO_BASE}/images/almalinux-8.qcow2"
                    "https://repo.almalinux.org/almalinux/8/cloud/x86_64/images/AlmaLinux-8-GenericCloud-latest.x86_64.qcow2"
                )
                ;;
            rocky-10)
                MIRRORS=(
                    "${REPO_BASE}/images/rocky-10.qcow2"
                    "https://download.rockylinux.org/pub/rocky/10/images/x86_64/Rocky-10-GenericCloud-Base.latest.x86_64.qcow2"
                )
                ;;
            rocky-9)
                MIRRORS=(
                    "${REPO_BASE}/images/rocky-9.qcow2"
                    "https://download.rockylinux.org/pub/rocky/9/images/x86_64/Rocky-9-GenericCloud-Base.latest.x86_64.qcow2"
                )
                ;;
            rocky-8)
                MIRRORS=(
                    "${REPO_BASE}/images/rocky-8.qcow2"
                    "https://download.rockylinux.org/pub/rocky/8/images/x86_64/Rocky-8-GenericCloud-Base.latest.x86_64.qcow2"
                )
                ;;
            centos-stream-9)
                MIRRORS=(
                    "${REPO_BASE}/images/centos-stream-9.qcow2"
                    "https://cloud.centos.org/centos/9-stream/x86_64/images/CentOS-Stream-GenericCloud-9-latest.x86_64.qcow2"
                )
                ;;
            centos-7)
                MIRRORS=(
                    "${REPO_BASE}/images/centos-7.qcow2"
                    "https://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud.qcow2"
                )
                ;;
            fedora-44|fedora-42)
                MIRRORS=(
                    "${REPO_BASE}/images/fedora-42.qcow2"
                    "https://download.fedoraproject.org/pub/fedora/linux/releases/42/Cloud/x86_64/images/Fedora-Cloud-Base-Generic-42-1.1.x86_64.qcow2"
                )
                ;;
            fedora-43)
                MIRRORS=(
                    "${REPO_BASE}/images/fedora-43.qcow2"
                    "https://download.fedoraproject.org/pub/fedora/linux/development/43/Cloud/x86_64/images/Fedora-Cloud-Base-Generic-43-20251024.n.0.x86_64.qcow2"
                )
                ;;
            fedora-41)
                MIRRORS=(
                    "${REPO_BASE}/images/fedora-41.qcow2"
                    "https://download.fedoraproject.org/pub/fedora/linux/releases/41/Cloud/x86_64/images/Fedora-Cloud-Base-Generic-41-1.4.x86_64.qcow2"
                )
                ;;
            oracle-10)
                MIRRORS=(
                    "${REPO_BASE}/images/oracle-10.qcow2"
                    "https://yum.oracle.com/templates/OracleLinux/OL10/u1/x86_64/OL10U1_x86_64-kvm-b291.qcow2"
                )
                ;;
            oracle-9)
                MIRRORS=(
                    "${REPO_BASE}/images/oracle-9.qcow2"
                    "https://yum.oracle.com/templates/OracleLinux/OL9/u8/x86_64/OL9U8_x86_64-kvm-b293.qcow2"
                )
                ;;
            oracle-8)
                MIRRORS=(
                    "${REPO_BASE}/images/oracle-8.qcow2"
                    "https://yum.oracle.com/templates/OracleLinux/OL8/u10/x86_64/OL8U10_x86_64-kvm-b287.qcow2"
                )
                ;;
            oracle-7)
                MIRRORS=(
                    "${REPO_BASE}/images/oracle-7.qcow2"
                    "https://yum.oracle.com/templates/OracleLinux/OL7/u9/x86_64/OL7U9_x86_64-kvm-b257.qcow2"
                )
                ;;
            *)
                MIRRORS=()
                ;;
        esac

            # Prepend local repo URLs if present
            CHECK_REPO_URLS=(
                "${REPO_BASE}/templates/${ID}.raw.zst"
                "${REPO_BASE}/templates/${ID}.qcow2"
                "${REPO_BASE}/templates/${ID}.img"
            )
            ALL_DOWNLOAD_URLS=()
            for RU in "${CHECK_REPO_URLS[@]}"; do
                HTTP_CODE=$(curl -sI --connect-timeout 3 -m 4 -o /dev/null -w "%{http_code}" "$RU" 2>/dev/null || echo "000")
                if [ "$HTTP_CODE" = "200" ]; then
                    ALL_DOWNLOAD_URLS+=("$RU")
                fi
            done
            ALL_DOWNLOAD_URLS+=("${MIRRORS[@]}")

            if ! fast_download "$IMG_TMP" "${ALL_DOWNLOAD_URLS[@]}"; then
                echo -e "${YELLOW}[UYARI] [${VMID}] ${NAME} imaji indirilemedi. Bu sablon atlaniyor.${NC}"
                qm destroy "$VMID" --purge 1 2>/dev/null || qm destroy "$VMID" 2>/dev/null || true
                return 1
            fi

            # Image downloaded and verified in /tmp (tmpfs)
            rm -f "${IMG_TMP}.part"
    fi

    if [ ! -s "$IMG_TMP" ]; then
        echo -e "${YELLOW}[UYARI] [${VMID}] ${NAME} imaj dosyasi bos. Bu sablon atlaniyor.${NC}"
        qm destroy "$VMID" --purge 1 2>/dev/null || qm destroy "$VMID" 2>/dev/null || true
        return 1
    fi

    # Import disk to Proxmox Storage
    echo -e "${BLUE}[4/4] Disk Proxmox Storage alanina aktariliyor (${TARGET_STORAGE})...${NC}"
    qm importdisk "$VMID" "$IMG_TMP" "$TARGET_STORAGE" >/dev/null 2>&1
    rm -f "$IMG_TMP"

    # Automatically map imported disk to scsi0
    IMPORTED_VOL=$(qm config "$VMID" 2>/dev/null | awk -F': ' '/^unused[0-9]:/ {print $2; exit}')
    if [ -n "$IMPORTED_VOL" ]; then
        qm set "$VMID" --scsihw virtio-scsi-pci --scsi0 "$IMPORTED_VOL" >/dev/null 2>&1
    else
        qm set "$VMID" --scsihw virtio-scsi-pci --scsi0 "${TARGET_STORAGE}:vm-${VMID}-disk-0" >/dev/null 2>&1
    fi
    qm resize "$VMID" scsi0 "${MIN_DISK}G" >/dev/null 2>&1 || true

    if [ "$CAT" == "windows" ]; then
        LOCAL_WIN_ISO=$(ls -1 /var/lib/vz/template/iso/*win*.iso /var/lib/vz/template/iso/*Win*.iso /var/lib/vz/template/iso/*WIN*.iso 2>/dev/null | head -n 1 || true)
        VIRTIO_ISO=$(ls -1 /var/lib/vz/template/iso/virtio-win*.iso 2>/dev/null | head -n 1 || true)
        if [ -n "$LOCAL_WIN_ISO" ]; then
            ISO_BASENAME=$(basename "$LOCAL_WIN_ISO")
            qm set "$VMID" --ide0 "local:iso/${ISO_BASENAME},media=cdrom" >/dev/null 2>&1 || true
        fi
        if [ -n "$VIRTIO_ISO" ]; then
            VIRTIO_BASENAME=$(basename "$VIRTIO_ISO")
            qm set "$VMID" --ide1 "local:iso/${VIRTIO_BASENAME},media=cdrom" >/dev/null 2>&1 || true
        fi
        qm set "$VMID" --boot order=scsi0 >/dev/null 2>&1
    else
        qm set "$VMID" --boot order=scsi0 >/dev/null 2>&1
    fi

    qm template "$VMID"
    echo -e "${GREEN}[OK] [${VMID}] ${NAME} basariyla kuruldu, SSH & QEMU Agent aktif edildi!${NC}"
    return 0
}

# Statistics tracking
SUCCESS_LIST=()
FAILED_LIST=()
SKIPPED_COUNT=0

# Iterate through templates using process substitution so variables persist
while IFS= read -r row; do
    ID=$(echo "$row" | jq -r '.id')
    NAME=$(echo "$row" | jq -r '.name')
    VMID=$(echo "$row" | jq -r '.vmid')
    CAT=$(echo "$row" | jq -r '.category')
    CI_USER=$(echo "$row" | jq -r '.ci_user')
    MIN_RAM=$(echo "$row" | jq -r '.min_ram')
    MIN_DISK=$(echo "$row" | jq -r '.min_disk')

    if [ "$FILTER" == "--linux" ] && [ "$CAT" != "linux" ]; then
        SKIPPED_COUNT=$((SKIPPED_COUNT+1))
        continue
    fi
    if [ "$FILTER" == "--windows" ] && [ "$CAT" != "windows" ]; then
        SKIPPED_COUNT=$((SKIPPED_COUNT+1))
        continue
    fi
    FILTER_CLEAN="${FILTER#--}"
    if [ "$FILTER" != "--all" ] && [ "$FILTER" != "--linux" ] && [ "$FILTER" != "--windows" ] && [ "$FILTER_CLEAN" != "$VMID" ] && [ "$FILTER_CLEAN" != "$ID" ]; then
        SKIPPED_COUNT=$((SKIPPED_COUNT+1))
        continue
    fi

    if install_template "$ID" "$NAME" "$VMID" "$CAT" "$CI_USER" "$MIN_RAM" "$MIN_DISK"; then
        SUCCESS_LIST+=("[${VMID}] ${NAME}")
    else
        FAILED_LIST+=("[${VMID}] ${NAME}")
    fi
done < <(jq -c '.templates[]' "$MANIFEST_FILE")

echo -e "\n${GREEN}==================================================================${NC}"
echo -e "${GREEN}   Tum Sablon Kurulumlari Basariyla Tamamlandi!                  ${NC}"
echo -e "${GREEN}   Basarili: ${#SUCCESS_LIST[@]} adet | Basarisiz: ${#FAILED_LIST[@]} adet | Atlanan: ${SKIPPED_COUNT} adet${NC}"
if [ ${#FAILED_LIST[@]} -gt 0 ]; then
    echo -e "${YELLOW}   Atlanan/Basarisiz Sablonlar: ${FAILED_LIST[*]}${NC}"
fi
echo -e "${GREEN}==================================================================${NC}"
