<?php

declare(strict_types=1);

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

use App\Framework\QrCode\DataEncoder;
use App\Framework\QrCode\DataMode;
use App\Framework\QrCode\ErrorCorrectionLevel;
use App\Framework\QrCode\QrCodeVersion;

// Debug actual encoding steps by modifying DataEncoder temporarily
class DebugDataEncoder extends DataEncoder
{
    public function debugEncode(string $data, QrCodeVersion $version, ErrorCorrectionLevel $errorLevel): array
    {
        echo "=== Debug Encoding Steps ===\n";
        echo "Data: '$data' (length: " . strlen($data) . ")\n";
        echo "Version: " . $version->getVersion() . "\n";
        echo "Error Level: {$errorLevel->value}\n";
        echo "Capacity: " . $version->getDataCapacity($errorLevel) . " bits\n\n";

        // Step 1: Create data bit stream
        $mode = DataMode::detectForData($data);
        echo "1. Mode detection: {$mode->value}\n";

        $bitStream = '';

        // Mode indicator
        $modeIndicator = $this->addModeIndicator($mode);
        $bitStream .= $modeIndicator;
        echo "2. Mode indicator: '$modeIndicator' (" . strlen($modeIndicator) . " bits)\n";

        // Character count
        $charCount = $this->addCharacterCountIndicator($data, $mode, $version);
        $bitStream .= $charCount;
        echo "3. Character count: '$charCount' (" . strlen($charCount) . " bits)\n";

        // Data encoding
        $encodedData = $this->encodeData($data, $mode);
        $bitStream .= $encodedData;
        echo "4. Encoded data: " . strlen($encodedData) . " bits\n";
        echo "   Bitstream so far: " . strlen($bitStream) . " bits\n";

        // Terminator
        $beforeTerminator = $bitStream;
        $bitStream .= $this->addTerminator($bitStream, $version, $errorLevel);
        $terminatorAdded = strlen($bitStream) - strlen($beforeTerminator);
        echo "5. Terminator: $terminatorAdded bits added\n";

        // Pad to byte length
        $beforePadding = $bitStream;
        $bitStream = $this->padToByteLength($bitStream);
        $bytePadding = strlen($bitStream) - strlen($beforePadding);
        echo "6. Byte padding: $bytePadding bits added\n";
        echo "   Bitstream length: " . strlen($bitStream) . " bits\n";

        // Final padding
        try {
            $beforeFinalPadding = $bitStream;
            $bitStream = $this->addPadding($bitStream, $version, $errorLevel);
            $finalPadding = strlen($bitStream) - strlen($beforeFinalPadding);
            echo "7. Final padding: $finalPadding bits added\n";
            echo "8. Final bitstream: " . strlen($bitStream) . " bits\n";
            echo "   Capacity: " . $version->getDataCapacity($errorLevel) . " bits\n";
            echo "   SUCCESS!\n";

            return [];
        } catch (Exception $e) {
            echo "7. ERROR in final padding: " . $e->getMessage() . "\n";
            echo "   Current length: " . strlen($bitStream) . " bits\n";
            echo "   Required capacity: " . $version->getDataCapacity($errorLevel) . " bits\n";

            return [];
        }
    }

    // Make protected methods public for debugging
    public function addModeIndicator(DataMode $mode): string
    {
        return parent::addModeIndicator($mode);
    }

    public function addCharacterCountIndicator(string $data, DataMode $mode, QrCodeVersion $version): string
    {
        return parent::addCharacterCountIndicator($data, $mode, $version);
    }

    public function encodeData(string $data, DataMode $mode): string
    {
        return parent::encodeData($data, $mode);
    }

    public function addTerminator(string $bitStream, QrCodeVersion $version, ErrorCorrectionLevel $errorLevel): string
    {
        return parent::addTerminator($bitStream, $version, $errorLevel);
    }

    public function padToByteLength(string $bitStream): string
    {
        return parent::padToByteLength($bitStream);
    }

    public function addPadding(string $bitStream, QrCodeVersion $version, ErrorCorrectionLevel $errorLevel): string
    {
        return parent::addPadding($bitStream, $version, $errorLevel);
    }
}

$testData = 'otpauth://totp/Test?secret=JBSWY3DPEHPK3PXP';
$version = new QrCodeVersion(3);
$errorLevel = ErrorCorrectionLevel::L;

$debugEncoder = new DebugDataEncoder();
$debugEncoder->debugEncode($testData, $version, $errorLevel);
