<?php
  
/* --------------------------------------------------------------------
 * AJAX: Single App Update
 * --------------------------------------------------------------------
 * Handles the AJAX request when a user clicks "Update Now" on a single app.
 * Performs security checks, runs your update logic, and clears temporary meta.
 */
if ( ! function_exists( 'ajax_update_single_app' ) ) 
{
	add_action('wp_ajax_ajax_update_single_app', 'ajax_update_single_app');
	function ajax_update_single_app() 
	{
		// Verify nonce to prevent CSRF attacks
		check_ajax_referer('apps_updates_nonce', 'nonce');

		// Get and sanitize the post ID
		$post_id 			= intval($_POST['post_id'] ?? 0);
		
		// Check if post exists and user has permission to edit it
		if (!$post_id || !current_user_can('edit_post', $post_id)) {
			wp_send_json_error(['message' => 'Permission denied']);
		}

		// Retrieve the scraped available version and what's new
		$available_version 	= get_post_meta($post_id, 'available_version', true);
		$available_whatsnew	= get_post_meta($post_id, 'available_whatsnew', true);
		
		// Use GP title if available, otherwise fallback to post title
		$title 				= get_post_meta($post_id, 'wp_title_GP', true) ?: get_the_title($post_id) ?: 'Unknown App';

		// Safety check – no new version found
		if (empty($available_version)) {
			wp_send_json_error(['message' => 'No new version available.']);
		}

		// === PLACE YOUR ACTUAL UPDATE LOGIC HERE ===
		// e.g., download new APK, extract data, update fields, etc.
		$result 			= true; // Replace with real result (true or WP_Error)

		// If something went wrong in your update process
		if (is_wp_error($result)) {
			wp_send_json_error(['message' => $result->get_error_message()]);
		}

		// Clean up temporary update detection meta fields
		delete_post_meta($post_id, 'available_updated');
		delete_post_meta($post_id, 'available_version');
		delete_post_meta($post_id, 'available_whatsnew');

		// Save the new current version and changelog
		update_post_meta($post_id, 'wp_version_GP', $available_version);
		update_post_meta($post_id, 'wp_whatnews_GP', $available_whatsnew);
		update_post_meta($post_id, 'last_updated', current_time('mysql'));

		// Send success response back to JavaScript
		wp_send_json_success([
			'message'     => 'Updated successfully!',
			'app_name'    => $title,
			'new_version' => $available_version,
		]);
	}
}

/**
 * AJAX Handler: Fast Check Single App
 * Dipanggil dari halaman Apps Updates (bulk, single, debug mode)
*/
if ( ! function_exists( 'ajax_fastcheck_single_app_handler' ) ) 
{
	add_action('wp_ajax_ajax_fastcheck_single_app', 'ajax_fastcheck_single_app_handler');
	function ajax_fastcheck_single_app_handler() 
	{
		// Cek nonce keamanan
		check_ajax_referer('apps_updates_nonce', 'nonce');

		// Pastikan hanya admin
		if (!current_user_can('manage_options')) {
			wp_send_json_error(['message' => 'Permission denied.']);
		}

		$post_id = isset($_POST['post_id']) ? absint($_POST['post_id']) : 0;
		if (!$post_id || !get_post($post_id)) {
			wp_send_json_error(['message' => "Invalid post ID: $post_id"]);
		}

		$debug_mode = !empty($_POST['debug']);

		// Jika debug mode aktif, capture output dari fungsi check
		if ($debug_mode) {
			ob_start();
		}

		// Jalankan pengecekan update
		// Ganti dengan fungsi kamu yang sebenarnya (misal: app_update_available, check_gp_version, dll)
		$needs_update = app_update_available($post_id, $debug_mode); // pastikan fungsi ini return true/false

		// Jika debug mode, ambil output
		$debug_output = $debug_mode ? ob_get_clean() : '';

		// Response
		$response = [
			'needs_update' => (bool) $needs_update,
		];

		if ($debug_mode && $debug_output) {
			$response['debug'] = $debug_output;
		}

		wp_send_json_success($response);
	}
}
  
