#!/usr/bin/env bash
# ============================================================
# VerifyBlind - iOS Kod Dogrulama Araci (macOS / Linux)
# App Store'a yuklenen iOS uygulamasinin GitHub'daki acik koddan
# derlendigini kriptografik olarak kanitlar (Sigstore build provenance).
#
# iOS'ta Android'deki gibi telefondan binary cekilemez: Apple'in FairPlay
# DRM'i cihazdaki uygulamayi sifreler (tum iOS uygulamalari icin gecerli
# platform kisiti). Bu arac yerine su zinciri dogrular:
#   1. Apple'a yuklenen IPA'nin GitHub commit'inden derlendigi (Sigstore imzasi)
#   2. Stok iOS yalnizca Apple imzali App Store kopyasini calistirir
#   3. App Attest: sunucu her kayitta orijinal build'i Apple uzerinden dogrular
# ============================================================

set -euo pipefail

GITHUB_REPO="VerifyBlind/VerifyBlind-iOS"
OIDC_ISSUER="https://token.actions.githubusercontent.com"
IDENTITY_REGEX="^https://github.com/$GITHUB_REPO/.github/workflows/ios-(dev|prod).yml@"

# --- Renkler ---
CYAN='\033[0;36m'; GREEN='\033[0;32m'; RED='\033[0;31m'
GRAY='\033[0;90m'; WHITE='\033[1;37m'; NC='\033[0m'

step()  { echo -e "\n${CYAN}>>> $1${NC}"; }
ok()    { echo -e "  ${GREEN}[OK]${NC} $1"; }
fail()  { echo -e "  ${RED}[!!]${NC} $1"; }
info()  { echo -e "  ${GRAY}$1${NC}"; }

echo ""
echo -e "${WHITE}============================================${NC}"
echo -e "${WHITE}  VerifyBlind iOS Kod Dogrulama Araci${NC}"
echo -e "${WHITE}============================================${NC}"

# --- 1. Gerekli araclari kontrol et ---
step "Gerekli araclar kontrol ediliyor..."
SHA_CMD="sha256sum"
command -v sha256sum &>/dev/null || { command -v shasum &>/dev/null && SHA_CMD="shasum -a 256"; }
for tool in curl openssl grep; do
    if ! command -v "$tool" &>/dev/null; then
        fail "Eksik arac: $tool"
        exit 1
    fi
done
ok "Tum araclar mevcut."

# --- 2. Build numarasini al ---
step "Build numarasi"
info "Telefonunuzda VerifyBlind > Ayarlar ekraninin EN ALTINDAKI surum satirina bakin."
info "Ornek: '1.0.1 (27) · abc1234'  ->  build numarasi 27'dir."
printf "  Build numarasini girin (bos = en son release dogrulanir): "
read -r BUILD_INPUT

if [ -z "$BUILD_INPUT" ]; then
    ASSET_BASE="https://github.com/$GITHUB_REPO/releases/latest/download"
    info "Build numarasi girilmedi - en son release dogrulanacak."
else
    # Prod release: "build-N", dev release: "dev-build-N" — ikisini de dene.
    ASSET_BASE=""
    for PREFIX in "build" "dev-build"; do
        CANDIDATE="https://github.com/$GITHUB_REPO/releases/download/$PREFIX-$BUILD_INPUT"
        if curl -fsSL --head "$CANDIDATE/ipa-hashes.json" -o /dev/null 2>/dev/null; then
            ASSET_BASE="$CANDIDATE"
            TAG_FOUND="$PREFIX-$BUILD_INPUT"
            break
        fi
    done
    if [ -z "$ASSET_BASE" ]; then
        fail "Build $BUILD_INPUT icin GitHub Release bulunamadi."
        info "Denenen tag'ler: build-$BUILD_INPUT, dev-build-$BUILD_INPUT"
        exit 1
    fi
    info "Release tag: $TAG_FOUND"
fi

# --- 3. Release dosyalarini indir ---
step "GitHub Release dosyalari indiriliyor..."
TEMP_DIR=$(mktemp -d)
trap 'rm -rf "$TEMP_DIR"' EXIT

for asset in ipa-hashes.json attestation.sigstore.json VerifyBlind.ipa; do
    if ! curl -fsSL "$ASSET_BASE/$asset" -o "$TEMP_DIR/$asset"; then
        fail "$asset indirilemedi."
        info "URL: $ASSET_BASE/$asset"
        info "Bu build icin henuz bir GitHub Release olusturulmamis olabilir."
        exit 1
    fi
done
ok "Uc dosya indirildi (IPA + hash manifesti + attestation)."

