<?php
/*-----------------------------------------------*/
/*  EXTHEM.ES
/*  PREMIUM WORDRESS THEMES
/*
/*  STOP DON'T TRY EDIT
/*  IF YOU DON'T KNOW PHP 
/*
/*  As Errors In Your Themes
/*  Are Not The Responsibility
/*  Of The DEVELOPERS
/*  @EXTHEM.ES
/*  
/*  Follow Social Media Exthem.es
/*  Youtube : https://www.youtube.com/channel/UCpcZNXk6ySLtwRSBN6fVyLA
/*  Facebook : https://www.facebook.com/groups/exthem.es
/*  Twitter : https://x.com/bangreyblog
/*  Instagram : https://www.instagram.com/exthem.es/
/*  Telegram : https://t.me/exthemes_helps
/*  TikTok : https://www.tiktok.com/@exthemes
/*	More Premium Themes Visit Now On https://exthem.es/
/*-----------------------------------------------*/
if ( ! defined( 'ABSPATH' ) ) exit; 
// Silence is golden.
global $opt_themes;

if (!function_exists('RandomAlphaNumeric')) {
	function RandomAlphaNumeric(int $length = 10) 
	{
		$characters 	= '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
		$randomString 	= '';
		$max 			= strlen($characters) - 1;
		for ($i = 0; $i < $length; $i++) 
		{
			$randomString .= $characters[mt_rand(0, $max)];
		}
		return $randomString;
	}
} 

if (!function_exists('upload_images_to_wp')) {
    function upload_images_to_wp($image_url, $format = 'png', $name = 'thumbnail'  )
    {
        if (!empty($image_url)) {
            $upload_dir 		= wp_upload_dir();			
            $image_full_name 	= "{$name}." . $format;
            $image_path 		= $upload_dir["path"] . "/" . $image_full_name;
            $fetch_image 		= file_get_contents($image_url);
            $existing_attachment_id = attachment_url_to_postid($upload_dir["url"] . "/" . $image_full_name);

            if ($existing_attachment_id) {
                return $existing_attachment_id;
            } else {
                file_put_contents($image_path, $fetch_image);
                $file_type = wp_check_filetype(basename($image_full_name), null);
                $image_attachment = [
                    "post_mime_type" => $file_type['type'],
                    "post_title" => $image_name,
                    "post_content" => "",
                    "post_status" => "inherit",
                ];
                $image_id = wp_insert_attachment(
                    $image_attachment,
                    $image_path
                );
				
				//if ( ! function_exists( 'download_url' ) ) {
					require_once ABSPATH . 'wp-admin/includes/file.php';
					require_once ABSPATH . 'wp-admin/includes/media.php';
					require_once ABSPATH . 'wp-admin/includes/image.php';
				//}
	
                //require_once ABSPATH . "wp-admin/includes/image.php";
                $image_data = wp_generate_attachment_metadata(
                    $image_id,
                    $image_path
                );
                wp_update_attachment_metadata($image_id, $image_data);
                return $image_id;
            }
        }
    }
}

/**
 * Validasi file APK (Magic Bytes + MIME)
 */
function validate_apk_file( $file_path ) {
    if ( ! file_exists( $file_path ) ) return false;
    
    // APK Magic Bytes (ZIP header + AndroidManifest.xml signature)
    $handle = fopen( $file_path, 'rb' );
    if ( ! $handle ) return false;
    
    $header = fread( $handle, 22 ); // PK\003\004 + file header
    fclose( $handle );
    
    // Cek ZIP header (APK adalah ZIP)
    if ( substr( $header, 0, 4 ) !== "\x50\x4B\x03\x04" ) {
        return false;
    }
    
    // Cek AndroidManifest.xml signature (posisi ~70 bytes dari awal)
    if ( strpos( $header, 'AndroidManifest.xml' ) !== false || 
         preg_match( '/AndroidManifest\.xml/i', file_get_contents( $file_path, false, null, 0, 500 ) ) ) {
        return true;
    }
    
    // Fallback: cek ekstensi & MIME
    $finfo = finfo_open( FILEINFO_MIME_TYPE );
    $mime = finfo_file( $finfo, $file_path );
    finfo_close( $finfo );
    
    return in_array( $mime, array( 'application/vnd.android.package-archive', 'application/zip' ) );
}

/**
 * Generate APK icon/thumbnail dari file
 */
function generate_apk_thumbnail( $attachment_id, $apk_file ) {
    // Gunakan aapt (Android Asset Packaging Tool) jika tersedia
    $aapt_path = apply_filters( 'apk_aapt_path', '/usr/bin/aapt' );
    if ( file_exists( $aapt_path ) ) {
        $icon_path = sys_get_temp_dir() . '/apk_icon_' . $attachment_id . '.png';
        $cmd = escapeshellcmd( "{$aapt_path} d badging {$apk_file} | grep icon" );
        exec( $cmd, $output );
        // Extract icon menggunakan library ZIP atau exec unzip
        // ... (implementasi detail)
    } else {
        // Fallback: generic APK icon
        $upload_dir = wp_upload_dir();
        $icon_url = $upload_dir['baseurl'] . '/apk-icon.png'; // Pre-made generic icon
        set_post_thumbnail( $attachment_id, $icon_url );
    }
}


/**
 * Allow APK files in WordPress media library
 */
if (!function_exists('allow_apk_uploads')) {
add_filter( 'upload_mimes', 'allow_apk_uploads' );
	function allow_apk_uploads( $mimes ) 
	{
		$mimes['apk'] = 'application/vnd.android.package-archive';
		return $mimes;
	}
}

if (!function_exists('allow_apk_filetype_and_ext')) {
/**
 * Fix WordPress sometimes blocking APK even when MIME is allowed
 */
add_filter( 'wp_check_filetype_and_ext', 'allow_apk_filetype_and_ext', 10, 4 );
	function allow_apk_filetype_and_ext( $values, $file, $filename, $mimes ) 
	{
		if ( strtolower( pathinfo( $filename, PATHINFO_EXTENSION ) ) === 'apk' ) 
		{
			$values['ext']  = 'apk';
			$values['type'] = 'application/vnd.android.package-archive';
		}
		return $values;
	}
}

/**
 * Allow .ipa files in WordPress
 */

if (!function_exists('allow_ipa_uploads')) {
add_filter( 'upload_mimes', 'allow_ipa_uploads' );
	function allow_ipa_uploads( $mimes ) 
	{
		// Official MIME type for iOS apps
		$mimes['ipa'] = 'application/octet-stream';
		// Some servers/CDNs serve IPA as these types too – accept them all
		$mimes['ipa'] = 'application/iphone';
		$mimes['ipa'] = 'application/x-itunes-ipa';
		return $mimes;
	}
}

