#!/bin/bash

# Etkileşimli Çok Formatlı Arşivleme ve Çıkarma Betiği | v2.x
# Yazar: @erhodev
# Tarih: 2025-05-03

# Renk tanımlamaları
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m' # Renksiz

# İşlem türü seçimi
function select_operation_type {
    clear
    echo -e "${GREEN}=== Etkileşimli Arşivleme Aracına Hoş Geldiniz ===${NC}"
    echo
    echo -e "${YELLOW}Yapmak istediğiniz işlemi seçin:${NC}"
    echo -e "  ${CYAN}1) Yeni bir arşiv oluştur (yedekle)${NC}"
    echo -e "  ${CYAN}2) Mevcut bir arşivi çıkart (geri yükle)${NC}"
    echo -e "  ${CYAN}q) Çıkış${NC}"
    echo

    local choice
    read -p "Seçiminiz (1/2/q): " choice

    case $choice in
        1)
            backup_operation
            ;;
        2)
            extract_operation
            ;;
        q|Q)
            echo -e "${GREEN}Program sonlandırılıyor. İyi günler!${NC}"
            exit 0
            ;;
        *)
            echo -e "${RED}Geçersiz seçim! Lütfen 1, 2 veya q girin.${NC}"
            sleep 2
            select_operation_type
            ;;
    esac
}

