<?php
/**
 * Committee functionality for Member Minder Pro plugin
 * 
 * This file contains the committees shortcode implementation.
 * It requires the following global variables to be set:
 * - $data_path: Path to data files
 * - $file_path: Path to file storage
 * - $options: Plugin options
 */

if (!defined('ABSPATH')) {
    exit; // Exit if accessed directly
}

/**
 * Register committee scripts and styles
 */
function mmpro_register_committees_assets() {
    // Register styles
    wp_register_style('mmpro-committees-style', plugins_url('css/show-committees.css', dirname(__FILE__)), array(), MMPDB_PLUGIN_VERSION);
    
    // Register ColorBox if not already registered
    if (!wp_script_is('jquery-colorbox', 'registered')) {
        $colorbox_cdn_js = 'https://cdn.jsdelivr.net/gh/jackmoore/colorbox@1.6.4/jquery.colorbox-min.js';
        $colorbox_cdn_css = 'https://cdn.jsdelivr.net/gh/jackmoore/colorbox@1.6.4/example1/colorbox.css';
        
        if (url_exists($colorbox_cdn_js) && url_exists($colorbox_cdn_css)) {
            wp_register_script('jquery-colorbox', $colorbox_cdn_js, array('jquery'), '1.6.4', true);
            wp_register_style('jquery-colorbox-style', $colorbox_cdn_css, array(), '1.6.4');
        } else {
            wp_register_script('jquery-colorbox', plugins_url('js/vendor/jquery.colorbox-min.js', dirname(__FILE__)), array('jquery'), '1.6.4', true);
            wp_register_style('jquery-colorbox-style', plugins_url('css/vendor/colorbox.css', dirname(__FILE__)), array(), '1.6.4');
        }
    }
}

// Register assets on init
add_action('init', 'mmpro_register_committees_assets');

// Register cron hook for committee cache warming
add_action('mmpro_warm_committee_cache', 'mmpro_warm_committee_cache');

// Include the member display functionality
require_once dirname(__FILE__) . '/display/member-cards.php';

/**
 * Helper function to get columns value for committee display
 */
function mmpro_get_committee_columns($get_params, $atts, $options) {
    if (isset($get_params['committee_members_per_row'])) return (int)$get_params['committee_members_per_row'];
    if (isset($get_params['cols'])) return (int)$get_params['cols'];
    if (isset($get_params['rows'])) return (int)$get_params['rows'];
    if (isset($get_params['cards'])) return (int)$get_params['cards'];
    if (isset($get_params['members_per_row'])) return (int)$get_params['members_per_row'];
    if (isset($atts['committee_members_per_row'])) return (int)$atts['committee_members_per_row'];
    if (isset($atts['cols'])) return (int)$atts['cols'];
    if (isset($atts['rows'])) return (int)$atts['rows'];
    if (isset($atts['cards'])) return (int)$atts['cards'];
    if (isset($atts['members_per_row'])) return (int)$atts['members_per_row'];
    if (isset($options['committee_members_per_row'])) return (int)$options['committee_members_per_row'];
    return 2;
}

/**
 * Helper function to check if API response indicates committee exists but has no members
 */
function mmpro_is_empty_committee_response($response) {
    $trimmed_response = trim($response);
    
    // Check for completely empty response
    if (empty($trimmed_response) || strlen($trimmed_response) == 0) {
        return true;
    }
    
    // Check for XML declaration only
    if ($trimmed_response === '<?xml version="1.0" encoding="UTF-8"?>' ||
        $trimmed_response === '<?xml version="1.0" encoding="utf-8"?>' ||
        $trimmed_response === '<?xml version="1.0"?>') {
        return true;
    }
    
    // Check for empty committee elements
    if (strpos($trimmed_response, '<committeemembers></committeemembers>') !== false ||
        strpos($trimmed_response, '<committeemembers/>') !== false ||
        strpos($trimmed_response, '<committee></committee>') !== false ||
        strpos($trimmed_response, '<committee/>') !== false) {
        return true;
    }
    
    return false;
}

/**
 * Helper function to check if a committee has members (with caching)
 */