if (!function_exists('fix_ipa_filetype')) {
/**
 * Force WordPress to recognize .ipa even if MIME sniff fails
 */
add_filter( 'wp_check_filetype_and_ext', 'fix_ipa_filetype', 99, 4 );
	function fix_ipa_filetype( $data, $file, $filename, $mimes ) 
	{
		$ext = strtolower( pathinfo( $filename, PATHINFO_EXTENSION ) );

		if ( $ext === 'ipa' ) 
		{
			$data['ext']  = 'ipa';
			$data['type'] = 'application/octet-stream';
			$data['proper_filename'] = $filename;
		}

		return $data;
	}
}
 
/**
 * upload_remote_file_apk() - VERSI FINAL & AMAN
 * Upload remote APK/XAPK/ZIP ke Media Library WordPress
 * Menggunakan download_url() + wp_handle_sideload() (cara resmi WP)
 *
 * @param string $file_url       URL file eksternal
 * @param int    $parent_post_id Optional: Post ID parent
 * @return int|WP_Error          Attachment ID atau WP_Error
 */
function upload_remote_file_apk( $file_url, $parent_post_id = 0 ) {

    // Load WP media functions jika belum ada
    if ( ! function_exists( 'wp_generate_attachment_metadata' ) ) {
        require_once ABSPATH . 'wp-admin/includes/file.php';
        require_once ABSPATH . 'wp-admin/includes/media.php';
        require_once ABSPATH . 'wp-admin/includes/image.php';
    }

    $file_url = trim( $file_url );

    // Validasi URL
    if ( empty( $file_url ) || ! filter_var( $file_url, FILTER_VALIDATE_URL ) ) {
        return new WP_Error( 'invalid_url', 'URL file tidak valid.' );
    }

    // === Deduplication: cek apakah file dari URL ini sudah pernah di-upload ===
    global $wpdb;
    $existing_id = $wpdb->get_var( $wpdb->prepare(
        "SELECT post_id FROM {$wpdb->postmeta}
         WHERE meta_key = '_remote_file_url'
           AND meta_value = %s
         LIMIT 1",
        $file_url
    ) );

    if ( $existing_id ) {
        return (int) $existing_id;
    }

    // === Download file dengan timeout panjang (untuk APK besar) ===
    $tmp = download_url( $file_url, 3600 ); // 30 menit timeout

    if ( is_wp_error( $tmp ) ) {
        return $tmp; // Error dari download_url (timeout, 404, partial, dll)
    }

    // Cek apakah file kosong atau terlalu kecil (kemungkinan error page)
    if ( filesize( $tmp ) < 1024 ) { // < 1KB
        @unlink( $tmp );
        return new WP_Error( 'invalid_file', 'File terlalu kecil - kemungkinan halaman error.' );
    }

    // === Sanitasi nama file ===
    $original_filename = wp_basename( parse_url( $file_url, PHP_URL_PATH ) );
    $path_info         = pathinfo( $original_filename );
    $ext               = strtolower( $path_info['extension'] ?? '' );

    $clean_filename = sanitize_file_name( $path_info['filename'] ?? 'downloaded-apk' );
    if ( ! empty( $ext ) ) {
        $clean_filename .= '.' . $ext;
    } else {
        $clean_filename .= '.apk'; // Fallback
    }

    // === Tentukan MIME type ===
    $filetype = wp_check_filetype( $tmp );
    $mime     = $filetype['type'];

    // Force MIME benar untuk APK/XAPK
    if ( in_array( $ext, [ 'apk', 'xapk' ] ) ) {
        $mime = 'application/vnd.android.package-archive';
    } elseif ( $ext === 'ipa' ) {
        $mime = 'application/octet-stream';
    } elseif ( $ext === 'zip' ) {
        $mime = 'application/zip';
    }

    // Cek apakah tipe diizinkan
    $allowed_mimes = get_allowed_mime_types();
    if ( ! in_array( $mime, $allowed_mimes, true ) ) {
        @unlink( $tmp );
        return new WP_Error( 'invalid_type', "Tipe file tidak diizinkan: {$mime}" );
    }

    // Optional: batas ukuran (sesuaikan dengan hosting)
    $max_size = 1000 * MB_IN_BYTES; // 1GB
    if ( filesize( $tmp ) > $max_size ) {
        @unlink( $tmp );
        return new WP_Error( 'file_too_large', 'File melebihi batas ukuran (1GB).' );
    }

    // === Siapkan array untuk sideload ===
    $file_array = [
        'name'     => $clean_filename,
        'type'     => $mime,
        'tmp_name' => $tmp,
        'error'    => 0,
        'size'     => filesize( $tmp ),
    ];

    // === Handle sideload ===
    $overrides = [
        'test_form' => false,
        'test_size' => true,
    ];

    $results = wp_handle_sideload( $file_array, $overrides );

    if ( isset( $results['error'] ) ) {
        @unlink( $tmp );
        return new WP_Error( 'sideload_failed', $results['error'] );
    }

    $filename = $results['file']; // Path di server
    $url      = $results['url'];   // URL publik

    // === Insert attachment ===
    $attachment = [
        'guid'           => $url,
        'post_mime_type' => $results['type'],
        'post_title'     => preg_replace( '/\.[^.]+$/', '', $clean_filename ),
        'post_content'   => '',
        'post_status'    => 'inherit',
        'post_parent'    => (int) $parent_post_id,
    ];

    $attach_id = wp_insert_attachment( $attachment, $filename, (int) $parent_post_id );

    if ( is_wp_error( $attach_id ) ) {
        @unlink( $filename );
        return $attach_id;
    }

    // Generate metadata
    $attach_data = wp_generate_attachment_metadata( $attach_id, $filename );
    wp_update_attachment_metadata( $attach_id, $attach_data );

    // Simpan URL sumber untuk deduplication
    update_post_meta( $attach_id, '_remote_file_url', $file_url );
    update_post_meta( $attach_id, '_original_filename', $original_filename );
    update_post_meta( $attach_id, '_file_size_bytes', filesize( $filename ) );

    return $attach_id; // SUKSES!
}