# Yedekleme işlemi
function backup_operation {
    local source_dir
    local dest_dir
    local format
    local level

    # Kaynak dizini sor
    echo
    echo -e "${YELLOW}1. Yedeklemek istediğiniz klasörün yolunu girin:${NC}"
    read -p "Kaynak dizin: " source_dir

    # Dizin kontrolü
    if [ ! -d "$source_dir" ]; then
        echo -e "${RED}Hata: '$source_dir' bulunamadı veya bir dizin değil.${NC}"
        echo -e "${YELLOW}Tekrar denemek ister misiniz? (e/h)${NC}"
        local retry
        read -p "Seçiminiz (e/h): " retry
        case $retry in
            e|E)
                backup_operation
                return
                ;;
            *)
                select_operation_type
                return
                ;;
        esac
    fi

    # Hedef dizini sor
    echo
    echo -e "${YELLOW}2. Yedeğin kaydedileceği dizini girin:${NC}"
    echo -e "${BLUE}Not: Boş bırakırsanız mevcut dizin kullanılacaktır.${NC}"
    read -p "Hedef dizin: " dest_dir

    # Hedef dizin boş ise mevcut dizini kullan
    if [ -z "$dest_dir" ]; then
        dest_dir="$(pwd)"
        echo -e "${BLUE}Mevcut dizin kullanılacak: $dest_dir${NC}"
    else
        # Hedef dizin yoksa oluştur
        if [ ! -d "$dest_dir" ]; then
            echo -e "${YELLOW}Dizin '$dest_dir' mevcut değil. Oluşturulsun mu? (e/h)${NC}"
            local create_dir
            read -p "Seçiminiz (e/h): " create_dir
            case $create_dir in
                e|E)
                    mkdir -p "$dest_dir"
                    if [ $? -ne 0 ]; then
                        echo -e "${RED}Hata: Hedef dizin '$dest_dir' oluşturulamadı.${NC}"
                        echo "Ana menüye dönülüyor..."
                        sleep 2
                        select_operation_type
                        return
                    fi
                    echo -e "${GREEN}Dizin başarıyla oluşturuldu.${NC}"
                    ;;
                *)
                    echo "Ana menüye dönülüyor..."
                    sleep 2
                    select_operation_type
                    return
                    ;;
            esac
        fi
    fi

    # Arşiv formatını sor
    echo
    echo -e "${YELLOW}3. Kullanmak istediğiniz arşiv formatını seçin:${NC}"
    echo -e "  ${CYAN}1) zip${NC} - En yaygın format, tüm platformlarda desteklenir"
    echo -e "  ${CYAN}2) tar${NC} - Sıkıştırmasız, hızlı, Linux izinlerini korur"
    echo -e "  ${CYAN}3) targz${NC} - Orta seviye sıkıştırma, Linux'ta yaygın"
    echo -e "  ${CYAN}4) tarbz2${NC} - İyi sıkıştırma, daha yavaş"
    echo -e "  ${CYAN}5) tarxz${NC} - En iyi sıkıştırma, en yavaş"
    echo -e "  ${CYAN}6) 7z${NC} - Çok iyi sıkıştırma, çoklu platform desteği"
    echo

    local format_choice
    read -p "Format seçimi (1-6): " format_choice

    case $format_choice in
        1) format="zip" ;;
        2) format="tar" ;;
        3) format="targz" ;;
        4) format="tarbz2" ;;
        5) format="tarxz" ;;
        6) format="7z" ;;
        *)
            echo -e "${RED}Geçersiz seçim! Varsayılan olarak zip kullanılacak.${NC}"
            format="zip"
            ;;
    esac

    # Sıkıştırma seviyesini sor
    echo
    echo -e "${YELLOW}4. Sıkıştırma seviyesini seçin (0-9):${NC}"
    echo -e "${BLUE}Not: 0 = sıkıştırma yok (hızlı), 9 = maksimum sıkıştırma (yavaş)${NC}"
    echo -e "${BLUE}Önerilen: 5 (dengeli)${NC}"

    read -p "Sıkıştırma seviyesi (0-9, varsayılan: 5): " level

    # Seviyeyi doğrula
    if [[ ! "$level" =~ ^[0-9]$ ]]; then
        echo -e "${YELLOW}Geçersiz seviye. Varsayılan olarak 5 kullanılacak.${NC}"
        level=5
    fi

    # Özet bilgileri göster ve onay al
    clear
    echo -e "${GREEN}=== İşlem Özeti ===${NC}"
    echo -e "${BLUE}Kaynak Dizin:${NC} $source_dir"
    echo -e "${BLUE}Hedef Dizin:${NC} $dest_dir"
    echo -e "${BLUE}Arşiv Formatı:${NC} $format"
    echo -e "${BLUE}Sıkıştırma Seviyesi:${NC} $level"

    # Kaynak klasörün boyutunu hesapla
    local source_size=$(du -sh "$source_dir" | cut -f1)
    echo -e "${BLUE}Kaynak Boyutu:${NC} $source_size"
    echo

    echo -e "${YELLOW}Bu ayarlarla yedekleme işlemini başlatmak istiyor musunuz? (e/h)${NC}"
    local confirm
    read -p "Onaylıyor musunuz? (e/h): " confirm

    case $confirm in
        e|E)
            # Zaman damgası oluştur
            local timestamp=$(date +"%Y%m%d_%H%M%S")
            local source_dir_name=$(basename "$source_dir")

            # Arşivi oluştur
            echo -e "${MAGENTA}Yedekleme işlemi başlatılıyor...${NC}"
            create_archive "$format" "$source_dir" "$dest_dir" "$level" "$timestamp" "$source_dir_name"

            echo
            echo -e "${YELLOW}Ana menüye dönmek ister misiniz? (e/h)${NC}"
            local return_main
            read -p "Seçiminiz (e/h): " return_main

            case $return_main in
                e|E)
                    select_operation_type
                    ;;
                *)
                    echo -e "${GREEN}Program sonlandırılıyor. İyi günler!${NC}"
                    exit 0
                    ;;
            esac
            ;;
        *)
            echo "Ana menüye dönülüyor..."
            sleep 2
            select_operation_type
            ;;
    esac
}