LOCAL_IPA="$TEMP_DIR/VerifyBlind.ipa"
LOCAL_HASHES="$TEMP_DIR/ipa-hashes.json"
LOCAL_BUNDLE="$TEMP_DIR/attestation.sigstore.json"

MF_COMMIT=$(grep -o '"git_commit": *"[^"]*"' "$LOCAL_HASHES" | cut -d'"' -f4)
MF_BUILD=$(grep -o '"build_number": *[0-9]*' "$LOCAL_HASHES" | grep -o '[0-9]*')
MF_VERSION=$(grep -o '"version_name": *"[^"]*"' "$LOCAL_HASHES" | cut -d'"' -f4)
MF_IPA_SHA=$(grep -o '"ipa_sha256": *"[^"]*"' "$LOCAL_HASHES" | cut -d'"' -f4)

ok "Versiyon : $MF_VERSION (Build $MF_BUILD)"
ok "Commit   : $MF_COMMIT"
if [ -n "$BUILD_INPUT" ] && [ "$MF_BUILD" != "$BUILD_INPUT" ]; then
    fail "Manifest build numarasi ($MF_BUILD) girdiginizle ($BUILD_INPUT) eslesmiyor."
    exit 1
fi

# --- 4. IPA hash'ini hesapla ve manifestle karsilastir ---
step "IPA SHA-256 hesaplaniyor..."
IPA_HASH=$($SHA_CMD "$LOCAL_IPA" | awk '{print $1}')
if [ "$IPA_HASH" = "$MF_IPA_SHA" ]; then
    ok "IPA hash'i manifest ile ESLESTI"
    info "  $IPA_HASH"
else
    fail "IPA hash'i manifest ile eslesmiyor!"
    info "  Beklenen : $MF_IPA_SHA"
    info "  Gelen    : $IPA_HASH"
    exit 1
fi

# --- 5. cosign kontrol (yoksa otomatik indir) ---
step "cosign (Sigstore dogrulama araci) kontrol ediliyor..."
COSIGN="cosign"
if command -v cosign &>/dev/null; then
    ok "cosign sistemde bulundu."
else
    CACHE_DIR="${TMPDIR:-/tmp}/verifyblind_cosign"
    COSIGN="$CACHE_DIR/cosign"
    if [ -x "$COSIGN" ]; then
        ok "cosign onceki indirmeden bulundu."
    else
        case "$(uname -s)" in
            Darwin) COS_OS="darwin" ;;
            Linux)  COS_OS="linux" ;;
            *) fail "Desteklenmeyen isletim sistemi: $(uname -s)"; exit 1 ;;
        esac
        case "$(uname -m)" in
            x86_64)        COS_ARCH="amd64" ;;
            arm64|aarch64) COS_ARCH="arm64" ;;
            *) fail "Desteklenmeyen mimari: $(uname -m)"; exit 1 ;;
        esac
        info "cosign bulunamadi. Resmi GitHub release'inden indiriliyor (~100 MB)..."
        mkdir -p "$CACHE_DIR"
        if ! curl -fsSL "https://github.com/sigstore/cosign/releases/latest/download/cosign-$COS_OS-$COS_ARCH" -o "$COSIGN"; then
            fail "cosign indirilemedi."
            info "Manuel kurulum: https://github.com/sigstore/cosign/releases"
            exit 1
        fi
        chmod +x "$COSIGN"
        ok "cosign indirildi ($COSIGN)."
    fi
fi

# --- 6. Sigstore attestation dogrulamasi ---
# Imza, GitHub Actions'in OIDC kimligine baglidir: yalnizca VerifyBlind-iOS reposunun
# ios-prod.yml workflow'u bu imzayi uretebilir. Sahte attestation matematiksel olarak uretilemez.
step "Build provenance imzasi dogrulaniyor (Sigstore)..."
if ! "$COSIGN" verify-blob-attestation \
        --bundle "$LOCAL_BUNDLE" \
        --new-bundle-format \
        --type slsaprovenance1 \
        --certificate-oidc-issuer "$OIDC_ISSUER" \
        --certificate-identity-regexp "$IDENTITY_REGEX" \
        "$LOCAL_IPA" 2>&1 | sed 's/^/  /'; then
    fail "Attestation imza dogrulamasi BASARISIZ."
    exit 1
fi
ok "Sigstore imzasi gecerli: bu IPA, $GITHUB_REPO/ios-prod.yml tarafindan uretildi."