if (!function_exists('upload_remote_file_apk_asli')) {
/**
 * Upload a remote file to the WordPress media library by URL.
 *
 * @param string $file_url     Full URL of the remote file (e.g. https://example.com/image.jpg)
 * @param int    $parent_post_id Optional. Post ID to attach the media to.
 * @return int|WP_Error        Attachment ID on success, WP_Error on failure.
 */
	function upload_remote_file_apk_asli( $file_url, $parent_post_id = 0 ) 
	{

		// 1. Load WordPress core files (only needed if called outside WP context)
		if ( ! function_exists( 'wp_generate_attachment_metadata' ) ) 
		{
			require_once( ABSPATH . 'wp-admin/includes/file.php' );
			require_once( ABSPATH . 'wp-admin/includes/media.php' );
			require_once( ABSPATH . 'wp-admin/includes/image.php' );
		}
		
		// 1. Check by remote URL stored in postmeta (fastest)
		global $wpdb;
		$existing_id = $wpdb->get_var( $wpdb->prepare(
			"SELECT post_id FROM $wpdb->postmeta 
			 WHERE meta_key = '_remote_file_url' 
			 AND meta_value = %s 
			 LIMIT 1",
			$file_url
		) );

		if ( $existing_id ) {
			//if ( is_callable( $progress_callback ) ) {
			//    call_user_func( $progress_callback, 1, 1, 'already_exists' );
			//}
			return (int) $existing_id; // Already uploaded → return ID immediately
		}
		
		// 2. Validate URL
		if ( ! filter_var( $file_url, FILTER_VALIDATE_URL ) ) {
			return new WP_Error( 'invalid_url', 'Invalid file URL.' );
		}

		// 3. Download file to temp directory
		$tmp = download_url( $file_url );
		if ( is_wp_error( $tmp ) ) {
			return $tmp; // contains download error
		}

		// 4. Security checks (MODIFIED)
		$file_array = array(
			'name'     => wp_basename( parse_url( $file_url, PHP_URL_PATH ) ),
			'type'     => wp_check_filetype( $tmp )['type'],
			'tmp_name' => $tmp,
			'error'    => 0,
			'size'     => filesize( $tmp ),
		);

		// Force APK if extension is .apk (in case wp_check_filetype fails)
		// Force correct MIME if extension is .ipa or .apk
		$ext = strtolower( pathinfo( $file_array['name'], PATHINFO_EXTENSION ) );
		if ( $ext === 'ipa' ) {
			$file_array['type'] = 'application/octet-stream';
		} elseif ( $ext === 'apk' ) {
			$file_array['type'] = 'application/vnd.android.package-archive';
		}

		$allowed = get_allowed_mime_types();
		if ( empty( $file_array['type'] ) || ! in_array( $file_array['type'], $allowed, true ) ) {
			@unlink( $tmp );
			return new WP_Error( 'invalid_type', 'File type not allowed: ' . $file_array['type'] );
		}

		// Optional: max size (5 MB)
		//if ( $file_array['size'] > 5 * MB_IN_BYTES ) {
		//    @unlink( $tmp );
		//    return new WP_Error( 'file_too_large', 'File exceeds 5 MB.' );
		//}

		// 5. Handle the upload (sideloading)
		$overrides = array( 'test_form' => false );
		$results   = wp_handle_sideload( $file_array, $overrides );

		if ( isset( $results['error'] ) ) {
			@unlink( $tmp );
			return new WP_Error( 'sideload_failed', $results['error'] );
		}

		$filename = $results['file'];   // Full server path
		$url      = $results['url'];    // Public URL

		// 6. Prepare attachment data
		$attachment = array(
			'post_mime_type' => $results['type'],
			'post_title'     => preg_replace( '/\.[^.]+$/', '', wp_basename( $filename ) ),
			'post_content'   => '',
			'post_status'    => 'inherit',
			'post_parent'    => (int) $parent_post_id,
		);

		// 7. Insert attachment
		$attach_id = wp_insert_attachment( $attachment, $filename, (int) $parent_post_id );
		if ( is_wp_error( $attach_id ) ) {
			@unlink( $filename );
			return $attach_id;
		}

		// 8. Generate metadata & thumbnails
		$attach_data = wp_generate_attachment_metadata( $attach_id, $filename );
		wp_update_attachment_metadata( $attach_id, $attach_data );

		return $attach_id; // Success!
	}
}

function upload_remote_file_apk11( $file_url, $parent_post_id = 0 ) {

    if ( ! function_exists( 'wp_generate_attachment_metadata' ) ) {
        require_once ABSPATH . 'wp-admin/includes/file.php';
        require_once ABSPATH . 'wp-admin/includes/media.php';
        require_once ABSPATH . 'wp-admin/includes/image.php';
    }

    $file_url = trim( $file_url );
    if ( empty( $file_url ) || ! filter_var( $file_url, FILTER_VALIDATE_URL ) ) {
        return new WP_Error( 'invalid_url', 'URL tidak valid.' );
    }

    // Deduplication
    global $wpdb;
    $existing_id = $wpdb->get_var( $wpdb->prepare(
        "SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = '_remote_file_url' AND meta_value = %s LIMIT 1",
        $file_url
    ) );
    if ( $existing_id ) {
        return (int) $existing_id;
    }

    // Temporary file
    $tmp = wp_tempnam( 'apk' );
    if ( ! $tmp ) {
        return new WP_Error( 'temp_error', 'Gagal buat temp file.' );
    }

    $fp = fopen( $tmp, 'wb' );
    if ( ! $fp ) {
        @unlink( $tmp );
        return new WP_Error( 'file_open', 'Gagal buka temp file.' );
    }

    // === HEAD request dulu untuk ambil Content-Length ===
    $ch_head = curl_init();
    curl_setopt_array( $ch_head, [
        CURLOPT_URL            => $file_url,
        CURLOPT_NOBODY         => true,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => 60,
        CURLOPT_USERAGENT      => 'WordPress APK Importer',
    ]);
    curl_exec( $ch_head );
    $expected_size = curl_getinfo( $ch_head, CURLINFO_CONTENT_LENGTH_DOWNLOAD );
    curl_close( $ch_head );

    // === Download dengan resume + chunk verification ===
    $downloaded_bytes = 0;
    $ch = curl_init();
    curl_setopt_array( $ch, [
        CURLOPT_URL            => $file_url,
        CURLOPT_FILE           => $fp,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_TIMEOUT        => 3600,  // 1 jam max
        CURLOPT_CONNECTTIMEOUT => 60,
        CURLOPT_USERAGENT      => 'Mozilla/5.0 (WordPress APK Downloader)',
        CURLOPT_SSL_VERIFYPEER => true,
        CURLOPT_RESUME_FROM    => $downloaded_bytes,
        CURLOPT_NOPROGRESS     => false,
        CURLOPT_PROGRESSFUNCTION => function( $resource, $download_size, $downloaded, $upload_size, $uploaded ) use ( &$downloaded_bytes ) {
            $downloaded_bytes = $downloaded;
        },
    ]);

    $success = curl_exec( $ch );
    $curl_error = curl_error( $ch );
    $http_code  = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
    $final_downloaded = curl_getinfo( $ch, CURLINFO_SIZE_DOWNLOAD );

    curl_close( $ch );
    fclose( $fp );

    // === Verifikasi kelengkapan file ===
    if ( ! $success || $http_code !== 200 ) {
        @unlink( $tmp );
        return new WP_Error( 'download_failed', "cURL error: {$curl_error} (HTTP {$http_code})" );
    }

    // Jika server kasih Content-Length, cek apakah cocok
    if ( $expected_size > 0 && $final_downloaded < $expected_size ) {
        @unlink( $tmp );
        return new WP_Error( 'partial_file', "File tidak lengkap: missing " . ($expected_size - $final_downloaded) . " bytes" );
    }

    // Cek ukuran minimal (hindari halaman error)
    if ( filesize( $tmp ) < 100 * 1024 ) { // < 100KB
        @unlink( $tmp );
        return new WP_Error( 'invalid_file', 'File terlalu kecil - kemungkinan error page.' );
    }

    // === Proses sideload (sama seperti sebelumnya) ===
    $original_name = wp_basename( parse_url( $file_url, PHP_URL_PATH ) );
    $path_info     = pathinfo( $original_name );
    $ext           = strtolower( $path_info['extension'] ?? '' );

    $clean_name = sanitize_file_name( $path_info['filename'] ?? 'apk-download' );
    $clean_name .= $ext ? '.' . $ext : '.apk';

     


    // Force MIME type benar
    if ( in_array( $ext, array( 'apk', 'xapk' ) ) ) {
        $mime_type = 'application/vnd.android.package-archive';
    } elseif ( $ext === 'ipa' ) {
        $mime_type = 'application/octet-stream';
    } elseif ( $ext === 'zip' ) {
        $mime_type = 'application/zip';
    } else {
        $mime_type = wp_check_filetype( $tmp )['type'] ?: 'application/octet-stream';
    }
	
    $allowed = get_allowed_mime_types();
    if ( ! in_array( $mime_type, $allowed, true ) ) {
        @unlink( $tmp );
        return new WP_Error( 'invalid_type', 'Tipe file tidak diizinkan.' );
    }

    $file_array = [
        'name'     => $clean_name,
        'type'     => $mime_type,
        'tmp_name' => $tmp,
        'error'    => 0,
        'size'     => filesize( $tmp ),
    ];

    $overrides = [ 'test_form' => false ];
    $results   = wp_handle_sideload( $file_array, $overrides );

    if ( isset( $results['error'] ) ) {
        @unlink( $tmp );
        return new WP_Error( 'sideload_error', $results['error'] );
    }

    $attachment = [
        'guid'           => $results['url'],
        'post_mime_type' => $results['type'],
        'post_title'     => preg_replace( '/\.[^.]+$/', '', $clean_name ),
        'post_content'   => '',
        'post_status'    => 'inherit',
        'post_parent'    => (int) $parent_post_id,
    ];

    $attach_id = wp_insert_attachment( $attachment, $results['file'], (int) $parent_post_id );
    if ( is_wp_error( $attach_id ) ) {
        @unlink( $results['file'] );
        return $attach_id;
    }

    $attach_data = wp_generate_attachment_metadata( $attach_id, $results['file'] );
    wp_update_attachment_metadata( $attach_id, $attach_data );

    // Simpan info
    update_post_meta( $attach_id, '_remote_file_url', $file_url );
    update_post_meta( $attach_id, '_original_filename', $original_name );
    update_post_meta( $attach_id, '_file_size_bytes', filesize( $results['file'] ) );

    return $attach_id;
}

