<?php

declare(strict_types=1);

namespace App\Framework\QrCode\Structure;

use App\Framework\QrCode\ValueObjects\Module;
use App\Framework\QrCode\ValueObjects\ModulePosition;
use App\Framework\QrCode\ValueObjects\QrCodeMatrix;

/**
 * QR Code Finder Pattern Generator
 *
 * Generates the three 7x7 finder patterns (position detection patterns)
 * Located in three corners: top-left, top-right, bottom-left
 *
 * Pattern structure (7x7):
 * █████████
 * █░░░░░░█
 * █░█████░█
 * █░█░░░█░█
 * █░█████░█
 * █░░░░░░█
 * █████████
 */
final readonly class FinderPattern
{
    /**
     * Apply all three finder patterns to matrix
     */
    public static function apply(QrCodeMatrix $matrix): QrCodeMatrix
    {
        $size = $matrix->getSize();

        // Top-left corner
        $matrix = self::drawPattern($matrix, ModulePosition::at(0, 0));

        // Top-right corner
        $matrix = self::drawPattern($matrix, ModulePosition::at(0, $size - 7));

        // Bottom-left corner
        $matrix = self::drawPattern($matrix, ModulePosition::at($size - 7, 0));

        return $matrix;
    }

    /**
     * Draw single 7x7 finder pattern at position
     *
     * QR Code Finder Pattern (1:1:3:1:1 ratio):
     * - Outer ring (1 module): DARK
     * - White ring (1 module): LIGHT
     * - Inner 3x3 center (3 modules): DARK
     */
    private static function drawPattern(QrCodeMatrix $matrix, ModulePosition $topLeft): QrCodeMatrix
    {
        // 7x7 finder pattern with inner 3x3 dark, 1-module white ring, outer dark ring
        for ($r = 0; $r < 7; $r++) {
            for ($c = 0; $c < 7; $c++) {
                $row = $topLeft->row + $r;
                $col = $topLeft->column + $c;
                $pos = ModulePosition::at($row, $col);

                // Outer ring (r==0 || r==6 || c==0 || c==6) => DARK
                if ($r === 0 || $r === 6 || $c === 0 || $c === 6) {
                    $matrix = $matrix->setModule($pos, Module::dark());
                    continue;
                }

                // White ring (r==1 || r==5 || c==1 || c==5) => LIGHT
                if ($r === 1 || $r === 5 || $c === 1 || $c === 5) {
                    $matrix = $matrix->setModule($pos, Module::light());
                    continue;
                }

                // Inner 3x3 (r,c in 2..4) => DARK
                $matrix = $matrix->setModule($pos, Module::dark());
            }
        }

        return $matrix;
    }

    /**
     * Add separator (1 module white border around finder pattern)
     * The separator is the 8th row/column around the 7x7 finder pattern
     */
    public static function applySeparators(QrCodeMatrix $matrix): QrCodeMatrix
    {
        $size = $matrix->getSize();

        // Top-left separator (row 7 and column 7)
        for ($i = 0; $i < 8; $i++) {
            $matrix = $matrix->setModuleAt(7, $i, Module::light());  // Row 7
            $matrix = $matrix->setModuleAt($i, 7, Module::light());  // Column 7
        }

        // Top-right separator (row 7 and column size-8)
        for ($i = 0; $i < 8; $i++) {
            $matrix = $matrix->setModuleAt(7, $size - 1 - $i, Module::light());  // Row 7
            $matrix = $matrix->setModuleAt($i, $size - 8, Module::light());  // Column size-8
        }

        // Bottom-left separator (row size-8 and column 7)
        for ($i = 0; $i < 8; $i++) {
            $matrix = $matrix->setModuleAt($size - 8, $i, Module::light());  // Row size-8
            $matrix = $matrix->setModuleAt($size - 1 - $i, 7, Module::light());  // Column 7
        }

        return $matrix;
    }
}