# Çıkarma işlemi
function extract_operation {
    local archive_path
    local extract_dir

    # Arşiv dosyasını sor
    echo
    echo -e "${YELLOW}1. Çıkarmak istediğiniz arşiv dosyasının yolunu girin:${NC}"
    read -p "Arşiv dosyası: " archive_path

    # Dosya kontrolü
    if [ ! -f "$archive_path" ]; then
        echo -e "${RED}Hata: '$archive_path' bulunamadı veya bir dosya değil.${NC}"
        echo -e "${YELLOW}Tekrar denemek ister misiniz? (e/h)${NC}"
        local retry
        read -p "Seçiminiz (e/h): " retry
        case $retry in
            e|E)
                extract_operation
                return
                ;;
            *)
                select_operation_type
                return
                ;;
        esac
    fi

    # Arşiv formatını otomatik tespit et
    local detected_format
    if [[ "$archive_path" == *.zip ]]; then
        detected_format="zip"
    elif [[ "$archive_path" == *.tar ]]; then
        detected_format="tar"
    elif [[ "$archive_path" == *.tar.gz || "$archive_path" == *.tgz ]]; then
        detected_format="targz"
    elif [[ "$archive_path" == *.tar.bz2 || "$archive_path" == *.tbz2 ]]; then
        detected_format="tarbz2"
    elif [[ "$archive_path" == *.tar.xz ]]; then
        detected_format="tarxz"
    elif [[ "$archive_path" == *.7z ]]; then
        detected_format="7z"
    else
        echo -e "${RED}Hata: Desteklenmeyen arşiv formatı. Betik zip, tar, tar.gz, tar.bz2, tar.xz ve 7z formatlarını destekler.${NC}"
        echo "Ana menüye dönülüyor..."
        sleep 2
        select_operation_type
        return
    fi

    # Çıkarma dizinini sor
    echo
    echo -e "${YELLOW}2. Arşivin çıkarılacağı dizini girin:${NC}"
    echo -e "${BLUE}Not: Boş bırakırsanız arşivin bulunduğu dizin kullanılacaktır.${NC}"
    read -p "Çıkarma dizini: " extract_dir

    # Çıkarma dizini boş ise arşivin bulunduğu dizini kullan
    if [ -z "$extract_dir" ]; then
        extract_dir="$(dirname "$archive_path")"
        echo -e "${BLUE}Arşivin bulunduğu dizin kullanılacak: $extract_dir${NC}"
    else
        # Dizin yoksa oluştur
        if [ ! -d "$extract_dir" ]; then
            echo -e "${YELLOW}Dizin '$extract_dir' mevcut değil. Oluşturulsun mu? (e/h)${NC}"
            local create_dir
            read -p "Seçiminiz (e/h): " create_dir
            case $create_dir in
                e|E)
                    mkdir -p "$extract_dir"
                    if [ $? -ne 0 ]; then
                        echo -e "${RED}Hata: Çıkarma dizini '$extract_dir' oluşturulamadı.${NC}"
                        echo "Ana menüye dönülüyor..."
                        sleep 2
                        select_operation_type
                        return
                    fi
                    echo -e "${GREEN}Dizin başarıyla oluşturuldu.${NC}"
                    ;;
                *)
                    echo "Ana menüye dönülüyor..."
                    sleep 2
                    select_operation_type
                    return
                    ;;
            esac
        fi
    fi

    # İzinleri koruma seçeneğini sor
    echo
    echo -e "${YELLOW}3. İzinleri ve sahiplik bilgilerini korumak istiyor musunuz?${NC}"
    echo -e "${BLUE}Not: İzinlerin korunması, dosya/klasörlerin orijinal izinlerinin ve sahiplik bilgilerinin aynen kalmasını sağlar.${NC}"
    echo -e "${BLUE}Bu seçenek özellikle sistem dosyalarının geri yüklenmesi için önemlidir.${NC}"

    local preserve_permissions
    read -p "İzinleri koru? (e/h, varsayılan: e): " preserve_permissions

    case $preserve_permissions in
        h|H|n|N)
            preserve_permissions="hayır"
            ;;
        *)
            preserve_permissions="evet"
            ;;
    esac

    # Özet bilgileri göster ve onay al
    clear
    echo -e "${GREEN}=== İşlem Özeti ===${NC}"
    echo -e "${BLUE}Arşiv Dosyası:${NC} $archive_path"
    echo -e "${BLUE}Tespit Edilen Format:${NC} $detected_format"
    echo -e "${BLUE}Çıkarma Dizini:${NC} $extract_dir"
    echo -e "${BLUE}İzinleri Koru:${NC} $preserve_permissions"
    echo

    # Arşiv boyutunu ve içeriğini göster
    local archive_size=$(du -h "$archive_path" | cut -f1)
    echo -e "${BLUE}Arşiv Boyutu:${NC} $archive_size"

    echo -e "${YELLOW}Bu ayarlarla çıkarma işlemini başlatmak istiyor musunuz? (e/h)${NC}"
    local confirm
    read -p "Onaylıyor musunuz? (e/h): " confirm

    case $confirm in
        e|E)
            # Arşivi çıkart
            echo -e "${MAGENTA}Çıkarma işlemi başlatılıyor...${NC}"
            extract_archive "$detected_format" "$archive_path" "$extract_dir" "$preserve_permissions"

            echo
            echo -e "${YELLOW}Ana menüye dönmek ister misiniz? (e/h)${NC}"
            local return_main
            read -p "Seçiminiz (e/h): " return_main

            case $return_main in
                e|E)
                    select_operation_type
                    ;;
                *)
                    echo -e "${GREEN}Program sonlandırılıyor. İyi günler!${NC}"
                    exit 0
                    ;;
            esac
            ;;
        *)
            echo "Ana menüye dönülüyor..."
            sleep 2
            select_operation_type
            ;;
    esac
}