function upload_remote_file_apk112( $file_url, $parent_post_id = 0 ) {

    // Load WordPress media functions jika belum ada
    if ( ! function_exists( 'wp_generate_attachment_metadata' ) ) {
        require_once ABSPATH . 'wp-admin/includes/file.php';
        require_once ABSPATH . 'wp-admin/includes/media.php';
        require_once ABSPATH . 'wp-admin/includes/image.php';
    }

    // Sanitasi & validasi URL
    $file_url = trim( $file_url );
    if ( empty( $file_url ) || ! filter_var( $file_url, FILTER_VALIDATE_URL ) ) {
        return new WP_Error( 'invalid_url', 'URL file tidak valid.' );
    }

    // === 1. Deduplication: cek apakah sudah pernah di-upload ===
    global $wpdb;
    $existing_id = $wpdb->get_var( $wpdb->prepare(
        "SELECT post_id FROM {$wpdb->postmeta}
         WHERE meta_key = '_remote_file_url'
           AND meta_value = %s
         LIMIT 1",
        $file_url
    ) );

    if ( $existing_id ) {
        return (int) $existing_id;
    }

    // === 2. Buat temporary file ===
    $tmp = wp_tempnam( 'apk_download' );
    if ( ! $tmp ) {
        return new WP_Error( 'temp_file', 'Gagal membuat file sementara.' );
    }

    // === 3. Download dengan cURL + Resume Support (FIX Error 18) ===
    $fp = fopen( $tmp, 'w+' );
    if ( ! $fp ) {
        return new WP_Error( 'file_open', 'Gagal membuka file sementara.' );
    }

    $ch = curl_init();
    curl_setopt_array( $ch, array(
        CURLOPT_URL            => $file_url,
        CURLOPT_FILE           => $fp,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_TIMEOUT        => 1800,        // 30 menit max (untuk file 1GB+)
        CURLOPT_CONNECTTIMEOUT => 60,
        CURLOPT_USERAGENT      => 'Mozilla/5.0 (WordPress APK Importer/1.0)',
        CURLOPT_SSL_VERIFYPEER => true,
        CURLOPT_SSL_VERIFYHOST => 2,
        CURLOPT_HEADER         => false,
        CURLOPT_NOPROGRESS     => false,
        // Penting: resume jika putus
        CURLOPT_RESUME_FROM    => 0,
    ) );

    $success = curl_exec( $ch );
    $curl_error = curl_error( $ch );
    $http_code  = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
    $downloaded = curl_getinfo( $ch, CURLINFO_SIZE_DOWNLOAD );

    curl_close( $ch );
    fclose( $fp );

    if ( ! $success || $http_code !== 200 ) {
        @unlink( $tmp );
        return new WP_Error( 'download_failed', "Download gagal: {$curl_error} (HTTP {$http_code})" );
    }

    // Cek apakah file kosong atau terlalu kecil
    if ( filesize( $tmp ) < 1024 ) { // < 1KB → kemungkinan error page
        @unlink( $tmp );
        return new WP_Error( 'partial_file', 'File terdeteksi tidak lengkap atau error page.' );
    }

    // === 4. Sanitasi nama file & MIME type ===
    $original_name = wp_basename( parse_url( $file_url, PHP_URL_PATH ) );
    $path_info     = pathinfo( $original_name );
    $ext           = strtolower( $path_info['extension'] ?? '' );

    $clean_name = sanitize_file_name( $path_info['filename'] ?? 'apk-file' );
    $clean_name .= $ext ? '.' . $ext : '.apk';

	/* $ext = strtolower( pathinfo( $file_array['name'], PATHINFO_EXTENSION ) );
	if ( $ext === 'ipa' ) {
		$file_array['type'] = 'application/octet-stream';
	} elseif ( $ext === 'apk' ) {
		$file_array['type'] = 'application/vnd.android.package-archive';
	} */
		
    // Force MIME type benar
    if ( in_array( $ext, array( 'apk', 'xapk' ) ) ) {
        $mime_type = 'application/vnd.android.package-archive';
    } elseif ( $ext === 'ipa' ) {
        $mime_type = 'application/octet-stream';
    } elseif ( $ext === 'zip' ) {
        $mime_type = 'application/zip';
    } else {
        $mime_type = wp_check_filetype( $tmp )['type'] ?: 'application/octet-stream';
    }

    // Cek allowed MIME
    $allowed = get_allowed_mime_types();
    if ( ! in_array( $mime_type, $allowed, true ) ) {
        @unlink( $tmp );
        return new WP_Error( 'invalid_type', "Tipe file tidak diizinkan: {$mime_type}" );
    }

    // === 5. Sideload file ===
    $file_array = array(
        'name'     => $clean_name,
        'type'     => $mime_type,
        'tmp_name' => $tmp,
        'error'    => 0,
        'size'     => filesize( $tmp ),
    );

    $overrides = array( 'test_form' => false );
    $results   = wp_handle_sideload( $file_array, $overrides );

    if ( isset( $results['error'] ) ) {
        @unlink( $tmp );
        return new WP_Error( 'sideload_failed', $results['error'] );
    }

    $filename = $results['file'];
    $url      = $results['url'];

    // === 6. Insert attachment ===
    $attachment = array(
        'guid'           => $url,
        'post_mime_type' => $results['type'],
        'post_title'     => preg_replace( '/\.[^.]+$/', '', $clean_name ),
        'post_content'   => '',
        'post_status'    => 'inherit',
        'post_parent'    => (int) $parent_post_id,
    );

    $attach_id = wp_insert_attachment( $attachment, $filename, (int) $parent_post_id );

    if ( is_wp_error( $attach_id ) ) {
        @unlink( $filename );
        return $attach_id;
    }

    // === 7. Generate metadata ===
    $attach_data = wp_generate_attachment_metadata( $attach_id, $filename );
    wp_update_attachment_metadata( $attach_id, $attach_data );

    // === 8. Simpan info tambahan ===
    update_post_meta( $attach_id, '_remote_file_url', $file_url );
    update_post_meta( $attach_id, '_original_filename', $original_name );
    update_post_meta( $attach_id, '_file_size_bytes', filesize( $filename ) );

    return $attach_id; // SUCCESS!
}