function mmpro_committee_has_members($committee_id, $options) {
    global $data_path;
    
    // Create a unique cache key for this committee
    $cache_key = 'mmpro_committee_members_' . $options['dacdb_district'] . '_' . $options['dacdb_club'] . '_' . $committee_id;
    
    // Try to get cached result first
    $cached_result = get_transient($cache_key);
    if ($cached_result !== false) {
        return $cached_result;
    }
    
    // If not cached, make API call to check
    $api_url = $data_path . 'wp_ByID.cfm?AccountID=' . $options['dacdb_district'] . '&ClubID=' . $options['dacdb_club'] . '&id=' . $committee_id . '&R=' . rand();
    $response = file_get_contents($api_url);
    
    // Check if response indicates no members
    $has_members = !mmpro_is_empty_committee_response($response);
    
    // Cache the result for 1 hour (3600 seconds)
    set_transient($cache_key, $has_members, 3600);
    
    return $has_members;
}

/**
 * Helper function to schedule background cache warming for committees
 */
function mmpro_schedule_committee_cache_warming($options) {
    // Check if we've already scheduled warming recently
    $warming_key = 'mmpro_committee_warming_' . $options['dacdb_district'] . '_' . $options['dacdb_club'];
    $last_warmed = get_transient($warming_key);
    
    // Only schedule if we haven't warmed in the last hour
    if ($last_warmed === false) {
        // Schedule background warming for 5 minutes from now
        wp_schedule_single_event(time() + 300, 'mmpro_warm_committee_cache', array($options));
        
        // Mark that we've scheduled warming
        set_transient($warming_key, time(), 3600);
    }
}

/**
 * Background process to warm committee member cache
 */
function mmpro_warm_committee_cache($options) {
    global $data_path;
    
    // Get list of all committees
    $committees_url = $data_path . 'wp_committees.cfm?AccountID=' . $options['dacdb_district'] . '&ClubID=' . $options['dacdb_club'] . '&R=' . rand();
    $committees_xml = dacdb_load_xml($committees_url, 'committees');
    
    if ($committees_xml === false || strlen($committees_xml) == 0) {
        return;
    }
    
    // Process each committee (with memory safety)
    foreach ($committees_xml->committee as $committee) {
        $committee_id = (string)$committee->committeeid;
        
        // Skip if already cached
        $cache_key = 'mmpro_committee_members_' . $options['dacdb_district'] . '_' . $options['dacdb_club'] . '_' . $committee_id;
        if (get_transient($cache_key) !== false) {
            continue;
        }
        
        // Check memory usage before processing
        $memory_limit = ini_get('memory_limit');
        $memory_usage = memory_get_usage(true);
        
        // If memory usage is high, stop processing
        if ($memory_usage > 64 * 1024 * 1024) { // 64MB limit
            break;
        }
        
        // Make API call to check member status
        $api_url = $data_path . 'wp_ByID.cfm?AccountID=' . $options['dacdb_district'] . '&ClubID=' . $options['dacdb_club'] . '&id=' . $committee_id . '&R=' . rand();
        $response = file_get_contents($api_url);
        
        // Cache the result
        $has_members = !mmpro_is_empty_committee_response($response);
        set_transient($cache_key, $has_members, 3600);
        
        // Small delay to prevent overwhelming the API
        usleep(100000); // 0.1 second delay
    }
}

/**
 * Main committees shortcode function
 */
