<?php

declare(strict_types=1);

require_once __DIR__ . '/../../vendor/autoload.php';

use App\Framework\QrCode\QrCodeGenerator;
use App\Framework\QrCode\ValueObjects\ErrorCorrectionLevel;
use App\Framework\QrCode\ValueObjects\QrCodeConfig;
use App\Framework\QrCode\ValueObjects\QrCodeVersion;
use App\Framework\QrCode\ValueObjects\EncodingMode;
use App\Framework\QrCode\Structure\FinderPattern;
use App\Framework\QrCode\Structure\AlignmentPattern;

echo "=== QR Code Debug Visualizer ===\n\n";

// Test with simple data
$data = "HELLO";
$version = 1;

echo "Testing Data: '{$data}'\n";
echo "Version: {$version}\n";
echo "Length: " . strlen($data) . " bytes\n\n";

// Generate QR Code
$config = new QrCodeConfig(
    version: QrCodeVersion::fromNumber($version),
    errorCorrectionLevel: ErrorCorrectionLevel::M,
    encodingMode: EncodingMode::BYTE
);

$matrix = QrCodeGenerator::generate($data, $config);
$size = $matrix->getSize();

echo "Matrix Size: {$size}x{$size}\n\n";

// Function to check if position is a function pattern
function isFunctionPattern(int $row, int $col, int $size, int $version): string
{
    // Finder patterns + separators (9x9 areas)
    if (
        ($row <= 8 && $col <= 8) ||  // Top-left
        ($row <= 8 && $col >= $size - 8) ||  // Top-right
        ($row >= $size - 8 && $col <= 8)  // Bottom-left
    ) {
        return 'FINDER';
    }

    // Timing patterns
    if ($row === 6 || $col === 6) {
        return 'TIMING';
    }

    // Dark module
    $darkModuleRow = 4 * $version + 9;
    if ($row === $darkModuleRow && $col === 8) {
        return 'DARK';
    }

    // Format information positions
    // Horizontal: row 8, cols 0-8 and size-8 to size-1
    if ($row === 8 && ($col <= 8 || $col >= $size - 8)) {
        return 'FORMAT';
    }
    // Vertical: col 8, rows 0-8 and size-7 to size-1
    if ($col === 8 && ($row <= 8 || $row >= $size - 7)) {
        return 'FORMAT';
    }

    // Alignment patterns (Version 2+)
    if ($version >= 2) {
        $alignmentLocations = AlignmentPattern::getLocations($version);
        foreach ($alignmentLocations as $alignRow) {
            foreach ($alignmentLocations as $alignCol) {
                // Skip if overlaps with finder patterns
                if ($alignRow <= 8 && $alignCol <= 8) {
                    continue;
                }
                if ($alignRow <= 8 && $alignCol >= $size - 8) {
                    continue;
                }
                if ($alignRow >= $size - 8 && $alignCol <= 8) {
                    continue;
                }

                // Check if within 5x5 alignment pattern
                if (abs($row - $alignRow) <= 2 && abs($col - $alignCol) <= 2) {
                    return 'ALIGN';
                }
            }
        }
    }

    return 'DATA';
}

// Visualize matrix with pattern types
echo "=== Matrix Visualization (Pattern Types) ===\n";
echo "Legend: F=Finder, T=Timing, A=Align, D=Dark, X=Format, .=Data(light), #=Data(dark)\n\n";

for ($row = 0; $row < $size; $row++) {
    for ($col = 0; $col < $size; $col++) {
        $patternType = isFunctionPattern($row, $col, $size, $version);
        $isDark = $matrix->getModuleAt($row, $col)->isDark();

        $char = match($patternType) {
            'FINDER' => 'F',
            'TIMING' => 'T',
            'ALIGN' => 'A',
            'DARK' => 'D',
            'FORMAT' => 'X',
            'DATA' => $isDark ? '#' : '.',
            default => '?'
        };

        echo $char . ' ';
    }
    echo "\n";
}

echo "\n=== Data Region Analysis ===\n";

// Count data modules
$dataModules = 0;
$darkDataModules = 0;
for ($row = 0; $row < $size; $row++) {
    for ($col = 0; $col < $size; $col++) {
        if (isFunctionPattern($row, $col, $size, $version) === 'DATA') {
            $dataModules++;
            if ($matrix->getModuleAt($row, $col)->isDark()) {
                $darkDataModules++;
            }
        }
    }
}