function upload_remote_file_apk2($url, $args = array()) {
    
    // Default arguments
    $defaults = array(
        'timeout'     => 60,    // Timeout lebih lama untuk APK besar
        'filename'    => '',    // Custom filename
        'force_apk'   => true,  // Selalu tambah .apk extension
    );
    $args = wp_parse_args($args, $defaults);
    
    // Validasi URL
    if (empty($url) || !filter_var($url, FILTER_VALIDATE_URL)) {
        return new WP_Error('invalid_url', 'URL tidak valid');
    }
    
    // Sanitasi URL
    $url = esc_url_raw($url);
    
    // Cek apakah sudah ada attachment dengan URL ini
    $existing = get_posts(array(
        'post_type'   => 'attachment',
        'meta_key'    => '_remote_apk_url',
        'meta_value'  => $url,
        'post_status' => 'inherit',
        'numberposts' => 1,
    ));
    
    if (!empty($existing)) {
        return $existing[0]->ID; // Return existing attachment
    }
    
    // Download file dari URL
    $response = wp_remote_get($url, array(
        'timeout'     => $args['timeout'],
        'stream'      => true,
        'redirection' => 5,
        'user-agent'  => 'Mozilla/5.0 (WordPress APK Importer)',
    ));
    
    if (is_wp_error($response)) {
        return $response;
    }
    
    $code = wp_remote_retrieve_response_code($response);
    if ($code !== 200) {
        return new WP_Error('http_error', 'HTTP Error: ' . $code);
    }
    
    // Ambil file info
    $file_size = wp_remote_retrieve_header($response, 'content-length');
    $content_type = wp_remote_retrieve_header($response, 'content-type');
    
    // Baca file stream
    $upload_dir = wp_upload_dir();
    $temp_file = wp_tempnam(basename($url));
    
    $file_handle = fopen($temp_file, 'w');
    if (!$file_handle) {
        return new WP_Error('file_error', 'Gagal membuat temporary file');
    }
    
    $body = wp_remote_retrieve_body($response);
    fwrite($file_handle, $body);
    fclose($file_handle);
    
    // Cek ukuran file
    if ($file_size && filesize($temp_file) != $file_size) {
        unlink($temp_file);
        return new WP_Error('size_mismatch', 'Ukuran file tidak cocok');
    }
    
    // Tentukan filename
    $filename = $args['filename'];
    if (empty($filename)) {
        $filename = basename(parse_url($url, PHP_URL_PATH));
    }
    
    // Tambah .apk extension jika force_apk aktif
    if ($args['force_apk'] && !preg_match('/\.(apk|xapk|zip)$/i', $filename)) {
        $filename .= '.apk';
    }
    
    // Pindah ke upload directory
    $final_path = $upload_dir['path'] . '/' . $filename;
    
    if (!move_uploaded_file($temp_file, $final_path)) {
        unlink($temp_file);
        return new WP_Error('move_error', 'Gagal memindah file');
    }
    
    // Buat attachment
    $attachment = array(
        'guid'           => $upload_dir['url'] . '/' . $filename,
        'post_mime_type' => 'application/vnd.android.package-archive',
        'post_title'     => preg_replace('/\.[^.]+$/', '', $filename),
        'post_content'   => '',
        'post_status'    => 'inherit',
    );
    
    $attach_id = wp_insert_attachment($attachment, $final_path, $post_id);
    
    if (is_wp_error($attach_id)) {
        unlink($final_path);
        return $attach_id;
    }
    
    // Generate metadata
    require_once(ABSPATH . 'wp-admin/includes/image.php');
    $attach_data = wp_generate_attachment_metadata($attach_id, $final_path);
    wp_update_attachment_metadata($attach_id, $attach_data);
    
    // Simpan info remote URL untuk deduplication
    update_post_meta($attach_id, '_remote_apk_url', $url);
    update_post_meta($attach_id, '_apk_source', $url);
    update_post_meta($attach_id, '_file_size', filesize($final_path));
    
    // Hapus temp file
    unlink($temp_file);
    
    return $attach_id;
}
 
