<?php
/**
 * Fix mojibake in app.js
 * 
 * The problem: Thai UTF-8 text was re-interpreted as Windows-1252/Latin1 
 * and then re-encoded to UTF-8, causing double-encoding.
 * 
 * Solution: Read raw bytes, find sequences that are double-encoded UTF-8,
 * and reverse the process.
 * 
 * A double-encoded UTF-8 Thai character looks like:
 *   Original UTF-8 byte E0 -> C3 A0 in double-encoded UTF-8
 *   Original UTF-8 byte B8 -> C2 B8 in double-encoded UTF-8
 *   etc.
 * 
 * We detect and fix these patterns byte-by-byte.
 */

$inputFile = 'app.js';
$outputFile = 'app.js';

$content = file_get_contents($inputFile);

// Strategy: We know the mojibake comes from UTF-8 bytes being misinterpreted
// as CP1252/Latin1 and then re-encoded to UTF-8.
// 
// To reverse: take each "character" that is in the C2-C3 range (2-byte UTF-8 
// for codepoints 0x80-0xFF), decode it back to the single byte it represents,
// then check if the resulting byte sequence forms valid UTF-8 Thai.

$output = '';
$len = strlen($content);
$i = 0;
$fixCount = 0;

while ($i < $len) {
    $byte = ord($content[$i]);
    
    // Check if this could be start of a double-encoded sequence
    // Double-encoded UTF-8 Thai starts with: C3 A0 (which is UTF-8 for U+00E0, 
    // but originally was byte 0xE0, the start of a 3-byte UTF-8 sequence for Thai)
    // OR C2 xx (UTF-8 for bytes 0x80-0xBF which are continuation bytes)
    
    if ($byte == 0xC3 || $byte == 0xC2 || $byte == 0xC5 || $byte == 0xC4) {
        // This is a 2-byte UTF-8 sequence encoding a byte in 0x80-0xFF range
        if ($i + 1 < $len) {
            $next = ord($content[$i + 1]);
            if ($next >= 0x80 && $next <= 0xBF) {
                // Decode back to original byte
                $origByte = (($byte & 0x1F) << 6) | ($next & 0x3F);
                
                // Check if this original byte could be part of a Thai UTF-8 sequence
                // Thai UTF-8 starts with E0 B8 xx or E0 B9 xx
                if ($origByte == 0xE0) {
                    // Potential start of a 3-byte UTF-8 Thai char
                    // We need 2 more "decoded" bytes
                    $decoded = chr($origByte);
                    $j = $i + 2;
                    $consumed = 2;
                    $validThai = false;
                    
                    // Try to decode next 2 bytes
                    for ($k = 0; $k < 2 && $j < $len; $k++) {
                        $b = ord($content[$j]);
                        if ($b == 0xC2 || $b == 0xC3) {
                            if ($j + 1 < $len) {
                                $n = ord($content[$j + 1]);
                                if ($n >= 0x80 && $n <= 0xBF) {
                                    $orig = (($b & 0x1F) << 6) | ($n & 0x3F);
                                    $decoded .= chr($orig);
                                    $j += 2;
                                    $consumed += 2;
                                } else {
                                    break;
                                }
                            } else {
                                break;
                            }
                        } elseif ($b >= 0x80 && $b <= 0xBF) {
                            // Already a raw continuation byte (shouldn't happen in valid UTF-8 standalone)
                            break;
                        } else {
                            break;
                        }
                    }
                    
                    if (strlen($decoded) == 3) {
                        // Check if decoded bytes form valid Thai UTF-8
                        $decoded_str = mb_convert_encoding($decoded, 'UTF-8', 'UTF-8');
                        $cp = mb_ord($decoded_str, 'UTF-8');
                        
                        // Thai range: U+0E00 to U+0E7F, also check U+0E80+ for Lao
                        // Also allow Thai baht sign U+0E3F
                        if ($cp >= 0x0E00 && $cp <= 0x0E7F) {
                            $output .= $decoded;
                            $i = $j;
                            $fixCount++;
                            continue;
                        }
                    }
                }
                
                // Check for other double-encoded patterns
                // E2 80 xx sequences (smart quotes, bullets, em-dash etc.)
                if ($origByte == 0xE2) {
                    $decoded = chr($origByte);
                    $j = $i + 2;
                    
                    for ($k = 0; $k < 2 && $j < $len; $k++) {
                        $b = ord($content[$j]);
                        if ($b == 0xC2 || $b == 0xC3) {
                            if ($j + 1 < $len) {
                                $n = ord($content[$j + 1]);
                                if ($n >= 0x80 && $n <= 0xBF) {
                                    $orig = (($b & 0x1F) << 6) | ($n & 0x3F);
                                    $decoded .= chr($orig);
                                    $j += 2;
                                } else {
                                    break;
                                }
                            } else {
                                break;
                            }
                        } else {
                            break;
                        }
                    }
                    
                    if (strlen($decoded) == 3) {
                        $decoded_str = mb_convert_encoding($decoded, 'UTF-8', 'UTF-8');
                        if ($decoded_str !== false && mb_check_encoding($decoded, 'UTF-8')) {
                            $cp = mb_ord($decoded_str, 'UTF-8');
                            // Common typographic characters: bullets, dashes, quotes
                            // U+2000-U+206F (general punctuation), U+2190-U+21FF, etc
                            if (($cp >= 0x2000 && $cp <= 0x206F) || 
                                ($cp >= 0x2190 && $cp <= 0x21FF) ||
                                ($cp >= 0x2500 && $cp <= 0x257F)) {
                                $output .= $decoded;
                                $i = $j;
                                $fixCount++;
                                continue;
                            }
                        }
                    }
                }
            }
        }
    }
    
    // Not a double-encoded sequence, keep original byte
    $output .= $content[$i];
    $i++;
}

file_put_contents($outputFile, $output);
echo "Fixed $fixCount double-encoded characters in app.js\n";

// Verify: count remaining non-ASCII suspicious patterns
$remaining = 0;
$lines = explode("\n", $output);
foreach ($lines as $lineNum => $line) {
    // Check for C2/C3 followed by Thai-range bytes (signs of remaining mojibake)
    if (preg_match('/[\xC2\xC3][\x80-\xBF]/', $line)) {
        // This could be legitimate UTF-8, so check if it's in Thai context
        // Just count for reporting
        if (preg_match('/[\x{0E00}-\x{0E7F}]/u', $line) || 
            preg_match('/[\xC2][\x80-\x9F]/', $line)) {
            // Lines with Thai AND suspicious C2 bytes
            $remaining++;
        }
    }
}
echo "Lines with potential remaining issues: $remaining\n";
