<?php
require_once __DIR__ . '/assets/vendor/phpqrcode/qrlib.php';

$url = 'http://localhost/tap2order/menu.php?r=big-mama';
$ref = new ReflectionClass('QRcode');

// Generate
$genMethod = $ref->getMethod('generate');
$genMethod->setAccessible(true);
$qr = $genMethod->invoke(null, $url);
$matrix = $qr['matrix'];
$size = $qr['size'];
$version = $qr['version'];

// Get reserved matrix
$createMethod = $ref->getMethod('createMatrix');
$createMethod->setAccessible(true);
$md = $createMethod->invoke(null, $version);
$reserved = $md['reserved'];

// Decode format info
$pos1 = [
    [8,0],[8,1],[8,2],[8,3],[8,4],[8,5],[8,7],[8,8],
    [7,8],[5,8],[4,8],[3,8],[2,8],[1,8],[0,8]
];
$fmtVal = 0;
for ($i = 0; $i < 15; $i++) {
    $bit = $matrix[$pos1[$i][0]][$pos1[$i][1]];
    $fmtVal = ($fmtVal << 1) | $bit;
}
$unmasked = $fmtVal ^ 0x5412;
$maskPattern = ($unmasked >> 10) & 7;
$ecNames = ['M','L','H','Q'];
$ecIndicator = ($unmasked >> 13) & 3;
echo "EC={$ecNames[$ecIndicator]}, Mask=$maskPattern\n";

// Read interleaved data bits from matrix (same traversal as placeData)
$dataBits = '';
for ($right = $size - 1; $right >= 1; $right -= 2) {
    if ($right == 6) $right = 5;
    $upward = (($right + 1) & 2) == 0;
    for ($vert = 0; $vert < $size; $vert++) {
        for ($j = 0; $j < 2; $j++) {
            $col = $right - $j;
            $row = $upward ? ($size - 1 - $vert) : $vert;
            if ($row < 0 || $row >= $size || $col < 0 || $col >= $size) continue;
            if ($reserved[$row][$col]) continue;

            $bit = $matrix[$row][$col] ? 1 : 0;
            $mask = false;
            switch ($maskPattern) {
                case 0: $mask = ($row + $col) % 2 == 0; break;
                case 1: $mask = $row % 2 == 0; break;
                case 2: $mask = $col % 3 == 0; break;
                case 3: $mask = ($row + $col) % 3 == 0; break;
                case 4: $mask = (intdiv($row, 2) + intdiv($col, 3)) % 2 == 0; break;
                case 5: $mask = ($row * $col) % 2 + ($row * $col) % 3 == 0; break;
                case 6: $mask = ((($row * $col) % 2 + ($row * $col) % 3) % 2) == 0; break;
                case 7: $mask = ((($row + $col) % 2 + ($row * $col) % 3) % 2) == 0; break;
            }
            if ($mask) $bit ^= 1;
            $dataBits .= $bit;
        }
    }
}

echo "Interleaved data bits: " . strlen($dataBits) . "\n";

// Convert to interleaved codewords
$interleavedCW = [];
for ($i = 0; $i < strlen($dataBits); $i += 8) {
    $byte = substr($dataBits, $i, 8);
    if (strlen($byte) === 8) {
        $interleavedCW[] = bindec($byte);
    }
}
echo "Interleaved codewords: " . count($interleavedCW) . "\n";

// Get EC params for de-interleaving
$ecParams = $ref->getStaticPropertyValue('ecParams');
$params = $ecParams[$version];
$totalDataCW = $params[3];
$ecPerBlock = $params[1];
$numBlocks = $params[2];
$totalCW = $params[0];

echo "Version $version: $numBlocks blocks, $totalDataCW data CW, $ecPerBlock EC/block, $totalCW total CW\n";

// De-interleave data blocks
if ($numBlocks == 1) {
    $dataCW = array_slice($interleavedCW, 0, $totalDataCW);
} else {
    $baseSize = intdiv($totalDataCW, $numBlocks);
    $extra = $totalDataCW % $numBlocks;
    $blockSizes = [];
    for ($i = 0; $i < $numBlocks; $i++) {
        $blockSizes[] = ($i < $numBlocks - $extra) ? $baseSize : $baseSize + 1;
    }

    // Read interleaved data CW
    $offset = 0;
    $dataBlocks = [];
    $maxDataLen = max($blockSizes);
    for ($i = 0; $i < $maxDataLen; $i++) {
        for ($b = 0; $b < $numBlocks; $b++) {
            if ($i < $blockSizes[$b]) {
                $dataBlocks[$b][] = $interleavedCW[$offset++];
            }
        }
    }

    // Concatenate blocks
    $dataCW = [];
    foreach ($dataBlocks as $block) {
        $dataCW = array_merge($dataCW, $block);
    }
}

echo "De-interleaved data CW: " . count($dataCW) . " (" . implode(',', array_slice($dataCW, 0, 8)) . "...)\n";

// Convert to bits and parse
$dataBits2 = '';
foreach ($dataCW as $byte) {
    $dataBits2 .= str_pad(decbin($byte), 8, '0', STR_PAD_LEFT);
}

$mode = substr($dataBits2, 0, 4);
$countBits = ($version >= 10) ? 16 : 8;
$charCount = bindec(substr($dataBits2, 4, $countBits));
$start = 4 + $countBits;

echo "\nMode: $mode (expected 0100)\n";
echo "Char count: $charCount (expected " . strlen($url) . ")\n";

$decoded = '';
for ($i = 0; $i < $charCount; $i++) {
    $byte = bindec(substr($dataBits2, $start + $i * 8, 8));
    $decoded .= chr($byte);
}

echo "Decoded: $decoded\n";
echo "Expected: $url\n";
echo "MATCH: " . ($decoded === $url ? "YES ✓" : "NO ✗") . "\n";
