# HVAC Trainer System Troubleshooting Guide

This guide provides solutions for common issues with the HVAC Trainer custom post type and Find A Trainer page functionality.

## Table of Contents

1. [Trainer Profile Issues](#trainer-profile-issues)
2. [Find A Trainer Page Issues](#find-a-trainer-page-issues)
3. [MapGeo Integration Issues](#mapgeo-integration-issues)
4. [Performance Issues](#performance-issues)
5. [Database Issues](#database-issues)
6. [API & AJAX Issues](#api--ajax-issues)
7. [Geocoding Issues](#geocoding-issues)
8. [Permission Issues](#permission-issues)
9. [Debug Tools](#debug-tools)
10. [Known Issues](#known-issues)

## Trainer Profile Issues

### Trainer Profiles Not Appearing

**Symptoms**: Trainer profiles exist but don't show in directory or admin list

**Common Causes**:
1. Profile not set to public
2. User account not approved
3. Missing required meta fields
4. Wrong post status

**Solutions**:

```php
// Check profile visibility
$profile_id = 5840;
$is_public = get_post_meta($profile_id, 'is_public_profile', true);
if ($is_public !== '1') {
    update_post_meta($profile_id, 'is_public_profile', '1');
    echo "Profile set to public";
}

// Check user approval status
$user_id = get_post_meta($profile_id, 'user_id', true);
$user_status = get_user_meta($user_id, 'account_status', true);
if (!in_array($user_status, ['approved', 'active', 'inactive'])) {
    update_user_meta($user_id, 'account_status', 'approved');
    echo "User approved";
}

// Check post status
$post = get_post($profile_id);
if ($post->post_status !== 'publish') {
    wp_update_post([
        'ID' => $profile_id,
        'post_status' => 'publish'
    ]);
    echo "Profile published";
}
```

### Profile Data Not Saving

**Symptoms**: Changes to trainer profiles don't persist

**Common Causes**:
1. Permission issues
2. Nonce verification failures
3. Invalid data validation
4. Database errors

**Solutions**:

```php
// Debug profile save operation
add_action('hvac_trainer_profile_updated', function($profile_id, $old_data, $new_data) {
    error_log("Profile {$profile_id} updated");
    error_log("Old data: " . print_r($old_data, true));
    error_log("New data: " . print_r($new_data, true));
}, 10, 3);

// Check user permissions
if (!current_user_can('edit_hvac_profile')) {
    echo "User lacks edit_hvac_profile capability";
    // Grant capability temporarily for testing
    $user = wp_get_current_user();
    $user->add_cap('edit_hvac_profile');
}

// Test direct meta update
$result = update_post_meta($profile_id, 'trainer_city', 'Test City');
if ($result === false) {
    echo "Failed to update meta field";
} else {
    echo "Meta field updated successfully";
}
```

### Profile Images Not Displaying

**Symptoms**: Profile images appear broken or don't load

**Common Causes**:
1. Invalid image URLs
2. Missing image files
3. Permission issues on uploads
4. SSL/HTTPS conflicts

**Solutions**:

```php
// Validate image URLs
$profile_id = 5840;
$image_url = get_post_meta($profile_id, 'profile_image_url', true);

if (!empty($image_url)) {
    // Check if URL is accessible
    $response = wp_remote_head($image_url);
    if (is_wp_error($response)) {
        echo "Image URL not accessible: " . $response->get_error_message();
    } else {
        $response_code = wp_remote_retrieve_response_code($response);
        if ($response_code !== 200) {
            echo "Image URL returns HTTP {$response_code}";
        } else {
            echo "Image URL is valid and accessible";
        }
    }
    
    // Fix HTTP/HTTPS issues
    if (is_ssl() && strpos($image_url, 'http://') === 0) {
        $fixed_url = str_replace('http://', 'https://', $image_url);
        update_post_meta($profile_id, 'profile_image_url', $fixed_url);
        echo "Fixed HTTPS issue in image URL";
    }
} else {
    echo "No profile image URL set";
}
```

## Find A Trainer Page Issues

### Search Not Working

**Symptoms**: Search functionality returns no results or doesn't respond

**Common Causes**:
1. AJAX endpoints not registered
2. JavaScript errors
3. Nonce verification issues
4. Database query problems

**Solutions**:

```php
// Check AJAX endpoint registration
add_action('wp_ajax_hvac_search_trainers', function() {
    echo "AJAX endpoint registered for logged-in users";
    wp_die();
});

add_action('wp_ajax_nopriv_hvac_search_trainers', function() {
    echo "AJAX endpoint registered for non-logged-in users";
    wp_die();
});

// Debug search query
add_action('wp_ajax_hvac_search_trainers', function() {
    error_log('Search AJAX called with data: ' . print_r($_POST, true));
    
    // Test basic query
    $args = [
        'post_type' => 'trainer_profile',
        'post_status' => 'publish',
        'posts_per_page' => 5
    ];
    
    $query = new WP_Query($args);
    error_log("Basic query found {$query->found_posts} profiles");
    
    wp_send_json_success([
        'found_posts' => $query->found_posts,
        'debug' => true
    ]);
});
```

**JavaScript Debug**:

```javascript
// Test AJAX endpoint
jQuery.ajax({
    url: hvac_find_trainer.ajax_url,
    method: 'POST',
    data: {
        action: 'hvac_search_trainers',
        search: 'test',
        nonce: hvac_find_trainer.nonce
    },
    success: function(response) {
        console.log('Search test successful:', response);
    },
    error: function(jqXHR, textStatus, errorThrown) {
        console.error('Search test failed:', textStatus, errorThrown);
        console.error('Response text:', jqXHR.responseText);
    }
});
```

### Filters Not Working

**Symptoms**: Filter dropdowns don't affect results

**Common Causes**:
1. Taxonomy terms not assigned
2. Filter value mismatches
3. Query argument issues
4. Cache problems

**Solutions**:

```php
// Check taxonomy assignments
$profile_id = 5840;
$business_types = wp_get_post_terms($profile_id, 'business_type', ['fields' => 'names']);

if (empty($business_types)) {
    echo "No business type assigned to profile {$profile_id}";
    
    // Assign a business type for testing
    wp_set_post_terms($profile_id, ['Contractor'], 'business_type');
    echo "Assigned 'Contractor' business type";
} else {
    echo "Business types: " . implode(', ', $business_types);
}

// Debug filter query
function debug_trainer_filter_query($args, $filters) {
    error_log("Filter args: " . print_r($args, true));
    error_log("Applied filters: " . print_r($filters, true));
    
    // Test the query
    $query = new WP_Query($args);
    error_log("Filter query found {$query->found_posts} results");
    
    return $args;
}

add_filter('hvac_trainer_query_args', 'debug_trainer_filter_query', 10, 2);
```

### Pagination Not Working

**Symptoms**: Pagination links don't work or show incorrect page counts

**Common Causes**:
1. Incorrect pagination calculations
2. JavaScript event handling issues
3. AJAX parameter problems

**Solutions**:

```php
// Debug pagination calculations
function debug_pagination($query) {
    if ($query->get('post_type') === 'trainer_profile') {
        error_log("Pagination debug:");
        error_log("Found posts: " . $query->found_posts);
        error_log("Posts per page: " . $query->get('posts_per_page'));
        error_log("Max pages: " . $query->max_num_pages);
        error_log("Current page: " . $query->get('paged'));
    }
}

add_action('pre_get_posts', 'debug_pagination');
```

**JavaScript Debug**:

```javascript
// Test pagination AJAX
jQuery(document).on('click', '.hvac-page-link', function(e) {
    e.preventDefault();
    var page = jQuery(this).data('page');
    
    console.log('Pagination clicked, page:', page);
    
    // Test the AJAX call
    jQuery.ajax({
        url: hvac_find_trainer.ajax_url,
        method: 'POST',
        data: {
            action: 'hvac_filter_trainers',
            filters: HVAC_FindTrainer.config.filters,
            page: page,
            per_page: 12,
            nonce: hvac_find_trainer.nonce
        },
        success: function(response) {
            console.log('Pagination AJAX success:', response);
        },
        error: function(jqXHR, textStatus, errorThrown) {
            console.error('Pagination AJAX failed:', textStatus, errorThrown);
        }
    });
});
```

## MapGeo Integration Issues

### Markers Not Appearing on Map

**Symptoms**: Map loads but no trainer markers are visible

**Common Causes**:
1. Missing geocoding data (latitude/longitude)
2. MapGeo configuration issues
3. Profile visibility settings
4. Map ID mismatch

**Solutions**:

```php
// Check geocoding status for all trainers
function check_geocoding_status() {
    $args = [
        'post_type' => 'trainer_profile',
        'post_status' => 'publish',
        'posts_per_page' => -1
    ];
    
    $query = new WP_Query($args);
    $total = $query->found_posts;
    $geocoded = 0;
    $missing_coords = [];
    
    while ($query->have_posts()) {
        $query->the_post();
        $profile_id = get_the_ID();
        
        $lat = get_post_meta($profile_id, 'geocoded_lat', true);
        $lng = get_post_meta($profile_id, 'geocoded_lng', true);
        
        if (!empty($lat) && !empty($lng)) {
            $geocoded++;
        } else {
            $missing_coords[] = [
                'id' => $profile_id,
                'title' => get_the_title(),
                'city' => get_post_meta($profile_id, 'trainer_city', true),
                'state' => get_post_meta($profile_id, 'trainer_state', true)
            ];
        }
    }
    
    wp_reset_postdata();
    
    echo "Geocoding Status Report:\n";
    echo "Total profiles: {$total}\n";
    echo "Geocoded profiles: {$geocoded}\n";
    echo "Missing coordinates: " . count($missing_coords) . "\n";
    
    if (!empty($missing_coords)) {
        echo "\nProfiles missing coordinates:\n";
        foreach ($missing_coords as $profile) {
            echo "- {$profile['title']} (ID: {$profile['id']}) - {$profile['city']}, {$profile['state']}\n";
        }
    }
}

// Run the check
check_geocoding_status();

// Trigger geocoding for profiles missing coordinates
function fix_missing_geocoding() {
    $args = [
        'post_type' => 'trainer_profile',
        'post_status' => 'publish',
        'posts_per_page' => -1,
        'meta_query' => [
            'relation' => 'OR',
            [
                'key' => 'geocoded_lat',
                'compare' => 'NOT EXISTS'
            ],
            [
                'key' => 'geocoded_lng',
                'compare' => 'NOT EXISTS'
            ]
        ]
    ];
    
    $query = new WP_Query($args);
    
    if (class_exists('HVAC_Geocoding_Service')) {
        $geocoding = HVAC_Geocoding_Service::get_instance();
        
        while ($query->have_posts()) {
            $query->the_post();
            $profile_id = get_the_ID();
            
            echo "Attempting to geocode profile {$profile_id}...";
            $result = $geocoding->geocode_trainer($profile_id);
            
            if ($result) {
                echo " SUCCESS\n";
            } else {
                echo " FAILED\n";
            }
            
            // Rate limiting
            sleep(1);
        }
    }
    
    wp_reset_postdata();
}
```

### Map Modal Not Opening

**Symptoms**: Clicking map markers doesn't open trainer modals

**Common Causes**:
1. JavaScript errors preventing modal system
2. Missing trainer data in modal correlation
3. Champions (intentionally don't show modals)
4. MapGeo custom action configuration

**Solutions**:

```javascript
// Debug modal system
console.log('MapGeo Integration Debug:');
console.log('hvac_show_trainer_modal function:', typeof window.hvac_show_trainer_modal);
console.log('showTrainerModal function:', typeof window.showTrainerModal);
console.log('Cache object exists:', typeof window.hvacTrainerDataCache);

// Test modal function directly
if (typeof window.hvac_show_trainer_modal === 'function') {
    // Test with sample data
    window.hvac_show_trainer_modal({
        hvac_profile_id: '5840',
        id: 'trainer_5840',
        title: 'Test Trainer'
    });
} else {
    console.error('hvac_show_trainer_modal function not found');
}

// Check for JavaScript errors
window.addEventListener('error', function(e) {
    if (e.filename && e.filename.includes('mapgeo')) {
        console.error('MapGeo JavaScript error:', e.message, e.filename, e.lineno);
    }
});

// Debug marker click events
jQuery(document).on('click', '.imapsSprite-group, .imapsMapObject-group, [class*="imaps"], circle', function(e) {
    console.log('Marker clicked:', this);
    console.log('Last MapGeo data:', window.lastMapGeoTrainerData);
});
```

**PHP Debug**:

```php
// Check MapGeo map configuration
add_filter('igm_add_meta', function($meta, $map_id) {
    if ($map_id == '5872') { // Your map ID
        error_log("MapGeo meta data for map {$map_id}:");
        error_log(print_r($meta, true));
        
        // Check if markers have trainer data
        if (isset($meta['markers'])) {
            foreach ($meta['markers'] as $i => $marker) {
                if (isset($marker['hvac_profile_id'])) {
                    error_log("Marker {$i} has trainer profile ID: " . $marker['hvac_profile_id']);
                } else {
                    error_log("Marker {$i} missing trainer profile ID");
                }
            }
        }
    }
    return $meta;
}, 10, 2);
```

### Modal Performance Issues

**Symptoms**: Modal takes >5 seconds to load or shows multiple AJAX requests

**Common Causes**:
1. Duplicate AJAX requests
2. Missing caching
3. Complex fallback logic

**Solutions**:

```javascript
// Check for duplicate requests
var requestTracker = {};

// Override jQuery.ajax to track requests
var originalAjax = jQuery.ajax;
jQuery.ajax = function(options) {
    if (options.data && options.data.action === 'hvac_get_trainer_profile') {
        var profileId = options.data.profile_id;
        var requestKey = 'profile_' + profileId;
        
        if (requestTracker[requestKey]) {
            console.warn('Duplicate AJAX request prevented for profile:', profileId);
            return requestTracker[requestKey];
        }
        
        console.log('New AJAX request for profile:', profileId);
        requestTracker[requestKey] = originalAjax.call(this, options);
        
        // Clean up after request completes
        requestTracker[requestKey].always(function() {
            delete requestTracker[requestKey];
        });
        
        return requestTracker[requestKey];
    }
    
    return originalAjax.call(this, options);
};

// Monitor cache usage
setInterval(function() {
    if (window.hvacTrainerDataCache) {
        var cacheSize = Object.keys(window.hvacTrainerDataCache).length;
        console.log('Trainer data cache size:', cacheSize);
    }
}, 5000);
```

## Performance Issues

### Slow Page Loading

**Symptoms**: Find A Trainer page loads slowly

**Common Causes**:
1. Large number of trainer profiles
2. Inefficient database queries
3. Missing indexes
4. Large images

**Solutions**:

```php
// Add database indexes for better performance
function add_trainer_performance_indexes() {
    global $wpdb;
    
    // Index for trainer profile queries
    $wpdb->query("
        CREATE INDEX IF NOT EXISTS idx_postmeta_trainer_queries 
        ON {$wpdb->postmeta} (meta_key, meta_value(50), post_id)
    ");
    
    // Index for geocoded trainer queries
    $wpdb->query("
        CREATE INDEX IF NOT EXISTS idx_posts_trainer_type_status 
        ON {$wpdb->posts} (post_type, post_status, post_date)
    ");
    
    echo "Performance indexes added";
}

// Optimize trainer queries with caching
function get_cached_trainers($args) {
    $cache_key = 'hvac_trainers_' . md5(serialize($args));
    $trainers = wp_cache_get($cache_key, 'hvac_trainers');
    
    if (false === $trainers) {
        $query = new WP_Query($args);
        $trainers = [];
        
        while ($query->have_posts()) {
            $query->the_post();
            $trainers[] = [
                'id' => get_the_ID(),
                'title' => get_the_title(),
                'city' => get_post_meta(get_the_ID(), 'trainer_city', true),
                // ... other fields
            ];
        }
        wp_reset_postdata();
        
        wp_cache_set($cache_key, $trainers, 'hvac_trainers', HOUR_IN_SECONDS);
    }
    
    return $trainers;
}

// Profile query optimization
function optimize_trainer_profile_queries($args) {
    // Use 'fields' => 'ids' when only IDs are needed
    if (!isset($args['fields'])) {
        $args['fields'] = 'ids';
    }
    
    // Add specific meta_query structure for better index usage
    if (isset($args['meta_query'])) {
        // Ensure is_public_profile check is first for index efficiency
        usort($args['meta_query'], function($a, $b) {
            if (isset($a['key']) && $a['key'] === 'is_public_profile') {
                return -1;
            }
            if (isset($b['key']) && $b['key'] === 'is_public_profile') {
                return 1;
            }
            return 0;
        });
    }
    
    return $args;
}

add_filter('hvac_trainer_query_args', 'optimize_trainer_profile_queries');
```

### Memory Issues

**Symptoms**: PHP memory limit exceeded or slow performance

**Solutions**:

```php
// Monitor memory usage
function check_memory_usage($context = '') {
    $memory_used = memory_get_usage(true);
    $memory_peak = memory_get_peak_usage(true);
    $memory_limit = ini_get('memory_limit');
    
    error_log("Memory usage {$context}: " . 
        "Current: " . size_format($memory_used) . 
        ", Peak: " . size_format($memory_peak) . 
        ", Limit: {$memory_limit}");
}

// Optimize large trainer queries
function get_trainers_in_batches($total_needed = -1, $batch_size = 50) {
    $trainers = [];
    $page = 1;
    
    do {
        $args = [
            'post_type' => 'trainer_profile',
            'post_status' => 'publish',
            'posts_per_page' => $batch_size,
            'paged' => $page,
            'fields' => 'ids'
        ];
        
        $query = new WP_Query($args);
        
        foreach ($query->posts as $profile_id) {
            $trainers[] = $profile_id;
            
            if ($total_needed > 0 && count($trainers) >= $total_needed) {
                break 2;
            }
        }
        
        wp_reset_postdata();
        $page++;
        
        check_memory_usage("after batch {$page}");
        
    } while ($query->have_posts() && ($total_needed < 0 || count($trainers) < $total_needed));
    
    return $trainers;
}
```

## Database Issues

### Missing Meta Fields

**Symptoms**: Trainer data appears incomplete or missing

**Solutions**:

```php
// Audit trainer profile meta fields
function audit_trainer_meta_fields() {
    $required_fields = [
        'user_id',
        'trainer_display_name',
        'trainer_city',
        'trainer_state',
        'is_public_profile',
        'certification_type'
    ];
    
    $args = [
        'post_type' => 'trainer_profile',
        'post_status' => 'publish',
        'posts_per_page' => -1,
        'fields' => 'ids'
    ];
    
    $profiles = get_posts($args);
    $issues = [];
    
    foreach ($profiles as $profile_id) {
        $profile_issues = [];
        
        foreach ($required_fields as $field) {
            $value = get_post_meta($profile_id, $field, true);
            if (empty($value)) {
                $profile_issues[] = $field;
            }
        }
        
        if (!empty($profile_issues)) {
            $issues[$profile_id] = [
                'title' => get_the_title($profile_id),
                'missing_fields' => $profile_issues
            ];
        }
    }
    
    if (!empty($issues)) {
        echo "Profiles with missing meta fields:\n";
        foreach ($issues as $profile_id => $issue) {
            echo "Profile {$profile_id} ({$issue['title']}): " . 
                implode(', ', $issue['missing_fields']) . "\n";
        }
    } else {
        echo "All profiles have required meta fields\n";
    }
    
    return $issues;
}

// Fix common meta field issues
function fix_trainer_meta_issues() {
    $profiles = get_posts([
        'post_type' => 'trainer_profile',
        'post_status' => 'publish',
        'posts_per_page' => -1,
        'fields' => 'ids'
    ]);
    
    foreach ($profiles as $profile_id) {
        $updated = false;
        
        // Fix missing display name
        $display_name = get_post_meta($profile_id, 'trainer_display_name', true);
        if (empty($display_name)) {
            $post_title = get_the_title($profile_id);
            if (!empty($post_title)) {
                update_post_meta($profile_id, 'trainer_display_name', $post_title);
                $updated = true;
            }
        }
        
        // Fix missing public profile flag
        $is_public = get_post_meta($profile_id, 'is_public_profile', true);
        if ($is_public === '') {
            update_post_meta($profile_id, 'is_public_profile', '1');
            $updated = true;
        }
        
        // Fix missing certification type
        $cert_type = get_post_meta($profile_id, 'certification_type', true);
        if (empty($cert_type)) {
            update_post_meta($profile_id, 'certification_type', 'HVAC Trainer');
            $updated = true;
        }
        
        if ($updated) {
            echo "Fixed meta fields for profile {$profile_id}\n";
        }
    }
}
```

### Taxonomy Issues

**Symptoms**: Filters not working, missing taxonomy terms

**Solutions**:

```php
// Check taxonomy registration
function check_trainer_taxonomies() {
    $taxonomies = ['business_type', 'training_formats', 'training_resources', 'training_audience'];
    
    foreach ($taxonomies as $taxonomy) {
        if (taxonomy_exists($taxonomy)) {
            $terms = get_terms([
                'taxonomy' => $taxonomy,
                'hide_empty' => false
            ]);
            
            echo "Taxonomy '{$taxonomy}': " . count($terms) . " terms\n";
            
            if (empty($terms)) {
                echo "  WARNING: No terms found for {$taxonomy}\n";
            }
        } else {
            echo "ERROR: Taxonomy '{$taxonomy}' not registered\n";
        }
    }
}

// Create missing taxonomy terms
function create_default_taxonomy_terms() {
    $taxonomies = [
        'business_type' => [
            'Manufacturer',
            'Distributor', 
            'Contractor',
            'Consultant',
            'Educator',
            'Government',
            'Other'
        ],
        'training_formats' => [
            'In-person',
            'Virtual',
            'Hybrid',
            'On-demand'
        ],
        'training_resources' => [
            'Classroom',
            'Training Lab',
            'Online Platform',
            'Custom Curriculum'
        ]
    ];
    
    foreach ($taxonomies as $taxonomy => $terms) {
        if (taxonomy_exists($taxonomy)) {
            foreach ($terms as $term) {
                if (!term_exists($term, $taxonomy)) {
                    $result = wp_insert_term($term, $taxonomy);
                    if (!is_wp_error($result)) {
                        echo "Created term '{$term}' in taxonomy '{$taxonomy}'\n";
                    }
                }
            }
        }
    }
}
```

## API & AJAX Issues

### AJAX Endpoints Not Working

**Symptoms**: AJAX requests return 404 or 400 errors

**Solutions**:

```php
// Debug AJAX endpoint registration
function debug_ajax_endpoints() {
    global $wp_filter;
    
    $ajax_actions = [
        'hvac_get_trainer_profile',
        'hvac_filter_trainers', 
        'hvac_search_trainers',
        'hvac_get_trainer_certification'
    ];
    
    foreach ($ajax_actions as $action) {
        // Check logged-in user endpoints
        $logged_in_hook = "wp_ajax_{$action}";
        if (isset($wp_filter[$logged_in_hook])) {
            echo "✓ {$logged_in_hook} registered\n";
        } else {
            echo "✗ {$logged_in_hook} NOT registered\n";
        }
        
        // Check non-logged-in user endpoints
        $public_hook = "wp_ajax_nopriv_{$action}";
        if (isset($wp_filter[$public_hook])) {
            echo "✓ {$public_hook} registered\n";
        } else {
            echo "✗ {$public_hook} NOT registered\n";
        }
    }
}

// Test AJAX endpoint manually
function test_ajax_endpoint($action, $data = []) {
    // Simulate AJAX request
    $_POST = array_merge([
        'action' => $action,
        'nonce' => wp_create_nonce('hvac_find_trainer')
    ], $data);
    
    // Capture output
    ob_start();
    do_action("wp_ajax_{$action}");
    do_action("wp_ajax_nopriv_{$action}");
    $output = ob_get_clean();
    
    echo "AJAX Test for '{$action}':\n";
    echo "Output: {$output}\n";
    
    // Clean up
    $_POST = [];
}

// Usage
test_ajax_endpoint('hvac_get_trainer_profile', ['profile_id' => 5840]);
```

### Nonce Verification Failures

**Symptoms**: AJAX requests fail with "Invalid nonce" errors

**Solutions**:

```php
// Debug nonce issues
function debug_nonce_verification() {
    $action = 'hvac_find_trainer';
    $nonce = wp_create_nonce($action);
    
    echo "Generated nonce: {$nonce}\n";
    echo "Nonce action: {$action}\n";
    echo "Current user ID: " . get_current_user_id() . "\n";
    
    // Test verification
    $verify_result = wp_verify_nonce($nonce, $action);
    echo "Verification result: " . ($verify_result ? 'PASS' : 'FAIL') . "\n";
    
    // Check nonce in JavaScript context
    echo "JavaScript nonce check:\n";
    ?>
    <script>
    console.log('Frontend nonce:', hvac_find_trainer.nonce);
    console.log('Nonce matches:', hvac_find_trainer.nonce === '<?php echo $nonce; ?>');
    </script>
    <?php
}

// Fix nonce issues in AJAX
function fix_ajax_nonce_handling() {
    add_action('wp_ajax_hvac_get_trainer_profile', function() {
        $nonce = $_POST['nonce'] ?? '';
        $action = 'hvac_find_trainer';
        
        error_log("Nonce verification attempt:");
        error_log("Received nonce: {$nonce}");
        error_log("Expected action: {$action}");
        error_log("User ID: " . get_current_user_id());
        
        $verify_result = wp_verify_nonce($nonce, $action);
        error_log("Verification result: " . ($verify_result ? 'PASS' : 'FAIL'));
        
        if (!$verify_result) {
            wp_send_json_error([
                'message' => 'Nonce verification failed',
                'debug' => [
                    'received_nonce' => $nonce,
                    'expected_action' => $action,
                    'user_id' => get_current_user_id()
                ]
            ]);
            return;
        }
        
        // Continue with normal processing...
    });
}
```

## Geocoding Issues

### Trainers Not Being Geocoded

**Symptoms**: Trainer profiles missing latitude/longitude coordinates

**Solutions**:

```php
// Check Google Maps API configuration
function check_geocoding_setup() {
    $api_key = get_option('hvac_google_maps_api_key');
    
    if (empty($api_key)) {
        echo "ERROR: Google Maps API key not configured\n";
        echo "Set it with: update_option('hvac_google_maps_api_key', 'your_key_here');\n";
        return false;
    }
    
    echo "Google Maps API key configured: " . substr($api_key, 0, 10) . "...\n";
    
    // Test API key with a simple request
    $test_address = 'Chicago, IL';
    $response = wp_remote_get('https://maps.googleapis.com/maps/api/geocode/json?' . http_build_query([
        'address' => $test_address,
        'key' => $api_key
    ]));
    
    if (is_wp_error($response)) {
        echo "ERROR: API request failed: " . $response->get_error_message() . "\n";
        return false;
    }
    
    $data = json_decode(wp_remote_retrieve_body($response), true);
    
    if (isset($data['status'])) {
        echo "API test result: {$data['status']}\n";
        
        if ($data['status'] === 'OK') {
            echo "✓ Geocoding API is working correctly\n";
            return true;
        } else {
            echo "✗ API Error: " . ($data['error_message'] ?? 'Unknown error') . "\n";
            return false;
        }
    }
    
    return false;
}

// Manual geocoding test
function test_geocoding_for_profile($profile_id) {
    echo "Testing geocoding for profile {$profile_id}...\n";
    
    $city = get_post_meta($profile_id, 'trainer_city', true);
    $state = get_post_meta($profile_id, 'trainer_state', true);
    
    if (empty($city) || empty($state)) {
        echo "ERROR: Missing city or state data\n";
        return false;
    }
    
    $address = "{$city}, {$state}";
    echo "Address to geocode: {$address}\n";
    
    $api_key = get_option('hvac_google_maps_api_key');
    if (empty($api_key)) {
        echo "ERROR: No API key configured\n";
        return false;
    }
    
    $response = wp_remote_get('https://maps.googleapis.com/maps/api/geocode/json?' . http_build_query([
        'address' => $address,
        'key' => $api_key
    ]));
    
    if (is_wp_error($response)) {
        echo "ERROR: " . $response->get_error_message() . "\n";
        return false;
    }
    
    $data = json_decode(wp_remote_retrieve_body($response), true);
    
    if ($data['status'] === 'OK' && !empty($data['results'][0])) {
        $location = $data['results'][0]['geometry']['location'];
        $lat = $location['lat'];
        $lng = $location['lng'];
        
        echo "✓ Geocoding successful: {$lat}, {$lng}\n";
        
        // Save coordinates
        update_post_meta($profile_id, 'geocoded_lat', $lat);
        update_post_meta($profile_id, 'geocoded_lng', $lng);
        update_post_meta($profile_id, '_last_geocode_attempt', time());
        
        echo "✓ Coordinates saved to profile\n";
        return true;
    } else {
        echo "✗ Geocoding failed: {$data['status']}\n";
        if (isset($data['error_message'])) {
            echo "Error: {$data['error_message']}\n";
        }
        return false;
    }
}

// Batch geocoding with rate limiting
function batch_geocode_missing_profiles($limit = 10) {
    $profiles = get_posts([
        'post_type' => 'trainer_profile',
        'post_status' => 'publish',
        'posts_per_page' => $limit,
        'meta_query' => [
            'relation' => 'OR',
            [
                'key' => 'geocoded_lat',
                'compare' => 'NOT EXISTS'
            ],
            [
                'key' => 'geocoded_lng', 
                'compare' => 'NOT EXISTS'
            ]
        ],
        'fields' => 'ids'
    ]);
    
    echo "Found " . count($profiles) . " profiles needing geocoding\n";
    
    foreach ($profiles as $profile_id) {
        $title = get_the_title($profile_id);
        echo "\nProcessing: {$title} (ID: {$profile_id})\n";
        
        test_geocoding_for_profile($profile_id);
        
        // Rate limiting - wait 1 second between requests
        sleep(1);
    }
    
    echo "\nBatch geocoding complete\n";
}
```

## Permission Issues

### Users Can't Edit Profiles

**Symptoms**: Trainers can't access or edit their profiles

**Solutions**:

```php
// Check user capabilities
function check_trainer_capabilities($user_id = null) {
    if (!$user_id) {
        $user_id = get_current_user_id();
    }
    
    $user = get_user_by('id', $user_id);
    if (!$user) {
        echo "User not found\n";
        return;
    }
    
    echo "User: {$user->display_name} (ID: {$user_id})\n";
    echo "Roles: " . implode(', ', $user->roles) . "\n";
    
    $required_caps = [
        'read',
        'edit_hvac_profile',
        'view_hvac_dashboard',
        'manage_hvac_events'
    ];
    
    foreach ($required_caps as $cap) {
        $has_cap = user_can($user_id, $cap);
        echo "Capability '{$cap}': " . ($has_cap ? '✓' : '✗') . "\n";
        
        if (!$has_cap) {
            // Grant capability for testing
            $user->add_cap($cap);
            echo "  → Granted capability '{$cap}'\n";
        }
    }
}

// Fix role capabilities
function fix_trainer_role_capabilities() {
    $trainer_role = get_role('hvac_trainer');
    $master_role = get_role('hvac_master_trainer');
    
    if (!$trainer_role) {
        echo "Creating hvac_trainer role...\n";
        $trainer_role = add_role('hvac_trainer', 'HVAC Trainer', [
            'read' => true,
            'edit_hvac_profile' => true,
            'view_hvac_dashboard' => true,
            'manage_hvac_events' => true,
            'upload_files' => true
        ]);
    }
    
    if (!$master_role) {
        echo "Creating hvac_master_trainer role...\n";
        $master_role = add_role('hvac_master_trainer', 'HVAC Master Trainer', [
            'read' => true,
            'edit_hvac_profile' => true,
            'view_hvac_dashboard' => true,
            'manage_hvac_events' => true,
            'upload_files' => true,
            'hvac_master_trainer' => true
        ]);
    }
    
    // Add missing capabilities
    $trainer_caps = [
        'edit_hvac_profile',
        'view_hvac_dashboard',
        'manage_hvac_events',
        'manage_attendees',
        'email_attendees'
    ];
    
    foreach ($trainer_caps as $cap) {
        if ($trainer_role && !$trainer_role->has_cap($cap)) {
            $trainer_role->add_cap($cap);
            echo "Added '{$cap}' to hvac_trainer role\n";
        }
        
        if ($master_role && !$master_role->has_cap($cap)) {
            $master_role->add_cap($cap);
            echo "Added '{$cap}' to hvac_master_trainer role\n";
        }
    }
}
```

## Debug Tools

### Enable Debug Logging

```php
// Add to wp-config.php
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
define('WP_DEBUG_DISPLAY', false);
define('HVAC_DEBUG', true);

// Custom debug logging
function hvac_debug_log($message, $context = '') {
    if (defined('HVAC_DEBUG') && HVAC_DEBUG) {
        $timestamp = date('Y-m-d H:i:s');
        $log_message = "[{$timestamp}] HVAC Debug";
        
        if (!empty($context)) {
            $log_message .= " ({$context})";
        }
        
        $log_message .= ": {$message}";
        
        error_log($log_message);
    }
}

// Usage
hvac_debug_log('Trainer profile created: ' . $profile_id, 'Profile Manager');
```

### Debug Information Panel

```php
// Add debug info to admin
function hvac_add_debug_panel() {
    if (current_user_can('manage_options') && isset($_GET['hvac_debug'])) {
        echo '<div style="background: #f1f1f1; padding: 20px; margin: 20px 0; border: 1px solid #ccc;">';
        echo '<h3>HVAC Trainer System Debug Info</h3>';
        
        // Plugin version
        echo '<p><strong>Plugin Version:</strong> ' . (defined('HVAC_PLUGIN_VERSION') ? HVAC_PLUGIN_VERSION : 'Unknown') . '</p>';
        
        // Active trainers
        $trainer_count = wp_count_posts('trainer_profile');
        echo '<p><strong>Total Trainer Profiles:</strong> ' . $trainer_count->publish . '</p>';
        
        // Geocoded trainers
        $geocoded = get_posts([
            'post_type' => 'trainer_profile',
            'posts_per_page' => -1,
            'meta_query' => [
                'relation' => 'AND',
                ['key' => 'geocoded_lat', 'compare' => 'EXISTS'],
                ['key' => 'geocoded_lng', 'compare' => 'EXISTS']
            ],
            'fields' => 'ids'
        ]);
        echo '<p><strong>Geocoded Trainers:</strong> ' . count($geocoded) . '</p>';
        
        // MapGeo integration
        echo '<p><strong>MapGeo Active:</strong> ' . (class_exists('HVAC_MapGeo_Integration') ? 'Yes' : 'No') . '</p>';
        
        // Google Maps API
        $api_key = get_option('hvac_google_maps_api_key');
        echo '<p><strong>Google Maps API:</strong> ' . (!empty($api_key) ? 'Configured' : 'Not Configured') . '</p>';
        
        echo '</div>';
    }
}

add_action('admin_notices', 'hvac_add_debug_panel');
```

## Known Issues

### MapGeo Certification Color Field Bug

**Issue**: When `certification_color` field is mapped to MapGeo "Fill Colour", markers disappear completely.

**Workaround**: Remove `certification_color` from MapGeo Fill Colour mapping. Colors are handled programmatically instead.

**Status**: Documented as known bug. MapGeo plugin has compatibility issues with custom color fields.

### Champions Don't Show Modals

**Issue**: measureQuick Champions don't show modal popups when clicked on map.

**Status**: This is intentional behavior. Only Certified measureQuick Trainers show modals. Champions are directory-only display.

### High Memory Usage with Large Datasets

**Issue**: Sites with 500+ trainer profiles may experience memory issues.

**Workaround**: 
- Implement pagination with smaller page sizes
- Use query optimization techniques
- Consider caching strategies
- Use `fields => 'ids'` in queries when possible

This troubleshooting guide covers the most common issues encountered with the HVAC Trainer system. For additional support, enable debug logging and use the provided debug tools to gather more specific information about your particular issue.