function dacdb_committees($atts)
{
    global $data_path, $file_path, $options;

    // Ensure assets are registered (in case init hook hasn't run)
    if (!wp_script_is('mmpro-committees-style', 'registered')) {
        mmpro_register_committees_assets();
    }

    // Enqueue required styles and scripts
    wp_enqueue_style('mmpro-committees-style');
    wp_enqueue_style('jquery-colorbox-style');
    wp_enqueue_script('jquery-colorbox');

    $committees = ''; // Initialize an empty string to store the generated list of committees.

    $account_id = $options['dacdb_district']; // Retrieve the district account ID from options.
    $club_id    = $options['dacdb_club']; // Retrieve the club ID from options.

    $description = $_GET['description'] ?? $atts['description'] ?? $options['committee_global_description'] ?? '0';

    $orgyear = isset($atts['orgyear']) ? $atts['orgyear'] : ''; // Retrieve the "orgyear" attribute from the function arguments.
    $members = isset($_GET["members"]) ? $_GET["members"] : ''; // Get the "members" value from the query string parameters.
    
    // Get the committee members display setting
    $show_members = isset($atts['show_members']) ? $atts['show_members'] : 
                   (isset($options['committee_show_members']) ? $options['committee_show_members'] : '2');

    $options['committee_members_per_row'] ??= 1;
    $current_url = "";

    // If members display is disabled, ignore the members parameter
    if ($show_members === '0') {
        $members = '';
    }

    if ($members) {
        // List members on the selected committee.
        $counter = 1;
        $grid_counter = 0;

        // Ensure $members is a string, not an array
        $committee_id = is_array($members) ? implode(',', $members) : $members;

        $response = file_get_contents($data_path . 'wp_ByID.cfm?AccountID=' . $options['dacdb_district'] . '&ClubID=' . $options['dacdb_club'] . '&id=' . $committee_id . '&R=' . rand());

        // Log the API URL and response for debugging
        error_log('DACdb Plus: API URL - ' . $data_path . 'wp_ByID.cfm?AccountID=' . $options['dacdb_district'] . '&ClubID=' . $options['dacdb_club'] . '&id=' . $committee_id);
        error_log('DACdb Plus: Raw API Response - ' . substr($response, 0, 1000)); // Log first 1000 chars to avoid huge logs

        // Try to detect if response is JSON or XML
        $first_char = substr(trim($response), 0, 1);
        if ($first_char === '{' || $first_char === '[') {
            // Response is JSON
            $data = json_decode($response);
            if (!$data) {
                error_log('DACdb Plus: JSON decode error - ' . json_last_error_msg());
                error_log('DACdb Plus: Failed JSON content - ' . substr($response, 0, 1000));
                return '<div class="mmpro-error">Error processing committee data (JSON error: ' . json_last_error_msg() . ')</div>';
            }

            // Convert JSON to SimpleXML structure
            try {
                $xml = new SimpleXMLElement('<root/>');
                $xml->addChild('committeemembers');
                
                foreach ($data as $member) {
                    $memberNode = $xml->committeemembers->addChild('member');
                    foreach ($member as $key => $value) {
                        if (is_string($value) || is_numeric($value)) {
                            $memberNode->addChild($key, htmlspecialchars((string)$value));
                        }
                    }
                }
            } catch (Exception $e) {
                error_log('DACdb Plus: XML creation error - ' . $e->getMessage());
                error_log('DACdb Plus: Failed XML creation from JSON - ' . substr(json_encode($data), 0, 1000));
                return '<div class="mmpro-error">Error processing committee data (XML creation error)</div>';
            }
        } else {
            // Response is XML
            libxml_use_internal_errors(true);
            $xml = simplexml_load_string($response);
            if (!$xml) {
                $errors = libxml_get_errors();
                libxml_clear_errors();
                error_log('DACdb Plus: XML parse error - ' . print_r($errors, true));
                error_log('DACdb Plus: Failed XML content - ' . substr($response, 0, 1000));
                
                // Check if this is an empty or minimal response (committee exists but no members)
                if (mmpro_is_empty_committee_response($response)) {
                    return '<div class="mmpro-notice">This committee currently has no active members for the current Rotary year.</div>';
                }
                
                return '<div class="mmpro-error">Error processing committee data (XML parse error)</div>';
            }
        }

        if (!$xml) {
            // Check if this is an empty or minimal response (committee exists but no members)
            if (mmpro_is_empty_committee_response($response)) {
                return '<div class="mmpro-notice">This committee currently has no active members for the current Rotary year.</div>';
            }
            
            // If we have a response but can't parse it, it's a real error
            return '<div class="mmpro-error">Error processing committee data (Invalid data structure)</div>';
        }

        // Filter members based on show_members setting
        if ($show_members === '1') {
            // Create a new XML structure for filtered leaders
            try {
                $new_xml = new SimpleXMLElement('<committee></committee>');
                $filtered_count = 0;
                
                // Iterate through each member
                foreach ($xml->committeemembers as $member) {
                    $raw_position = (string)$member->committeeposition;
                    $position = strtolower(trim($raw_position));
                    
                    // Consider as leader if position is not empty and not "member"
                    $is_leader = !empty($position) && $position !== 'member';
                    
                    // Add leaders to the new XML structure
                    if ($is_leader) {
                        $member_node = $new_xml->addChild('committeemembers');
                        foreach ($member as $key => $value) {
                            $member_node->addChild($key, htmlspecialchars((string)$value));
                        }
                        $filtered_count++;
                    }
                }
                
                if ($filtered_count === 0) {
                    return '<div class="mmpro-error">There are no committee leaders to display at this time.</div>';
                }
                
                $xml = $new_xml;
            } catch (Exception $e) {
                error_log('DACdb Plus: Leader filtering error - ' . $e->getMessage());
                return '<div class="mmpro-error">Error processing committee leaders data</div>';
            }
        }

        // Add committee header and description if enabled
        if ($counter == 1) {
            if ($options['committee_global_name'] == 1) {
                $committees .= '<div class="committee-header"><h3>' . $xml->committeemembers[0]->committeename . ' Committee Members</h3></div>';
            }

            if ($description == 1) {
                $committees .= '<div class="committee-description">' . $xml->committeemembers[0]->description . '</div>';
            }
        }

        // Set up display attributes
        $display_atts = array(
            'cols' => mmpro_get_committee_columns($_GET, $atts, $options),
            'pics' => $options['committee_members_pics'] ?? 1,
            'show_committee_position' => $options['committee_members_committeeposition'] ?? 1,
            'show_district_number' => $options['committee_global_show_district_number'] ?? 0,
            'show_business_position' => $options['committee_members_busposition'] ?? 0,
            'show_classification' => $options['committee_members_classification'] ?? 0,
            'show_contact' => $options['committee_members_contact_link'] ?? 1,
            'org_data_entity' => $options['committee_org_data_entity'] ?? 0,
            'org_data_account' => $options['committee_org_data_account'] ?? 0
        );

        // Use the display members function with style 1 (legacy) by default for backward compatibility
        $style = isset($atts['style']) && !empty($atts['style']) ? $atts['style'] : '1';
        
        // Ensure XML is valid and has member data
        if (!$xml || !isset($xml->committeemembers)) {
            // Check if this is an empty or minimal response (committee exists but no members)
            if (mmpro_is_empty_committee_response($response)) {
                return '<div class="mmpro-notice">This committee currently has no active members for the current Rotary year.</div>';
            }
            
            // If we have a response but no valid member data, it's an error
            return '<div class="mmpro-error">No valid committee data found</div>';
        }
        
        // Check if the committeemembers element is empty (no actual members)
        if (count($xml->committeemembers) == 0) {
            return '<div class="mmpro-notice">This committee currently has no active members for the current Rotary year.</div>';
        }
        
        // Wrap the display output in the proper container with style class
        $committees .= '<div class="mmpro-members style-' . $style . '">';
        $committees .= mmpro_display_members($xml, $style, $display_atts);
        $committees .= '</div>';

    } else {
        // List all committees - Club or District.
        $committees_list_url = $data_path . 'wp_committees.cfm?AccountID=' . $options['dacdb_district'] . '&ClubID=' . $options['dacdb_club'] . '&R=' . rand();
        $xml = dacdb_load_xml($committees_list_url, 'committees_list');
        
        // Schedule background cache warming for committees (lazy pre-warming)
        mmpro_schedule_committee_cache_warming($options);

        if ($xml === false || strlen($xml) == 0) {
            $system_url = ($options['dacdb_system'] === 'iMembersDB') ? 'https://www.imembersdb.com' : 'https://www.dacdb.com/';
            return 'There are no committees to display at this time.' . 
                   (current_user_can('manage_options') ? 
                   '<div class="mmpro-admin-notice" style="margin-top: 20px; padding: 15px; background-color: #fff3cd; border: 1px solid #ffeeba; border-radius: 4px; color: #856404;">
                        <strong>Administrator Notice:</strong> If you have active committees that do not appear, log into <a href="' . esc_url($system_url) . '" target="_blank">' . esc_html($options['dacdb_system']) . '</a> and check your committee settings. Possible reasons a committee may not be visible:
                        <ul style="margin: 10px 0 0 20px;">
                            <li>Check the active organization year to make sure it is current (or perpetual)</li>
                            <li>In the Security tab, ensure that "View Security" is set to Level-0 for public viewing.</li>
                        </ul>
                    </div>' : '');
        }

        $counter = 1;
        $committees .= '<div class="mmpro-committees">';

        foreach ($xml->committee as $committee) {
            $level_class = '';
            if ($committee->level > 0) {
                $level_class = ' mmpro-committees__item--level-' . $committee->level;
            }

            $committees .= '<div class="mmpro-committees__item' . $level_class . '">';
            
            // Committee name and link/button
            $committees .= '<div class="mmpro-committees__header">';
            if ($committee->gdg == "Y") {
                $committees .= '<h4 class="mmpro-committees__name mmpro-committees__name--gdg">' . esc_html($committee->name) . '</h4>';
            } else {
                // Create a button for accordion toggle and a separate members link
                $committees .= '<div class="mmpro-committees__title-group">';
                
                // Create a wrapper for the name/button to maintain consistent layout
                $committees .= '<div class="mmpro-committees__name-wrapper">';
                if (!empty(trim($committee->description))) {
                    $committees .= '<button type="button" 
                                    class="mmpro-committees__toggle" 
                                    aria-expanded="false"
                                    title="Click for more information">';
                    $committees .= '<h4 class="mmpro-committees__name">' . esc_html($committee->name) . '</h4>';
                    $committees .= '</button>';
                } else {
                    $committees .= '<h4 class="mmpro-committees__name">' . esc_html($committee->name) . '</h4>';
                }
                $committees .= '</div>';
                
                // Check committee members display setting
                $show_members = isset($atts['show_members']) ? $atts['show_members'] : 
                              (isset($options['committee_show_members']) ? $options['committee_show_members'] : '2');

                // Only show members link if setting allows and committee has members
                if ($show_members !== '0' && $committee->gdg !== "Y") {
                    // Check if this committee has members (with caching)
                    $committee_id = (string)$committee->committeeid;
                    $has_members = mmpro_committee_has_members($committee_id, $options);
                    
                    if ($has_members) {
                        // Get current URL and ensure committeeid is a string
                        $member_url = add_query_arg('members', $committee_id, get_permalink());
                        
                        // Set link text based on show_members setting
                        $link_text = ($show_members === '1') ? 'View leaders' : 'View members';
                        
                        $committees .= '<a href="' . esc_url($member_url) . '" 
                                         class="mmpro-committees__members-link" 
                                         title="View list of ' . ($show_members === '1' ? 'committee leaders' : 'committee members') . '">
                                         <i class="fa fa-users" aria-hidden="true"></i>
                                         <span>' . $link_text . '</span>
                                      </a>';
                    }
                }
                $committees .= '</div>';
            }

            // Year display if enabled
            if ($orgyear == 1 || strtoupper($orgyear) == 'Y') {
                $committees .= '<span class="mmpro-committees__year">' . esc_html($committee->year) . '</span>';
            }
            $committees .= '</div>'; // End mmpro-committees__header

            // Description if enabled - now in a collapsible panel
            if (!empty(trim($committee->description))) {
                $committees .= '<div class="mmpro-committees__content" hidden>';
                $committees .= '<div class="mmpro-committees__description">' . wp_kses_post(trim($committee->description)) . '</div>';
                $committees .= '</div>';
            }

            $committees .= '</div>'; // End mmpro-committees__item
            $counter++;
        }

        $committees .= '</div>'; // End mmpro-committees
        
        // Add the JavaScript for accordion functionality
        wp_enqueue_script(
            'mmpro-committees-js',
            plugins_url('js/show-committees.js', dirname(__FILE__)),
            array('jquery'),
            MMPDB_PLUGIN_VERSION,
            true
        );
    }

    return $committees;
}

// The mmpro_display_members function has been moved to display/member-cards.php