# --- 7. Attestation icerigini coz: hangi commit'ten derlendi? ---
step "Attestation icerigi okunuyor..."
PAYLOAD_B64=$(grep -o '"payload" *: *"[^"]*"' "$LOCAL_BUNDLE" | head -1 | sed 's/.*: *"//; s/"$//')
PAD=$(( ${#PAYLOAD_B64} % 4 ))
if [ "$PAD" -ne 0 ]; then PAYLOAD_B64="$PAYLOAD_B64$(printf '=%.0s' $(seq 1 $((4 - PAD))))"; fi
STATEMENT=$(printf '%s' "$PAYLOAD_B64" | openssl base64 -d -A)

SUBJECT_HASH=$(printf '%s' "$STATEMENT" | grep -o '"sha256" *: *"[0-9a-f]\{64\}"' | head -1 | grep -o '[0-9a-f]\{64\}')
ATT_COMMIT=$(printf '%s' "$STATEMENT" | grep -o '"gitCommit" *: *"[0-9a-f]*"' | head -1 | cut -d'"' -f4)

if [ "$SUBJECT_HASH" != "$IPA_HASH" ]; then
    fail "Attestation'daki hash indirilen IPA ile eslesmiyor!"
    info "  Attestation : $SUBJECT_HASH"
    info "  IPA         : $IPA_HASH"
    exit 1
fi
ok "Attestation'in imzaladigi hash, indirilen IPA'nin hash'i ile ESLESTI."

if [ "$ATT_COMMIT" != "$MF_COMMIT" ]; then
    fail "Attestation commit'i ($ATT_COMMIT) manifest commit'i ($MF_COMMIT) ile eslesmiyor."
    exit 1
fi
ok "Kaynak commit (imzali kanittan): $ATT_COMMIT"

# --- 7b. (Opsiyonel) USB bagli cihazdan build numarasini dogrula ---
# Bu adim, build numarasini uygulamanin kendi UI'sinden degil dogrudan iOS'un
# kayit defterinden (lockdown servisi) okur. Uygulama bu degeri tahrif edemez.
# NOT: Bu adim henuz Mac uzerinde test edilmemistir.
if [[ "$OSTYPE" == "darwin"* ]]; then
    step "Cihaz dogrulamasi — macOS + USB (opsiyonel)"
    info "Build numarasini iOS kayit defterinden okur; uygulama UI'sindeki"
    info "degeri degistirse bile bu adim gercek numarayi gosterir."
    info "(!) Bu adim henuz Mac uzerinde test edilmemistir."
    printf "  Atlamak icin ENTER, denemek icin 'd' girin: "
    read -r USB_CHOICE

    if [[ "$USB_CHOICE" == "d" || "$USB_CHOICE" == "D" ]]; then
        DEVICE_BUILD=""
        TRIED_TOOL=""
        RAW_OUTPUT=""

        # --- Yontem 1: ideviceinstaller (brew install libimobiledevice ideviceinstaller) ---
        if command -v ideviceinstaller &>/dev/null; then
            info "ideviceinstaller ile sorgulanıyor..."
            IDA_LINE=$(ideviceinstaller -l 2>/dev/null | grep "app\.verifyblind\.ios" | head -1 || true)
            if [[ -n "$IDA_LINE" ]]; then
                TRIED_TOOL="ideviceinstaller"
                RAW_OUTPUT="$IDA_LINE"
                # Beklenen format: "app.verifyblind.ios, 73, VerifyBlind"
                # Ikinci virgul-ayracli alan CFBundleVersion (build numarasi).
                PARSED=$(echo "$IDA_LINE" | cut -d',' -f2 | tr -d '[:space:]')
                if [[ "$PARSED" =~ ^[0-9]+$ ]]; then
                    DEVICE_BUILD="$PARSED"
                fi
            fi
        fi

        # --- Yontem 2: xcrun devicectl (Xcode 15+, iOS 17+) ---
        if [[ -z "$DEVICE_BUILD" ]] && command -v xcrun &>/dev/null; then
            DEVICE_ID=$(xcrun devicectl list devices 2>/dev/null \
                | grep -oE '[0-9A-Fa-f]{8}-[0-9A-Fa-f]{16}' | head -1 || true)
            if [[ -n "$DEVICE_ID" ]]; then
                info "xcrun devicectl ile sorgulanıyor (${DEVICE_ID:0:8}...)..."
                DCTL_OUT=$(xcrun devicectl device info apps \
                    --device "$DEVICE_ID" \
                    --bundle-id "app.verifyblind.ios" 2>/dev/null || true)
                if [[ -n "$DCTL_OUT" ]]; then
                    TRIED_TOOL="xcrun devicectl"
                    RAW_OUTPUT="${DCTL_OUT:0:600}"
                    PARSED=$(printf '%s' "$DCTL_OUT" | python3 -c '
import sys, json
try:
    d = json.load(sys.stdin)
    apps = d.get("result", {}).get("apps", [])
    if apps:
        v = str(apps[0].get("bundleVersion") or apps[0].get("buildVersion") or "").strip()
        print(v)
except Exception:
    pass
' 2>/dev/null || true)
                    if [[ "$PARSED" =~ ^[0-9]+$ ]]; then
                        DEVICE_BUILD="$PARSED"
                    fi
                fi
            fi
        fi

        # --- Sonuc ---
        if [[ -n "$DEVICE_BUILD" ]]; then
            if [[ "$DEVICE_BUILD" == "$MF_BUILD" ]]; then
                ok "Cihaz build numarasi ($TRIED_TOOL): $DEVICE_BUILD — manifest ile ESLESTI"
                ok "Tam zincir: iOS OS → Build $MF_BUILD → Commit $ATT_COMMIT (Sigstore imzali)"
            else
                fail "Cihazdan okunan build ($DEVICE_BUILD) != dogrulanan release ($MF_BUILD)!"
                info "Telefonunuzda farkli bir surum yuklu olabilir."
                info "Dogru build numarasi ile scripti yeniden calistirin."
                exit 1
            fi
        elif [[ -n "$RAW_OUTPUT" ]]; then
            info ""
            info "*** Parse basarisiz: bu adim henuz Mac uzerinde test edilmemistir. ***"
            info "Duzeltmemiz icin lutfen asagidaki bilgileri mail ile gonderin:"
            info "  Kime : support@verifyblind.com"
            info "  Konu : verify-ios.sh cihaz adimi parse hatasi"
            info "  ------------------------------------------------"
            info "  Arac     : $TRIED_TOOL"
            info "  Ham cikt : $RAW_OUTPUT"
            info "  OS/arch  : $(uname -srm)"
            if command -v ideviceinstaller &>/dev/null; then
                info "  ideviceinstaller: $(ideviceinstaller --version 2>/dev/null | head -1 || echo 'N/A')"
            fi
            info "  ------------------------------------------------"
            info ""
            info "Kriptografik dogrulama (Sigstore) tamamlandi; bu adim opsiyoneldir."
        else
            info "Build numarasi cihazdan okunamadi. Olasi nedenler:"
            info "  - ideviceinstaller kurulu degil:"
            info "      brew install libimobiledevice ideviceinstaller"
            info "  - iPhone Mac'e bagli degil veya kilitli"
            info "  - 'Bu bilgisayara guvensin mi?' onayini vermediniz"
            info "Kriptografik dogrulama (Sigstore) tamamlandi; bu adim opsiyoneldir."
        fi
    fi
fi

# --- 8. Sonuc ---
echo ""
echo -e "${WHITE}============================================${NC}"
echo -e "${GREEN}  DOGRULAMA BASARILI${NC}"
echo -e "${GREEN}  Apple'a Build $MF_BUILD olarak yuklenen uygulama${NC}"
echo -e "${GREEN}  asagidaki acik kaynak koddan derlenmistir:${NC}"
echo -e "${WHITE}============================================${NC}"
echo ""

COMMIT_URL="https://github.com/$GITHUB_REPO/tree/$ATT_COMMIT"
echo -e "${WHITE}  Kaynak Kod : ${CYAN}$COMMIT_URL${NC}"
echo ""
info "Zincirin geri kalanini Apple kapatir:"
info "  - Ayni build numarasi App Store Connect'te yalnizca BIR kez var olabilir."
info "  - Stok iOS yalnizca Apple imzali App Store kopyasini calistirir;"
info "    degistirilmis bir uygulama cihazda hic acilmaz."
info "  - App Attest: VerifyBlind sunucusu her kayitta, cihazdaki uygulamanin"
info "    orijinal App Store build'i oldugunu Apple uzerinden dogrular."
info "  - Mac + USB: iPhone'u baglayarak build numarasini iOS kayit defterinden"
info "    okuyabilirsiniz (7b. adim) — zinciri uygulama UI'sinden bagimsiz kapatir."
echo ""

if [[ "$OSTYPE" == "darwin"* ]]; then
    echo -e "${GRAY}  Kaynak kodu tarayicida acmak icin ENTER'a basin...${NC}"
    read -r
    open "$COMMIT_URL"
else
    echo -e "${GRAY}  Yukardaki linki tarayicinizda acabilirsiniz.${NC}"
fi