/* --------------------------------------------------------------------
 * AJAX: Render Table + Pagination + Count
 * --------------------------------------------------------------------
 * Called via AJAX to load a specific page of updates.
 * Returns the full table HTML and native WordPress pagination.
 */
if ( ! function_exists( 'apk_render_updates_list' ) ) 
{
	function apk_render_updates_list() 
	{
		check_ajax_referer( 'apps_updates_nonce', 'nonce' );
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( [ 'message' => 'Permission denied.' ] );
		}

		$paged    = max( 1, intval( $_POST['paged'] ?? 1 ) );
		$search   = sanitize_text_field( $_POST['s'] ?? '' );
		$per_page = 20;
		$offset   = ( $paged - 1 ) * $per_page;

		$total       = apk_update_count_posts_search( $search );
		$total_pages = max( 1, ceil( $total / $per_page ) );

		ob_start();
		apk_render_updates_table( $offset, $per_page, $search );
		$table_html = ob_get_clean();

		ob_start();
		?>
		<div class="tablenav-pages">
			<?php if ( $total > 0 ): ?>
				<span class="displaying-num"><?php echo esc_html( $total ); ?> item<?php echo $total != 1 ? 's' : ''; ?></span>
			<?php endif; ?>
			<?php if ( $total_pages > 1 ): ?>
				<span class="pagination-links">
					<?php if ( $paged == 1 ): ?>
						<span class="tablenav-pages-navspan button disabled">«</span>
						<span class="tablenav-pages-navspan button disabled">‹</span>
					<?php else: ?>
						<a class="first-page button" href="#" data-page="1">«</a>
						<a class="prev-page button" href="#" data-page="<?php echo $paged - 1; ?>">‹</a>
					<?php endif; ?>
					<span class="paging-input"><?php echo $paged; ?> of <span class="total-pages"><?php echo $total_pages; ?></span></span>
					<?php if ( $paged >= $total_pages ): ?>
						<span class="tablenav-pages-navspan button disabled">›</span>
						<span class="tablenav-pages-navspan button disabled">»</span>
					<?php else: ?>
						<a class="next-page button" href="#" data-page="<?php echo $paged + 1; ?>">›</a>
						<a class="last-page button" href="#" data-page="<?php echo $total_pages; ?>">»</a>
					<?php endif; ?>
				</span>
			<?php endif; ?>
		</div>
		<?php
		$pagination_html = ob_get_clean();

		wp_send_json_success( [
			'table'        => $table_html,
			'pagination'   => $pagination_html,
			'total'        => $total,
			'total_pages'  => $total_pages,
			'current_page' => $paged,
		] );
	}
	add_action( 'wp_ajax_apk_render_updates_list', 'apk_render_updates_list' );
}

