<?php
/**
 * Participant Color Generation Utility
 * 
 * Provides consistent color generation for participant badges across the system
 */

function clamp($v, $min, $max) { 
    return max($min, min($max, $v)); 
}

function hslToHex($h, $s, $l): string {
    $rgb = hslToRgb($h, $s, $l);
    return sprintf("#%02x%02x%02x", $rgb[0], $rgb[1], $rgb[2]);
}

function hslToRgb($h, $s, $l): array {
    $h /= 360;
    if ($s == 0) {
        $r = $g = $b = $l;
    } else {
        $q = $l < 0.5 ? $l * (1 + $s) : $l + $s - $l * $s;
        $p = 2 * $l - $q;
        $r = hue2rgb($p, $q, $h + 1/3);
        $g = hue2rgb($p, $q, $h);
        $b = hue2rgb($p, $q, $h - 1/3);
    }
    return [round($r * 255), round($g * 255), round($b * 255)];
}

function hue2rgb($p, $q, $t) {
    if ($t < 0) $t += 1;
    if ($t > 1) $t -= 1;
    if ($t < 1/6) return $p + ($q - $p) * 6 * $t;
    if ($t < 1/2) return $q;
    if ($t < 2/3) return $p + ($q - $p) * (2/3 - $t) * 6;
    return $p;
}

function hexToRgb(string $hex): array {
    $hex = ltrim($hex, '#');
    return [
        hexdec(substr($hex, 0, 2)),
        hexdec(substr($hex, 2, 2)),
        hexdec(substr($hex, 4, 2))
    ];
}

function relativeLuminance(string $hex): float {
    $rgb = hexToRgb($hex);
    $r = $rgb[0] / 255;
    $g = $rgb[1] / 255;
    $b = $rgb[2] / 255;
    
    $r = $r <= 0.03928 ? $r / 12.92 : pow(($r + 0.055) / 1.055, 2.4);
    $g = $g <= 0.03928 ? $g / 12.92 : pow(($g + 0.055) / 1.055, 2.4);
    $b = $b <= 0.03928 ? $b / 12.92 : pow(($b + 0.055) / 1.055, 2.4);
    
    return 0.2126 * $r + 0.7152 * $g + 0.0722 * $b;
}

function contrastRatio(string $hex1, string $hex2): float {
    $l1 = relativeLuminance($hex1);
    $l2 = relativeLuminance($hex2);
    $lighter = max($l1, $l2);
    $darker = min($l1, $l2);
    return ($lighter + 0.05) / ($darker + 0.05);
}

function ensureContrast(string $bgHex, array $textHsl, float $minContrast): string {
    $attempts = 0;
    $maxAttempts = 100;
    
    while ($attempts < $maxAttempts) {
        $textHex = hslToHex($textHsl[0], $textHsl[1], $textHsl[2]);
        $contrast = contrastRatio($bgHex, $textHex);
        
        if ($contrast >= $minContrast) {
            return $textHex;
        }
        
        if (relativeLuminance($bgHex) > 0.5) {
            $textHsl[2] = max(0, $textHsl[2] - 0.05);
        } else {
            $textHsl[2] = min(1, $textHsl[2] + 0.05);
        }
        
        $attempts++;
    }
    
    return hslToHex($textHsl[0], $textHsl[1], $textHsl[2]);
}

/**
 * Generate a color pair for a participant based on their initials
 * 
 * @param string $seed - Usually participant initials
 * @param array $opts - Options for color generation
 * @return array - Array containing bg, text, light, dark, accent colors
 */
function generateColorPair(string $seed, array $opts = []): array {
    $mode = $opts['mode'] ?? 'light';
    $saturation = $opts['saturation'] ?? 0.65;
    $minContrast = $opts['min_contrast'] ?? 4.5;
    
    $hash = crc32($seed);
    $hue = abs($hash) % 360;
    
    if ($mode === 'light') {
        $bgLightness = clamp(0.85 + (($hash % 20) / 100), 0.8, 0.95);
        $textLightness = clamp(0.15 + (($hash % 15) / 100), 0.1, 0.3);
    } else {
        $bgLightness = clamp(0.15 + (($hash % 20) / 100), 0.1, 0.3);
        $textLightness = clamp(0.85 + (($hash % 15) / 100), 0.8, 0.95);
    }
    
    $bgHex = hslToHex($hue, $saturation, $bgLightness);
    $textHex = ensureContrast($bgHex, [$hue, $saturation, $textLightness], $minContrast);
    
    $lightHex = hslToHex($hue, $saturation * 0.7, min(0.95, $bgLightness + 0.1));
    $darkHex = hslToHex($hue, $saturation * 1.2, max(0.1, $textLightness - 0.05));
    $accentHex = hslToHex($hue, min(1, $saturation * 1.3), 0.5);
    
    return [
        'bg' => $bgHex,
        'text' => $textHex,
        'light' => $lightHex,
        'dark' => $darkHex,
        'accent' => $accentHex
    ];
}

/**
 * Collect participant data and generate colors
 * 
 * @param array $participants - Array of participant data
 * @param array $opts - Options for color generation
 * @return array - Array of participant colors indexed by badge_class
 */
function collectParticipantColors($participants, $opts = []): array {
    $participant_colors = [];
    $collected_participants = [];
    
    foreach ($participants as $name => $runs) {
        if (!empty($runs['last_name']) && !empty($runs['first_name'])) {
            $initials = strtoupper(mb_substr($runs['last_name'], 0, 1, 'UTF-8') . mb_substr($runs['first_name'], 0, 1, 'UTF-8'));
            $bib = $runs['bib'] ?? '';
            $badge_class = 'badge_p_' . $bib . '_' . $initials;
            if (!isset($collected_participants[$badge_class])) {
                $collected_participants[$badge_class] = $initials;
            }
        }
    }
    
    // Generate colors for each unique participant
    foreach ($collected_participants as $badge_class => $initials) {
        $colors = generateColorPair($initials, $opts);
        $participant_colors[$badge_class] = [
            'initials' => $initials,
            'bg' => $colors['bg'],
            'text' => $colors['text'],
            'light' => $colors['light'],
            'dark' => $colors['dark'],
            'accent' => $colors['accent']
        ];
    }
    
    return $participant_colors;
}

/**
 * Generate CSS styles for participant badges
 * 
 * @param array $participant_colors - Array of participant colors
 * @return string - CSS styles
 */
function generateParticipantCSS($participant_colors): string {
    $css = '';
    
    if (!empty($participant_colors) && is_array($participant_colors)) {
        foreach ($participant_colors as $badge_class => $color_data) {
            // Validate color data structure
            if (!is_array($color_data) || 
                !isset($color_data['light']) || 
                !isset($color_data['dark']) || 
                !isset($color_data['accent'])) {
                continue;
            }
            
            try {
                // Convert hex to rgb for CSS
                $bg_rgb = hexToRgb($color_data['light']);
                $text_rgb = hexToRgb($color_data['dark']);
                $accent_rgb = hexToRgb($color_data['accent']);
                
                $css .= '.' . $badge_class . ' {';
                $css .= 'background: rgb(' . implode(',', $bg_rgb) . ') !important;';
                $css .= 'color: rgb(' . implode(',', $text_rgb) . ') !important;';
                $css .= 'border: 1px solid rgb(' . implode(',', $accent_rgb) . ') !important;';
                $css .= '}';
            } catch (Exception $e) {
                // Skip this badge if color conversion fails
                continue;
            }
        }
    }
    
    return $css;
}
?>