function upload_remote_file_apk3( $apk_url, $options = array() ) {
    
    // Default options
    $defaults = array(
        'timeout'    => 120,      // 2 menit timeout
        'max_size'   => 500 * MB_IN_BYTES, // 500MB max
        'user_id'    => get_current_user_id(),
        'generate_thumbnail' => true,
        'verify_apk' => true,
    );
    $options = wp_parse_args( $options, $defaults );
    
    // Capability check
    if ( ! current_user_can( 'upload_files' ) ) {
        return new WP_Error( 'no_permission', 'You do not have permission to upload files.', 403 );
    }
    
    // Sanitasi & validasi URL
    $apk_url = esc_url_raw( trim( $apk_url ) );
    if ( ! filter_var( $apk_url, FILTER_VALIDATE_URL ) ) {
        return new WP_Error( 'invalid_url', 'Invalid APK URL provided.', 400 );
    }
    
    // Parse URL untuk domain check (opsional blacklist)
    $parsed_url = wp_parse_url( $apk_url );
    $domain = isset( $parsed_url['host'] ) ? strtolower( $parsed_url['host'] ) : '';
    $blacklist = apply_filters( 'apk_upload_blacklist', array( 'suspicious-domain.com' ) );
    if ( in_array( $domain, $blacklist ) ) {
        return new WP_Error( 'blacklisted_domain', 'Upload from this domain is blocked.', 403 );
    }
    
    // Cek cache (hindari upload duplikat)
    $file_hash = md5( $apk_url );
    $cached_attachment = get_transient( "apk_upload_cache_{$file_hash}" );
    if ( $cached_attachment ) {
        return $cached_attachment;
    }
    
    // === DOWNLOAD FILE (Streaming - Memory Efficient) ===
    $response = wp_remote_get( $apk_url, array(
        'timeout'     => $options['timeout'],
        'stream'      => true,
        'filename'    => wp_tempnam(), // Temporary file
        'headers'     => array( 'User-Agent' => 'WordPress-APK-Uploader/1.0' ),
        'redirection' => 5,
        'sslverify'   => true,
    ) );
    
    if ( is_wp_error( $response ) ) {
        return new WP_Error( 
            'download_failed', 
            sprintf( 'Download failed: %s', $response->get_error_message() ), 
            $response->get_error_code()
        );
    }
    
    $status_code = wp_remote_retrieve_response_code( $response );
    if ( 200 !== $status_code ) {
        return new WP_Error( 'http_error', sprintf( 'HTTP Error: %d', $status_code ), $status_code );
    }
    
    // Cek content length
    $content_length = wp_remote_retrieve_header( $response, 'content-length' );
    if ( $content_length && $content_length > $options['max_size'] ) {
        wp_delete_file( wp_remote_retrieve_header( $response, 'filename' ) );
        return new WP_Error( 'file_too_large', sprintf( 'File too large: %s exceeds %s limit.', size_format( $content_length ), size_format( $options['max_size'] ) ), 413 );
    }
    
    $temp_file = wp_remote_retrieve_header( $response, 'filename' );
    if ( ! file_exists( $temp_file ) || ! is_readable( $temp_file ) ) {
        return new WP_Error( 'temp_file_error', 'Temporary file not accessible.', 500 );
    }
    
    // === VALIDASI APK (Magic Bytes + Extension) ===
    if ( $options['verify_apk'] ) {
        $is_valid_apk = validate_apk_file( $temp_file );
        if ( ! $is_valid_apk ) {
            wp_delete_file( $temp_file );
            return new WP_Error( 'invalid_apk', 'File is not a valid APK.', 400 );
        }
    }
    
    // === CEK DUPLIKAT (MD5 Hash) ===
    $file_md5 = md5_file( $temp_file );
    $existing = get_posts( array(
        'post_type'   => 'attachment',
        'meta_key'    => '_apk_md5',
        'meta_value'  => $file_md5,
        'post_status' => 'inherit',
        'numberposts' => 1,
    ) );
    
    if ( ! empty( $existing ) ) {
        $attachment_id = $existing[0]->ID;
        wp_delete_file( $temp_file );
        set_transient( "apk_upload_cache_{$file_hash}", $attachment_id, HOUR_IN_SECONDS );
        return $attachment_id;
    }
    
    // === WordPress Media Upload ===
    $file_array = array(
        'name'     => basename( $apk_url ), // Atau generate nama dari URL
        'tmp_name' => $temp_file,
    );
    
    $attachment_id = media_handle_sideload( $file_array, 0, null, array(
        'post_title'   => sanitize_file_name( basename( $apk_url ) ),
        'post_content' => '',
        'post_status'  => 'inherit',
    ) );
    
    if ( is_wp_error( $attachment_id ) ) {
        wp_delete_file( $temp_file );
        return $attachment_id;
    }
    
    // === Tambah APK-specific Meta ===
    update_post_meta( $attachment_id, '_apk_source_url', $apk_url );
    update_post_meta( $attachment_id, '_apk_md5', $file_md5 );
    update_post_meta( $attachment_id, '_apk_filesize', filesize( $temp_file ) );
    update_post_meta( $attachment_id, '_apk_uploaded_at', current_time( 'mysql' ) );
    
    // Generate APK icon/thumbnail (opsional)
    if ( $options['generate_thumbnail'] ) {
        generate_apk_thumbnail( $attachment_id, $temp_file );
    }
    
    // Cache hasil untuk 1 jam
    set_transient( "apk_upload_cache_{$file_hash}", $attachment_id, HOUR_IN_SECONDS );
    
    // Bersihkan temp file
    wp_delete_file( $temp_file );
    
    return $attachment_id;
}