/* --------------------------------------------------------------------
 * Render Table (Core WordPress Style)  (support search)
 * --------------------------------------------------------------------
 * Outputs the actual <table> with apps needing updates.
 * Uses exact WordPress core classes for seamless visual integration.
*/
if ( ! function_exists( 'apk_render_updates_table' ) ) 
{
	function apk_render_updates_table( $offset = 0, $per_page = 20, $search = '' ) 
	{
		global $wpdb;
		$post_type = 'post';
		$offset    = absint( $offset );
		$per_page  = absint( $per_page ) ?: 20;

		$select = "SELECT DISTINCT p.ID, p.post_title,
				   pm_title.meta_value AS display_title,
				   pm_curr.meta_value AS current_version,
				   pm_avail.meta_value AS available_version,
				   pm_poster.meta_value AS fallback_image,
				   pm_lastcheck.meta_value AS last_checked";

		$joins = "
			FROM {$wpdb->posts} p
			INNER JOIN {$wpdb->postmeta} pm_avail ON p.ID = pm_avail.post_id
				AND pm_avail.meta_key = 'available_version' AND pm_avail.meta_value != ''
			LEFT JOIN {$wpdb->postmeta} pm_curr ON p.ID = pm_curr.post_id AND pm_curr.meta_key = 'wp_version_GP'
			LEFT JOIN {$wpdb->postmeta} pm_title ON p.ID = pm_title.post_id AND pm_title.meta_key = 'wp_title_GP'
			LEFT JOIN {$wpdb->postmeta} pm_poster ON p.ID = pm_poster.post_id AND pm_poster.meta_key = 'wp_poster_GP'
			LEFT JOIN {$wpdb->postmeta} pm_lastcheck ON p.ID = pm_lastcheck.post_id AND pm_lastcheck.meta_key = '_time_scrape_app_update'
		";

		$where = "
			WHERE p.post_type = %s AND p.post_status = 'publish'
			  AND COALESCE(pm_avail.meta_value, '') > COALESCE(pm_curr.meta_value, '0.0.0')
			  AND EXISTS (
				  SELECT 1 FROM {$wpdb->postmeta} pm_flag
				  WHERE pm_flag.post_id = p.ID
					AND pm_flag.meta_key = 'available_updated'
					AND pm_flag.meta_value = 'yes'
			  )
		";

		$params = [ $post_type ];

		if ( ! empty( $search ) ) {
			$like = '%' . $wpdb->esc_like( $search ) . '%';
			$where .= " AND (
				p.post_title LIKE %s
				OR pm_title.meta_value LIKE %s
				OR EXISTS (
					SELECT 1 FROM {$wpdb->postmeta} pm_pkg
					WHERE pm_pkg.post_id = p.ID
					  AND pm_pkg.meta_key = 'wp_GP_ID'
					  AND pm_pkg.meta_value LIKE %s
				)
			)";
			$params[] = $like;
			$params[] = $like;
			$params[] = $like;
		}

		$query = $select . $joins . $where .
				 " ORDER BY COALESCE(pm_lastcheck.meta_value, 0) DESC" .
				 " LIMIT %d, %d";
		$params[] = $offset;
		$params[] = $per_page;

		$apps = $wpdb->get_results( $wpdb->prepare( $query, $params ) );

		if ( empty( $apps ) ) {
			if ( ! empty( $search ) ) {
				echo '<p class="notice notice-info" style="text-align: center;font-size: 2rem;padding: 1rem;">' . esc_html__( 'No apps found matching your search.', TEXT_DOMAIN ) . '</p>';
			} else {
				echo '<p class="notice notice-info" style="text-align: center;font-size: 2rem;padding: 1rem;"><strong>' . esc_html__( 'All apps are up to date!', TEXT_DOMAIN ) . '</strong></p>';
			}
			return;
		}

		// === TABEL HTML (sama seperti kode Anda sebelumnya) ===
		?>
		<table class="wp-list-table widefat fixed striped table-view-list posts">
			<thead>
				<tr>
					<td id="cb" class="manage-column column-cb check-column"><input id="cb-select-all-1" type="checkbox"></td>
					<th class="manage-column column-title column-primary"><?php esc_html_e( 'Title', TEXT_DOMAIN ); ?></th>
					<th class="manage-column"><?php esc_html_e( 'Current Version', TEXT_DOMAIN ); ?></th>
					<th class="manage-column"><?php esc_html_e( 'Available Version', TEXT_DOMAIN ); ?></th>
					<th class="manage-column"><?php esc_html_e( 'Last Checked', TEXT_DOMAIN ); ?></th>
					<th class="manage-column column-poster"><?php esc_html_e( 'Poster', TEXT_DOMAIN ); ?></th>
				</tr>
			</thead>
			<tbody id="the-list">
				<?php foreach ( $apps as $app ) :
					$post_id      = intval( $app->ID );
					$title        = ! empty( $app->display_title ) ? esc_html( $app->display_title ) : esc_html( $app->post_title ?: 'Untitled App' );
					$current      = $app->current_version ? esc_html( $app->current_version ) : '<span style="color:#999;">—</span>';
					$available    = esc_html( $app->available_version );
					$last_checked = $app->last_checked ? sprintf( __( '%s ago', TEXT_DOMAIN ), human_time_diff( intval( $app->last_checked ) ) ) : __( 'Never', TEXT_DOMAIN );
					$thumb        = get_the_post_thumbnail_url( $post_id, 'thumbnail' );
					if ( ! $thumb && ! empty( $app->fallback_image ) ) $thumb = esc_url( $app->fallback_image );
					?>
					<tr id="post-<?php echo $post_id; ?>">
						<th class="check-column"><input type="checkbox" name="post[]" value="<?php echo $post_id; ?>"></th>
						<td class="title column-title has-row-actions column-primary">
							<strong class="row-title"><a href="<?php echo esc_url( get_edit_post_link( $post_id ) ); ?>"><?php echo $title; ?></a></strong>
							<div class="row-actions">
								<span class="edit"><a href="<?php echo esc_url( get_edit_post_link( $post_id ) ); ?>"><?php esc_html_e( 'Edit', TEXT_DOMAIN ); ?></a> | </span>
								<span class="view"><a href="<?php echo esc_url( get_permalink( $post_id ) ); ?>" target="_blank"><?php esc_html_e( 'View', TEXT_DOMAIN ); ?></a> | </span>
								<span class="update"><a href="#" class="single-update" data-id="<?php echo $post_id; ?>"><?php esc_html_e( 'Update Now', TEXT_DOMAIN ); ?></a> | </span>
								<span class="fastcheck"><a href="#" class="single-fastcheck" data-id="<?php echo $post_id; ?>" style="color:#856404;"><?php esc_html_e( '⚡ Fast Check', TEXT_DOMAIN ); ?></a></span>
							</div>
						</td>
						<td><strong><?php echo wp_kses_post( $current ); ?></strong></td>
						<td><strong style="color:#2271b1;"><?php echo $available; ?></strong></td>
						<td><strong><?php echo esc_html( $last_checked ); ?></strong></td>
						<td class="column-poster">
							<?php if ( $thumb ) : ?>
								<img src="<?php echo esc_url( $thumb ); ?>" width="60" height="60" style="border-radius:8px;object-fit:cover;box-shadow:0 1px 3px rgba(0,0,0,0.2);" alt="<?php echo esc_attr( $title ); ?>">
							<?php else : ?>
								<div style="width:60px;height:60px;background:#f0f0f0;border-radius:8px;display:flex;align-items:center;justify-content:center;color:#999;font-size:12px;">No image</div>
							<?php endif; ?>
						</td>
					</tr>
				<?php endforeach; ?>
			</tbody>
		</table>
		<?php
	}
}
 