echo "Total data modules: {$dataModules}\n";
echo "Dark data modules: {$darkDataModules}\n";
echo "Light data modules: " . ($dataModules - $darkDataModules) . "\n";
echo "Data dark ratio: " . round(($darkDataModules / $dataModules) * 100, 2) . "%\n\n";

// Show data bits in placement order (zig-zag pattern)
echo "=== Data Bits (Zig-Zag Placement Order) ===\n";
echo "First 64 data bits:\n";

$bitIndex = 0;
$bits = [];

for ($col = $size - 1; $col >= 1; $col -= 2) {
    // Skip timing column
    if ($col === 6) {
        $col--;
    }

    // Zig-zag direction
    $upward = ((int) (($size - 1 - $col) / 2) % 2) === 0;

    for ($i = 0; $i < $size; $i++) {
        $row = $upward ? ($size - 1 - $i) : $i;

        // Check both columns of the pair
        for ($c = 0; $c < 2; $c++) {
            $currentCol = $col - $c;

            if (isFunctionPattern($row, $currentCol, $size, $version) === 'DATA') {
                $bit = $matrix->getModuleAt($row, $currentCol)->isDark() ? '1' : '0';
                $bits[] = $bit;
                $bitIndex++;

                if ($bitIndex <= 64) {
                    echo $bit;
                    if ($bitIndex % 8 === 0) {
                        echo " ";
                    }
                }
            }
        }
    }
}

echo "\n\n";

// Decode first few bytes
echo "=== First Data Bytes (Binary -> Decimal) ===\n";
for ($i = 0; $i < min(8, count($bits) / 8); $i++) {
    $byte = substr(implode('', $bits), $i * 8, 8);
    $decimal = bindec($byte);
    $char = $decimal >= 32 && $decimal < 127 ? chr($decimal) : '.';
    echo "Byte " . ($i + 1) . ": {$byte} = {$decimal} ('{$char}')\n";
}

echo "\n=== Expected Encoding ===\n";
echo "Mode indicator (Byte): 0100\n";
echo "Character count (8 bits): " . str_pad(decbin(strlen($data)), 8, '0', STR_PAD_LEFT) . " = " . strlen($data) . "\n";
echo "Data bytes:\n";
for ($i = 0; $i < strlen($data); $i++) {
    $byte = ord($data[$i]);
    $binary = str_pad(decbin($byte), 8, '0', STR_PAD_LEFT);
    echo "  '{$data[$i]}': {$binary} = {$byte}\n";
}

echo "\n=== Format Information Analysis ===\n";
echo "Format info should encode: Error Correction Level + Mask Pattern\n";
echo "Located at: row 8 and col 8 (with redundancy)\n\n";

// Extract format information bits
$formatBits = [];

// Horizontal format info (row 8, skipping timing column at 6)
for ($col = 0; $col < 9; $col++) {
    if ($col === 6) continue; // Skip timing column
    $formatBits[] = $matrix->getModuleAt(8, $col)->isDark() ? '1' : '0';
}

echo "Horizontal format bits: " . implode('', $formatBits) . "\n";

// Vertical format info
$formatBitsVertical = [];
for ($row = $size - 1; $row >= $size - 7; $row--) {
    $formatBitsVertical[] = $matrix->getModuleAt($row, 8)->isDark() ? '1' : '0';
}
for ($row = 7; $row >= 0; $row--) {
    if ($row === 6) continue; // Skip timing column
    $formatBitsVertical[] = $matrix->getModuleAt($row, 8)->isDark() ? '1' : '0';
}

echo "Vertical format bits:   " . implode('', $formatBitsVertical) . "\n";

echo "\n=== Summary ===\n";
echo "✓ Matrix generated: {$size}x{$size}\n";
echo "✓ Function patterns placed\n";
echo "✓ Data region identified: {$dataModules} modules\n";
echo "✓ First data bits extracted and decoded\n\n";

echo "Next steps for debugging:\n";
echo "1. Compare expected vs actual data encoding\n";
echo "2. Verify format information is correct\n";
echo "3. Check if mask pattern was applied correctly\n";
echo "4. Validate error correction codewords\n";