function upload_remote_file_apk4( $file_url, $parent_post_id = 0 ) {

    // Pastikan WordPress media functions tersedia
    if ( ! function_exists( 'wp_generate_attachment_metadata' ) ) {
        require_once ABSPATH . 'wp-admin/includes/file.php';
        require_once ABSPATH . 'wp-admin/includes/media.php';
        require_once ABSPATH . 'wp-admin/includes/image.php';
    }

    // Sanitasi & validasi URL
    $file_url = trim( $file_url );
    if ( empty( $file_url ) || ! filter_var( $file_url, FILTER_VALIDATE_URL ) ) {
        return new WP_Error( 'invalid_url', 'URL file tidak valid.' );
    }

    // === 1. Cek duplikat berdasarkan URL asli (cegah upload ulang) ===
    global $wpdb;
    $existing_id = $wpdb->get_var( $wpdb->prepare(
        "SELECT post_id FROM {$wpdb->postmeta}
         WHERE meta_key = '_remote_file_url'
           AND meta_value = %s
         LIMIT 1",
        $file_url
    ) );

    if ( $existing_id ) {
        return (int) $existing_id; // Sudah ada → langsung return ID
    }

    // === 2. Download file sementara ===
    $tmp = download_url( $file_url, 3600 ); // Timeout 120 detik untuk file besar

    if ( is_wp_error( $tmp ) ) {
        return $tmp; // Error dari download_url()
    }

    // === 3. Tentukan nama file & MIME type ===
    $original_filename = wp_basename( parse_url( $file_url, PHP_URL_PATH ) );
    $path_info = pathinfo( $original_filename );
    $ext = strtolower( $path_info['extension'] ?? '' );

    // Force filename bersih & aman
    $clean_name = sanitize_file_name( $path_info['filename'] ?? 'downloaded-file' );
    if ( ! empty( $ext ) ) {
        $clean_name .= '.' . $ext;
    } else {
        $clean_name .= '.apk'; // Default fallback
    }

    // Tentukan MIME type yang benar
    $mime_type = wp_check_filetype( $tmp )['type'];
    if ( in_array( $ext, array( 'apk', 'xapk' ) ) ) {
        $mime_type = 'application/vnd.android.package-archive';
    } elseif ( $ext === 'ipa' ) {
        $mime_type = 'application/octet-stream';
    } elseif ( $ext === 'zip' ) {
        $mime_type = 'application/zip';
    }

    // Cek apakah tipe file diizinkan
    $allowed_mimes = get_allowed_mime_types();
    if ( ! $mime_type || ! in_array( $mime_type, $allowed_mimes, true ) ) {
        @unlink( $tmp );
        return new WP_Error( 'invalid_type', 'Tipe file tidak diizinkan: ' . $mime_type );
    }

    // Optional: batas ukuran (misal 1000 MB untuk APK besar)
    $max_size = 1000 * MB_IN_BYTES; // Sesuaikan sesuai hosting
    if ( filesize( $tmp ) > $max_size ) {
        @unlink( $tmp );
        return new WP_Error( 'file_too_large', 'File terlalu besar (maksimal 1000 MB).' );
    }

    // === 4. Siapkan array untuk sideload ===
    $file_array = array(
        'name'     => $clean_name,
        'type'     => $mime_type,
        'tmp_name' => $tmp,
        'error'    => 0,
        'size'     => filesize( $tmp ),
    );

    // === 5. Handle sideload ===
    $overrides = array(
        'test_form' => false,
        'test_size' => true,
        'test_upload' => true,
    );

    $results = wp_handle_sideload( $file_array, $overrides );

    if ( isset( $results['error'] ) ) {
        @unlink( $tmp );
        return new WP_Error( 'sideload_failed', $results['error'] );
    }

    $filename = $results['file']; // Path lengkap di server
    $url      = $results['url'];   // URL publik

    // === 6. Buat attachment ===
    $attachment = array(
        'guid'           => $url,
        'post_mime_type' => $results['type'],
        'post_title'     => preg_replace( '/\.[^.]+$/', '', $clean_name ),
        'post_content'   => '',
        'post_status'    => 'inherit',
        'post_parent'    => (int) $parent_post_id,
    );

    $attach_id = wp_insert_attachment( $attachment, $filename, (int) $parent_post_id );

    if ( is_wp_error( $attach_id ) ) {
        @unlink( $filename );
        return $attach_id;
    }

    // === 7. Generate metadata ===
    $attach_data = wp_generate_attachment_metadata( $attach_id, $filename );
    wp_update_attachment_metadata( $attach_id, $attach_data );

    // === 8. Simpan URL asli untuk deduplication ===
    update_post_meta( $attach_id, '_remote_file_url', $file_url );
    update_post_meta( $attach_id, '_source_filename', $original_filename );
    update_post_meta( $attach_id, '_file_size_bytes', filesize( $filename ) );

    return $attach_id; // Sukses!
}
 

/**
 * upload_remote_file_apk() - FINAL VERSION DENGAN PROGRESS BAR CANTIK REAL-TIME
 * Upload APK besar dengan progress langsung di admin WordPress
 */
function upload_remote_file_apk_bar( $file_url, $parent_post_id = 0 ) {

    // Load WordPress media functions
    if ( ! function_exists( 'wp_generate_attachment_metadata' ) ) {
        require_once ABSPATH . 'wp-admin/includes/file.php';
        require_once ABSPATH . 'wp-admin/includes/media.php';
        require_once ABSPATH . 'wp-admin/includes/image.php';
    }

    $file_url = trim( $file_url );
    if ( empty( $file_url ) || ! filter_var( $file_url, FILTER_VALIDATE_URL ) ) {
        return new WP_Error( 'invalid_url', 'URL tidak valid.' );
    }

    // Deduplication berdasarkan URL asli
    global $wpdb;
    $existing_id = $wpdb->get_var( $wpdb->prepare(
        "SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = '_remote_file_url' AND meta_value = %s LIMIT 1",
        $file_url
    ) );
    if ( $existing_id ) {
        return (int) $existing_id;
    }

    // Unique progress key
    $url_hash     = md5( $file_url );
    $progress_key = 'apk_progress_' . $parent_post_id . '_' . $url_hash;

    // Inisialisasi progress
    set_transient( $progress_key, [
        'progress' => 0,
        'message'  => 'Memulai proses upload APK...',
        'status'   => 'starting'
    ], 7200 );

    $tmp = wp_tempnam( 'apk' );
    if ( ! $tmp ) {
        delete_transient( $progress_key );
        return new WP_Error( 'temp_error', 'Gagal membuat file sementara.' );
    }

    $fp = fopen( $tmp, 'wb' );
    if ( ! $fp ) {
        delete_transient( $progress_key );
        @unlink( $tmp );
        return new WP_Error( 'file_open', 'Gagal membuka file sementara.' );
    }

    // HEAD request untuk ambil ukuran file
    $ch_head = curl_init( $file_url );
    curl_setopt_array( $ch_head, [
        CURLOPT_NOBODY         => true,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => 60,
        CURLOPT_USERAGENT      => 'WordPress APK Importer',
    ]);
    curl_exec( $ch_head );
    $total_size = curl_getinfo( $ch_head, CURLINFO_CONTENT_LENGTH_DOWNLOAD );
    curl_close( $ch_head );

    update_transient( $progress_key, [
        'progress' => 5,
        'message'  => 'Menghubungkan ke server...',
        'size'     => $total_size
    ]);

    // Download utama dengan progress real-time
    $ch = curl_init( $file_url );
    curl_setopt_array( $ch, [
        CURLOPT_FILE           => $fp,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_TIMEOUT        => 3600,
        CURLOPT_USERAGENT      => 'Mozilla/5.0 (WordPress APK Downloader)',
        CURLOPT_NOPROGRESS     => false,
        CURLOPT_PROGRESSFUNCTION => function( $res, $total, $now ) use ( $progress_key, $total_size ) {
            $percent = 0;
            if ( $total_size > 0 && $total_size !== -1 ) {
                $percent = min( 98, round( ($now / $total_size) * 100 ) );
            } elseif ( $total > 0 ) {
                $percent = min( 98, round( ($now / $total) * 100 ) );
            }

            $down_mb  = round( $now / 1048576, 1 );
            $total_mb = $total_size > 0 && $total_size !== -1 ? round( $total_size / 1048576, 1 ) : '???';

            update_transient( $progress_key, [
                'progress' => $percent,
                'message'  => "Mengunduh: {$down_mb} MB dari {$total_mb} MB ({$percent}%)",
                'status'   => 'downloading'
            ]);
        },
    ]);

    $success = curl_exec( $ch );
    $error   = curl_error( $ch );
    $code    = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
    curl_close( $ch );
    fclose( $fp );

    if ( ! $success || $code !== 200 || filesize( $tmp ) < 102400 ) {
        delete_transient( $progress_key );
        @unlink( $tmp );
        return new WP_Error( 'download_failed', "Download gagal: {$error} (HTTP {$code})" );
    }

    update_transient( $progress_key, [
        'progress' => 99,
        'message'  => 'File selesai di-download. Sedang menyimpan ke Media Library...'
    ]);

    // Sideload file
    $orig_name = wp_basename( parse_url( $file_url, PHP_URL_PATH ) );
    $path_info = pathinfo( $orig_name );
    $ext       = strtolower( $path_info['extension'] ?? '' );
    $clean_name = sanitize_file_name( $path_info['filename'] ?? 'apk-file' ) . ( $ext ? '.' . $ext : '.apk' );

    $mime = in_array( $ext, ['apk', 'xapk'] ) ? 'application/vnd.android.package-archive' : 'application/octet-stream';

    $file_array = [
        'name'     => $clean_name,
        'type'     => $mime,
        'tmp_name' => $tmp,
        'error'    => 0,
        'size'     => filesize( $tmp )
    ];

    $results = wp_handle_sideload( $file_array, [ 'test_form' => false ] );
    if ( isset( $results['error'] ) ) {
        delete_transient( $progress_key );
        @unlink( $tmp );
        return new WP_Error( 'sideload_error', $results['error'] );
    }

    // Insert attachment
    $attachment = [
        'guid'           => $results['url'],
        'post_mime_type' => $results['type'],
        'post_title'     => preg_replace( '/\.[^.]+$/', '', $clean_name ),
        'post_content'   => '',
        'post_status'    => 'inherit',
        'post_parent'    => (int) $parent_post_id,
    ];

    $attach_id = wp_insert_attachment( $attachment, $results['file'], (int) $parent_post_id );
    if ( is_wp_error( $attach_id ) ) {
        delete_transient( $progress_key );
        @unlink( $results['file'] );
        return $attach_id;
    }

    // Generate metadata (fix: jangan panggil dua kali)
    $attach_data = wp_generate_attachment_metadata( $attach_id, $results['file'] );
    wp_update_attachment_metadata( $attach_id, $attach_data );

    // Simpan info sumber
    update_post_meta( $attach_id, '_remote_file_url', $file_url );

    // Selesai → hapus progress
    delete_transient( $progress_key );

    return $attach_id;
}