# Gerekli paketleri kontrol et ve yükle
function check_install_package {
    local package=$1
    if ! command -v "$package" &> /dev/null; then
        echo -e "${YELLOW}Uyarı: $package komutu bulunamadı. Yüklemeye çalışılıyor...${NC}"
        sudo apt-get update && sudo apt-get install -y "$package"
        if [ $? -ne 0 ]; then
            echo -e "${RED}Hata: $package yüklenemedi. Lütfen 'sudo apt-get install $package' komutu ile manuel olarak yükleyin.${NC}"
            exit 5
        fi
    fi
}

# Ana arşivleme fonksiyonu
function create_archive {
    local format=$1
    local source=$2
    local dest=$3
    local level=$4
    local timestamp=$5
    local source_name=$6

    case "$format" in
        zip)
            check_install_package "zip"
            ARCHIVE_PATH="${dest}/${source_name}_yedek_${timestamp}.zip"
            echo -e "${CYAN}$level seviyesinde ZIP arşivi oluşturuluyor (tüm izinler korunacak)...${NC}"
            cd "$(dirname "$source")" || exit 6
            # -r: recursive, -p: izinleri koru, -{level}: sıkıştırma seviyesi
            zip -r -p "-${level}" "$ARCHIVE_PATH" "$(basename "$source")"
            verify_command="zip -T"
            ;;
        tar)
            check_install_package "tar"
            ARCHIVE_PATH="${dest}/${source_name}_yedek_${timestamp}.tar"
            echo -e "${CYAN}TAR arşivi oluşturuluyor (tüm izinler korunacak)...${NC}"
            # -p: izinleri koru, --preserve-permissions: izinleri koru, --same-owner: sahipliği koru
            tar --preserve-permissions --same-owner -cf "$ARCHIVE_PATH" -C "$(dirname "$source")" "$(basename "$source")"
            verify_command="tar -tf"
            ;;
        targz)
            check_install_package "tar"
            ARCHIVE_PATH="${dest}/${source_name}_yedek_${timestamp}.tar.gz"
            echo -e "${CYAN}$level seviyesinde TAR.GZ arşivi oluşturuluyor (tüm izinler korunacak)...${NC}"
            # -p: izinleri koru, --preserve-permissions: izinleri koru, --same-owner: sahipliği koru
            GZIP="-$level" tar --preserve-permissions --same-owner -czf "$ARCHIVE_PATH" -C "$(dirname "$source")" "$(basename "$source")"
            verify_command="tar -tzf"
            ;;
        tarbz2)
            check_install_package "tar"
            check_install_package "bzip2"
            ARCHIVE_PATH="${dest}/${source_name}_yedek_${timestamp}.tar.bz2"
            echo -e "${CYAN}$level seviyesinde TAR.BZ2 arşivi oluşturuluyor (tüm izinler korunacak)...${NC}"
            # -p: izinleri koru, --preserve-permissions: izinleri koru, --same-owner: sahipliği koru
            BZIP2="-$level" tar --preserve-permissions --same-owner -cjf "$ARCHIVE_PATH" -C "$(dirname "$source")" "$(basename "$source")"
            verify_command="tar -tjf"
            ;;
        tarxz)
            check_install_package "tar"
            check_install_package "xz-utils"
            ARCHIVE_PATH="${dest}/${source_name}_yedek_${timestamp}.tar.xz"
            echo -e "${CYAN}$level seviyesinde TAR.XZ arşivi oluşturuluyor (tüm izinler korunacak)...${NC}"
            # -p: izinleri koru, --preserve-permissions: izinleri koru, --same-owner: sahipliği koru
            XZ_OPT="-${level}" tar --preserve-permissions --same-owner -cJf "$ARCHIVE_PATH" -C "$(dirname "$source")" "$(basename "$source")"
            verify_command="tar -tJf"
            ;;
        7z)
            check_install_package "p7zip-full"
            ARCHIVE_PATH="${dest}/${source_name}_yedek_${timestamp}.7z"
            echo -e "${CYAN}$level seviyesinde 7Z arşivi oluşturuluyor...${NC}"
            # 7z için özel izin koruma parametreleri
            7z a -mx="$level" -ssw -snl "$ARCHIVE_PATH" "$source"
            verify_command="7z t"
            ;;
        *)
            echo -e "${RED}Hata: '$format' desteklenmeyen bir arşiv formatı.${NC}"
            echo -e "${YELLOW}Desteklenen formatlar: zip, tar, targz, tarbz2, tarxz, 7z${NC}"
            exit 7
            ;;
    esac

    # Arşiv başarıyla oluşturuldu mu kontrol et
    if [ $? -eq 0 ]; then
        ARCHIVE_SIZE=$(du -h "$ARCHIVE_PATH" | cut -f1)
        echo -e "${GREEN}Yedekleme başarıyla tamamlandı!${NC}"
        echo -e "Yedek kaydedildi: ${ARCHIVE_PATH}"
        echo -e "Yedek boyutu: ${ARCHIVE_SIZE}"

        # Arşivin bütünlüğünü doğrula
        echo -e "${YELLOW}Arşiv bütünlüğü doğrulanıyor...${NC}"
        $verify_command "$ARCHIVE_PATH" > /dev/null

        if [ $? -eq 0 ]; then
            echo -e "${GREEN}Arşiv başarıyla doğrulandı!${NC}"
        else
            echo -e "${RED}Uyarı: Arşiv doğrulama başarısız oldu. Yedek bozulmuş olabilir.${NC}"
            exit 8
        fi
    else
        echo -e "${RED}Hata: Yedekleme başarısız oldu. İzinleri ve kullanılabilir disk alanını kontrol edin.${NC}"
        exit 9
    fi

    return 0
}