/* --------------------------------------------------------------------
 * Apps Updates Page - Main Admin Page Render
 * --------------------------------------------------------------------
 * Konten halaman sebenarnya yang ditampilkan saat mengklik "Apps Updates" di menu.
 * Menggunakan markup WordPress asli (h1, tablenav, bulk actions, etc.).
*/
 
if (!function_exists('apps_updates_page')) 
{
    function apps_updates_page() 
	{
        if (!current_user_can('manage_options')) {
            wp_die(esc_html__('Permission denied.', TEXT_DOMAIN));
        }

        $nonce = wp_create_nonce('apps_updates_nonce');
        $force_check_url = wp_nonce_url(add_query_arg('app_update_force_check', '1'), 'app_update_force_check_all');
        $total_updates = (int) apk_update_count_posts();
        ?>
		
		
        <div class="wrap">
            <h1 class="wp-heading-inline">
                <?php esc_html_e('Apps Updates List', TEXT_DOMAIN); ?>
                (<span id="h1-updates-count"><?php echo esc_html($total_updates); ?></span>)
            </h1>
            <a href="<?php echo esc_url($force_check_url); ?>" class="page-title-action">
                <?php esc_html_e('Check All Apps Now', TEXT_DOMAIN); ?>
            </a>
            <hr class="wp-header-end">

            <div id="fastcheck-results" style="margin:20px 0;"></div>

            <div id="update-progress" style="display:none; margin:25px 0;">
                <div class="notice notice-info inline">
                    <p><strong id="progress-title">Processing...</strong></p>
                    <p><span id="progress-text">0 of 0</span></p>
                    <div class="progress-container">
                        <div id="progress-bar">
                            <span id="progress-percent" class="percent-text">0%</span>
                        </div>
                    </div>
                    <p id="progress-status">Starting...</p>
                </div>
            </div>

            <h2 style="font-weight:700; margin-top:30px;">
                <strong><span id="updates-count">Loading...</span></strong> app(s) need update
            </h2>

            <form id="apps-updates-form" method="get">
                <?php wp_nonce_field('apps_updates_nonce', '_wpnonce'); ?>

                <div class="tablenav top">
                    <div class="alignleft actions bulkactions">
                        <select name="action" id="bulk-action-selector-top">
                            <option value="-1"><?php esc_html_e('Bulk actions', TEXT_DOMAIN); ?></option>
                            <option value="update-selected"><?php esc_html_e('Update Selected', TEXT_DOMAIN); ?></option>
                            <option value="fastcheck-selected"><?php esc_html_e('Fast Check Selected', TEXT_DOMAIN); ?></option>
                            <option value="fastcheck-debug"><?php esc_html_e('Fast Check Selected (Debug Mode)', TEXT_DOMAIN); ?></option>
                        </select>
                        <input type="button" id="doaction" class="button action" value="<?php esc_attr_e('Apply', TEXT_DOMAIN); ?>">
                        <input type="button" id="check-all-visible" class="button action" value="<?php esc_attr_e('⚡ Check All Visible', TEXT_DOMAIN); ?>" style="margin-left:8px;">
                    </div>
                    <div class="alignright">
                        <input type="search" id="apps-search-input" placeholder="<?php esc_attr_e('Search apps...', TEXT_DOMAIN); ?>" value="" aria-label="Search apps" />
                        <input type="button" id="apps-search-submit" class="button" value="<?php esc_html_e('Search', TEXT_DOMAIN); ?>">
                        <input type="button" id="apps-search-reset" class="button" value="<?php esc_html_e('Reset', TEXT_DOMAIN); ?>" style="display:none;">
                    </div>
                    <div id="top-pagination" class="tablenav-pages"></div>
                    <br class="clear">
                </div>

                <div id="updates-table-container">
                    <?php esc_html_e('Loading apps list...', TEXT_DOMAIN); ?>
                </div>

                <div class="tablenav bottom">
                    <div class="alignleft actions bulkactions">
                        <select name="action2" id="bulk-action-selector-bottom">
                            <option value="-1"><?php esc_html_e('Bulk actions', TEXT_DOMAIN); ?></option>
                            <option value="update-selected"><?php esc_html_e('Update Selected', TEXT_DOMAIN); ?></option>
                            <option value="fastcheck-selected"><?php esc_html_e('Fast Check Selected', TEXT_DOMAIN); ?></option>
                            <option value="fastcheck-debug"><?php esc_html_e('Fast Check Selected (Debug Mode)', TEXT_DOMAIN); ?></option>
                        </select>
                        <input type="button" id="doaction2" class="button action" value="<?php esc_attr_e('Apply', TEXT_DOMAIN); ?>">
                        <input type="button" id="check-all-visible-bottom" class="button action" value="<?php esc_attr_e('⚡ Check All Visible', TEXT_DOMAIN); ?>" style="margin-left:8px;">
                    </div>
                    <div id="bottom-pagination" class="tablenav-pages"></div>
                    <br class="clear">
                </div>
            </form>
        </div>

        <style>
            .updating-row   { background:#fffbe6 !important; border-left:4px solid #ffb900; }
            .updated-row    { background:#e6f7e6 !important; border-left:4px solid #00ba37; }
            .error-row      { background:#fdeaea !important; border-left:4px solid #d63638; }
            .checking-row   { background:#fff9e6 !important; border-left:4px solid #ffba00; }
            .no-update-row  { background:#f8f8f8 !important; border-left:4px solid #aaa; }

            .progress-container {
                background: #f0f0f1;
                height: 32px;                    /* lebih tinggi agar teks muat */
                border-radius: 6px;
                overflow: hidden;
                margin: 12px 0;
                position: relative;
                box-shadow: inset 0 1px 2px rgba(0,0,0,0.1);
            }

            #progress-bar {
                width: 0%;
                height: 100%;
                background: linear-gradient(90deg, #2271b1, #4f94d6);
                transition: width 0.5s ease;
                position: relative;
                display: flex;
                align-items: center;
                justify-content: center;
            }

            .percent-text {
                position: absolute;
                top: 50%;
                left: 50%;
                transform: translate(-50%, -50%);
                color: white;
                font-weight: bold;
                font-size: 13px;
                text-shadow: 0 0 3px rgba(0,0,0,0.7);
                pointer-events: none;
                z-index: 10;
            }

            /* Teks jadi gelap saat bar masih sangat kecil (agar tetap terbaca) */
            #progress-bar[data-percent^="0"],
            #progress-bar[data-percent^="1"] .percent-text {
                color: #333;
                text-shadow: none;
            }
        </style>

        <script>
        (function() {
            const els = {
                container:       document.getElementById('updates-table-container'),
                progress:        document.getElementById('update-progress'),
                progressBar:     document.getElementById('progress-bar'),
                progressText:    document.getElementById('progress-text'),
                progressPercent: document.getElementById('progress-percent'),
                progressStatus:  document.getElementById('progress-status'),
                progressTitle:   document.getElementById('progress-title'),
                results:         document.getElementById('fastcheck-results'),
                searchInput:     document.getElementById('apps-search-input'),
                searchSubmit:    document.getElementById('apps-search-submit'),
                searchReset:     document.getElementById('apps-search-reset'),
                h1Count:         document.getElementById('h1-updates-count'),
                count:           document.getElementById('updates-count')
            };

            const state = {
                nonce: '<?php echo esc_js($nonce); ?>',
                page: 1,
                search: '',
                total: 0,
                processing: false
            };

            const ajax = {
                url: window.ajaxurl || '/wp-admin/admin-ajax.php',
                async post(data) {
                    const fd = new FormData();
                    Object.entries({...data, _ajax_nonce: state.nonce}).forEach(([k,v]) => fd.append(k,v));
                    try {
                        const res = await fetch(this.url, {method: 'POST', body: fd, credentials: 'same-origin'});
                        if (!res.ok) throw new Error(`HTTP ${res.status}`);
                        const json = await res.json();
                        if (!json.success && json.data?.message) throw new Error(json.data.message);
                        return json;
                    } catch (e) {
                        console.error('AJAX error:', e);
                        return { success: false, data: { message: e.message || 'Failed' } };
                    }
                }
            };

            function scrollToProgress() {
                if (els.progress) {
                    setTimeout(() => {
                        els.progress.scrollIntoView({behavior: 'smooth', block: 'center'});
                    }, 80);
                }
            }

            async function loadList(page = 1, search = '') {
                state.page = page;
                state.search = search.trim();
                els.container.innerHTML = '<p><em>Loading applications...</em></p>';

                const res = await ajax.post({
                    action: 'apk_render_updates_list',
                    paged: page,
                    s: state.search
                });

                if (!res.success) {
                    els.container.innerHTML = '<p style="color:#d63638">Error loading list. Please refresh.</p>';
                    return;
                }

                const { table, pagination, total } = res.data;
                els.container.innerHTML = table;
                document.querySelectorAll('.tablenav-pages').forEach(el => el.innerHTML = pagination || '');

                state.total = Number(total) || 0;
                const display = state.total > 0 ? state.total : 'No';
                const display2 = state.total > 0 ? state.total : '-';
                els.h1Count.textContent = display2;
                els.count.textContent = display;

                const badge = document.querySelector('#toplevel_page_apps_updates .update-plugins');
                if (badge) {
                    badge.style.display = state.total > 0 ? 'inline-block' : 'none';
                    if (state.total > 0) badge.querySelector('.plugin-count').textContent = state.total;
                }

                if (els.searchInput) {
                    els.searchInput.value = state.search;
                    els.searchReset.style.display = state.search ? 'inline-block' : 'none';
                }
            }

            async function processItems(ids, action, titlePrefix, debug = false) {
                if (state.processing || !ids?.length) return;
                state.processing = true;

                els.progress.style.display = 'block';
                els.progressTitle.textContent = `${titlePrefix} ${ids.length} item${ids.length === 1 ? '' : 's'}...`;
                els.progressText.textContent = `0 / ${ids.length}`;
                els.progressPercent.textContent = '0%';
                els.progressBar.style.width = '0%';
                els.progressStatus.textContent = 'Preparing...';

                let done = 0, updates = 0, uptoDate = 0, errors = 0;
                const log = [];

                for (const id of ids) {
                    const row = document.getElementById(`post-${id}`);
                    const name = row?.querySelector('.row-title')?.textContent?.trim() || `App #${id}`;

                    row?.classList.add(action.includes('fastcheck') ? 'checking-row' : 'updating-row');
                    els.progressStatus.textContent = `${titlePrefix}: ${name}`;

                    const res = await ajax.post({
                        action: action,
                        post_id: id,
                        debug: debug ? '1' : '0'
                    });

                    row?.classList.remove('checking-row', 'updating-row');

                    let msg = '';
                    if (res.success) {
                        if (res.data?.needs_update) {
                            row?.classList.add('updated-row');
                            updates++;
                            msg = `<strong>${name}</strong> → <span style="color:#00a32a">Update available</span>`;
                        } else {
                            row?.classList.add('no-update-row');
                            uptoDate++;
                            msg = `<strong>${name}</strong> → Up to date`;
                        }
                    } else {
                        row?.classList.add('error-row');
                        errors++;
                        msg = `<strong>${name}</strong> → <span style="color:#d63638">Failed</span>`;
                    }

                    log.push(msg);
                    done++;

                    const percent = Math.round((done / ids.length) * 100);
                    els.progressText.textContent = `${done} / ${ids.length}`;
                    els.progressPercent.textContent = `${percent}%`;
                    els.progressBar.style.width = `${percent}%`;
                    els.progressBar.setAttribute('data-percent', percent); // untuk styling kondisional

                    await new Promise(r => setTimeout(r, debug ? 700 : 350));
                }

                let summary = `Completed! <strong>${ids.length}</strong> item${ids.length === 1 ? '' : 's'}. `;
                if (updates) summary += `<span style="color:#00a32a">${updates} update${updates === 1 ? '' : 's'} found</span>. `;
                if (uptoDate) summary += `${uptoDate} up to date. `;
                if (errors) summary += `<span style="color:#d63638">${errors} failed</span>.`;

                els.results.innerHTML = `
                    <div class="notice notice-success is-dismissible">
                        <p>${summary}</p>
                        ${log.length ? `
                        <div style="margin-top:12px;padding:12px;background:#f9f9f9;border:1px solid #ddd;border-radius:4px;">
                            <strong>Details:</strong>
                            <ul style="margin:8px 0 0 20px;">${log.map(item => `<li>${item}</li>`).join('')}</ul>
                        </div>` : ''}
                    </div>`;

                els.progressStatus.innerHTML = '<span style="color:#00a32a">Finished!</span>';
                els.progressPercent.textContent = '100%';
                els.progressBar.style.width = '100%';
                els.progressBar.setAttribute('data-percent', 100);

                await new Promise(r => setTimeout(r, 1600));
                els.progress.style.display = 'none';

                await loadList(state.page, state.search);
                state.processing = false;
            }

            document.addEventListener('click', async e => {
                const t = e.target;

                if (t.closest('.tablenav-pages a')) {
                    e.preventDefault();
                    const page = Number(t.closest('a').dataset.page);
                    if (page) loadList(page);
                    return;
                }

                if (t.classList.contains('single-update')) {
                    e.preventDefault();
                    const id = t.dataset.id;
                    if (id) {
                        scrollToProgress();
                        processItems([id], 'ajax_update_single_app', 'Updating');
                    }
                }

                if (t.classList.contains('single-fastcheck')) {
                    e.preventDefault();
                    const id = t.dataset.id;
                    if (id && confirm(`Fast check app #${id}?`)) {
                        processItems([id], 'ajax_fastcheck_single_app', 'Fast checking');
                    }
                }

                if (t.id === 'check-all-visible' || t.id === 'check-all-visible-bottom') {
                    const ids = [...document.querySelectorAll('#the-list input[name="post[]"]:checked')]
                        .map(el => Number(el.value))
                        .filter(Boolean);

                    if (!ids.length) {
                        alert('No apps selected on this page.');
                        return;
                    }
                    if (confirm(`Fast check ${ids.length} visible app${ids.length === 1 ? '' : 's'}?`)) {
                        processItems(ids, 'ajax_fastcheck_single_app', 'Fast checking');
                    }
                }
            });

            ['#doaction', '#doaction2'].forEach(sel => {
                const btn = document.querySelector(sel);
                if (!btn) return;

                btn.addEventListener('click', async () => {
                    const actionSelect = btn.previousElementSibling;
                    if (!actionSelect?.value || actionSelect.value === '-1') return;

                    const ids = [...document.querySelectorAll('#the-list input[name="post[]"]:checked')]
                        .map(el => Number(el.value))
                        .filter(Boolean);

                    if (!ids.length) {
                        alert('Please select at least one app.');
                        return;
                    }

                    const map = {
                        'update-selected': ['ajax_update_single_app', 'Updating'],
                        'fastcheck-selected': ['ajax_fastcheck_single_app', 'Fast checking'],
                        'fastcheck-debug': ['ajax_fastcheck_single_app', 'Fast checking (DEBUG)', true]
                    };

                    const [action, title, debug = false] = map[actionSelect.value] || [];
                    if (action) {
                        if (action === 'ajax_update_single_app') {
                            scrollToProgress();
                        }
                        processItems(ids, action, title, debug);
                    }
                });
            });

            let searchTimer;
            els.searchInput?.addEventListener('input', function() {
                clearTimeout(searchTimer);
                searchTimer = setTimeout(() => loadList(1, this.value.trim()), 400);
            });

            els.searchInput?.addEventListener('keydown', e => {
                if (e.key === 'Enter') {
                    e.preventDefault();
                    loadList(1, e.currentTarget.value.trim());
                }
            });

            els.searchSubmit?.addEventListener('click', () => loadList(1, els.searchInput?.value.trim() || ''));

            els.searchReset?.addEventListener('click', () => {
                if (els.searchInput) els.searchInput.value = '';
                loadList(1, '');
            });

            ['#cb-select-all-1', '#cb-select-all-2'].forEach(id => {
                document.querySelector(id)?.addEventListener('change', function() {
                    document.querySelectorAll('#the-list input[name="post[]"]').forEach(cb => {
                        cb.checked = this.checked;
                    });
                });
            });

            setInterval(() => {
                if (state.processing || state.search) return;
                ajax.post({
                    action: 'apk_render_updates_list',
                    paged: state.page,
                    s: ''
                }).then(res => {
                    if (res.success && Number(res.data.total || 0) !== state.total) {
                        loadList(state.page);
                    }
                });
            }, 30000);

            loadList(1);
        })();
        </script>
		
<?php
    }
}