// === AJAX Handler untuk Progress ===
add_action( 'wp_ajax_apk_get_progress', 'apk_get_progress' );
function apk_get_progress() {
    check_ajax_referer( 'apk_progress', 'nonce' );

    $post_id  = intval( $_GET['post_id'] ?? 0 );
    $url_hash = sanitize_text_field( $_GET['hash'] ?? '' );

    if ( ! $post_id || ! $url_hash ) {
        wp_send_json_error( ['progress' => 0, 'message' => 'Data tidak valid'] );
    }

    $key  = 'apk_progress_' . $post_id . '_' . $url_hash;
    $data = get_transient( $key );

    if ( ! $data ) {
        wp_send_json_success( [
            'progress' => 100,
            'message'  => 'Upload APK selesai!',
            'status'   => 'completed'
        ] );
    } else {
        wp_send_json_success( $data );
    }
}

// === Progress Bar Cantik di Admin ===
add_action( 'admin_footer', 'apk_progress_bar_ui' );
function apk_progress_bar_ui() {
    global $post;
    if ( ! $post || ! current_user_can( 'edit_post', $post->ID ) ) return;

    // Pastikan jQuery di-load
    wp_enqueue_script( 'jquery' );
    ?>
    <div id="apk-progress-box" style="display:none; position:fixed; bottom:20px; left:50%; transform:translateX(-50%); width:90%; max-width:600px; background:#ffffff; border-radius:16px; box-shadow:0 15px 40px rgba(0,0,0,0.25); padding:24px; z-index:99999; font-family:system-ui, -apple-system, sans-serif; border:1px solid #e0e0e0;">
        <div style="text-align:center; margin-bottom:18px;">
            <strong style="font-size:19px; color:#1a1a1a;">Sedang Mengupload File APK</strong>
        </div>
        <div id="apk-progress-text" style="text-align:center; margin-bottom:16px; font-size:16px; color:#333; font-weight:500;">
            Memulai proses...
        </div>
        <div style="height:48px; background:#f0f0f0; border-radius:24px; overflow:hidden; position:relative; box-shadow:inset 0 2px 4px rgba(0,0,0,0.1);">
            <div id="apk-progress-fill" style="height:100%; width:0%; background:linear-gradient(90deg, #4facfe 0%, #00f2fe 100%); transition:width 0.8s cubic-bezier(0.4, 0, 0.2, 1); display:flex; align-items:center; justify-content:center; color:white; font-weight:bold; font-size:18px; text-shadow:0 1px 2px rgba(0,0,0,0.3);">
                0%
            </div>
        </div>
        <div style="text-align:center; margin-top:14px;">
            <small style="color:#777; font-size:13px;">Jangan tutup atau refresh halaman ini</small>
        </div>
    </div>

    <script>
    jQuery(function($) {
        if (typeof apkProgressData === 'undefined' || !apkProgressData.active) return;

        const box  = $('#apk-progress-box');
        const fill = $('#apk-progress-fill');
        const text = $('#apk-progress-text');

        box.fadeIn(300);

        function updateProgress() {
            $.ajax({
                url: ajaxurl,
                type: 'GET',
                data: {
                    action: 'apk_get_progress',
                    nonce: apkProgressData.nonce,
                    post_id: apkProgressData.post_id,
                    hash: apkProgressData.hash
                },
                success: function(res) {
                    if (res.success) {
                        const d = res.data;
                        fill.css('width', d.progress + '%').text(d.progress + '%');
                        text.text(d.message || 'Memproses...');

                        if (d.progress < 100 && d.status !== 'completed') {
                            setTimeout(updateProgress, 1000);
                        } else {
                            setTimeout(() => box.fadeOut(1000), 2000);
                        }
                    }
                },
                error: function() {
                    text.text('Koneksi terputus. Mencoba lagi...');
                    setTimeout(updateProgress, 3000);
                }
            });
        }

        updateProgress();
    });
    </script>
    <?php
}