# Arşiv çıkarma fonksiyonu
function extract_archive {
    local format=$1
    local archive_path=$2
    local extract_dir=$3
    local preserve_perms=$4
    local extract_status=0

    echo -e "${CYAN}Arşiv çıkarılıyor: $archive_path -> $extract_dir${NC}"

    case "$format" in
        zip)
            check_install_package "unzip"
            if [ "$preserve_perms" = "evet" ]; then
                echo -e "${CYAN}İzinleri koruyarak ZIP arşivi çıkarılıyor...${NC}"
                unzip -p "$archive_path" -d "$extract_dir"
                extract_status=$?
            else
                echo -e "${CYAN}ZIP arşivi çıkarılıyor...${NC}"
                unzip "$archive_path" -d "$extract_dir"
                extract_status=$?
            fi
            ;;
        tar)
            check_install_package "tar"
            if [ "$preserve_perms" = "evet" ]; then
                echo -e "${CYAN}İzinleri koruyarak TAR arşivi çıkarılıyor...${NC}"
                tar --preserve-permissions --same-owner -xf "$archive_path" -C "$extract_dir"
                extract_status=$?
            else
                echo -e "${CYAN}TAR arşivi çıkarılıyor...${NC}"
                tar -xf "$archive_path" -C "$extract_dir"
                extract_status=$?
            fi
            ;;
        targz)
            check_install_package "tar"
            if [ "$preserve_perms" = "evet" ]; then
                echo -e "${CYAN}İzinleri koruyarak TAR.GZ arşivi çıkarılıyor...${NC}"
                tar --preserve-permissions --same-owner -xzf "$archive_path" -C "$extract_dir"
                extract_status=$?
            else
                echo -e "${CYAN}TAR.GZ arşivi çıkarılıyor...${NC}"
                tar -xzf "$archive_path" -C "$extract_dir"
                extract_status=$?
            fi
            ;;
        tarbz2)
            check_install_package "tar"
            check_install_package "bzip2"
            if [ "$preserve_perms" = "evet" ]; then
                echo -e "${CYAN}İzinleri koruyarak TAR.BZ2 arşivi çıkarılıyor...${NC}"
                tar --preserve-permissions --same-owner -xjf "$archive_path" -C "$extract_dir"
                extract_status=$?
            else
                echo -e "${CYAN}TAR.BZ2 arşivi çıkarılıyor...${NC}"
                tar -xjf "$archive_path" -C "$extract_dir"
                extract_status=$?
            fi
            ;;
        tarxz)
            check_install_package "tar"
            check_install_package "xz-utils"
            if [ "$preserve_perms" = "evet" ]; then
                echo -e "${CYAN}İzinleri koruyarak TAR.XZ arşivi çıkarılıyor...${NC}"
                tar --preserve-permissions --same-owner -xJf "$archive_path" -C "$extract_dir"
                extract_status=$?
            else
                echo -e "${CYAN}TAR.XZ arşivi çıkarılıyor...${NC}"
                tar -xJf "$archive_path" -C "$extract_dir"
                extract_status=$?
            fi
            ;;
        7z)
            check_install_package "p7zip-full"
            if [ "$preserve_perms" = "evet" ]; then
                echo -e "${CYAN}İzinleri koruyarak 7Z arşivi çıkarılıyor...${NC}"
                7z x -snl "$archive_path" -o"$extract_dir"
                extract_status=$?
            else
                echo -e "${CYAN}7Z arşivi çıkarılıyor...${NC}"
                7z x "$archive_path" -o"$extract_dir"
                extract_status=$?
            fi
            ;;
        *)
            echo -e "${RED}Hata: '$format' desteklenmeyen bir arşiv formatı.${NC}"
            return 1
            ;;
    esac

    # Çıkarma başarılı mı kontrol et
    if [ $extract_status -eq 0 ]; then
        echo -e "${GREEN}Arşiv başarıyla çıkarıldı!${NC}"
        echo -e "Çıkarma konumu: ${extract_dir}"

        # Çıkarılan dosyaların sayısını göster
        case "$format" in
            zip)
                local file_count=$(unzip -l "$archive_path" | tail -1 | awk '{print $2}')
                echo -e "Toplam dosya sayısı: ${file_count}"
                ;;
            tar|targz|tarbz2|tarxz)
                local file_count=$(tar -tf "$archive_path" | wc -l)
                echo -e "Toplam dosya/klasör sayısı: ${file_count}"
                ;;
            7z)
                local file_count=$(7z l "$archive_path" | grep -A 2 "^-------------------" | tail -1 | awk '{print $5}')
                echo -e "Toplam dosya/klasör sayısı: ${file_count}"
                ;;
        esac
    else
        echo -e "${RED}Hata: Arşiv çıkarma işlemi başarısız oldu.${NC}"
        echo -e "${YELLOW}Olası nedenler:${NC}"
        echo -e "- Hedef dizinde yeterli boş alan olmayabilir."
        echo -e "- Arşiv dosyası bozulmuş olabilir."
        echo -e "- Gerekli izinler olmayabilir. Root izinleri gerektiren dosyalar için sudo kullanın."
        return 1
    fi

    return 0
}

# Programı çalıştır
select_operation_type