<?php

declare(strict_types=1);

namespace App\Application\Service;

use App\Domain\QrCode\QrCode;
use App\Domain\QrCode\Service\QrCodeGenerator;
use App\Domain\QrCode\ValueObject\ErrorCorrectionLevel;
use App\Domain\QrCode\ValueObject\QrCodeConfig;
use App\Domain\QrCode\ValueObject\QrCodeMatrix;
use App\Domain\QrCode\ValueObject\QrCodeVersion;

readonly class QrCodeService
{
    public function __construct(
        private QrCodeGenerator $generator
    ) {
    }

    /**
     * Generiert einen QR-Code für die angegebenen Daten
     *
     * @param string $data Die zu kodierenden Daten
     * @param ErrorCorrectionLevel $errorLevel Fehlerkorrektur-Level
     * @param int|null $version Spezifische QR-Code-Version (optional)
     * @return QrCodeMatrix Die generierte QR-Code-Matrix
     */
    public function generateQrCode(
        string $data,
        ErrorCorrectionLevel $errorLevel = ErrorCorrectionLevel::M,
        ?int $version = null
    ): QrCodeMatrix {
        $qrCodeVersion = $version ? new QrCodeVersion($version) : null;
        $qrCode = new QrCode($data, $errorLevel, $qrCodeVersion);

        return $this->generator->generate($qrCode);
    }

    /**
     * Generiert einen QR-Code als SVG
     *
     * @param string $data Die zu kodierenden Daten
     * @param ErrorCorrectionLevel $errorLevel Fehlerkorrektur-Level
     * @param QrCodeConfig|null $config Konfigurationseinstellungen
     * @return string SVG-Darstellung des QR-Codes
     */
    public function generateSvg(
        string $data,
        ErrorCorrectionLevel $errorLevel = ErrorCorrectionLevel::M,
        ?QrCodeConfig $config = null
    ): string {
        $matrix = $this->generateQrCode($data, $errorLevel);
        $config = $config ?? new QrCodeConfig();

        return $matrix->toSvg(
            $config->getModuleSize(),
            $config->getMargin(),
            $config->getForegroundColor(),
            $config->getBackgroundColor()
        );
    }

    /**
     * Generiert einen QR-Code als PNG
     *
     * @param string $data Die zu kodierenden Daten
     * @param ErrorCorrectionLevel $errorLevel Fehlerkorrektur-Level
     * @param QrCodeConfig|null $config Konfigurationseinstellungen
     * @return string PNG-Binärdaten des QR-Codes
     */
    public function generatePng(
        string $data,
        ErrorCorrectionLevel $errorLevel = ErrorCorrectionLevel::M,
        ?QrCodeConfig $config = null
    ): string {
        $matrix = $this->generateQrCode($data, $errorLevel);
        $config = $config ?? new QrCodeConfig();

        return $matrix->toPng(
            $config->getModuleSize(),
            $config->getMargin()
        );
    }

    /**
     * Generiert einen QR-Code als ASCII-Art
     *
     * @param string $data Die zu kodierenden Daten
     * @param ErrorCorrectionLevel $errorLevel Fehlerkorrektur-Level
     * @return string ASCII-Darstellung des QR-Codes
     */
    public function generateAscii(
        string $data,
        ErrorCorrectionLevel $errorLevel = ErrorCorrectionLevel::M
    ): string {
        $matrix = $this->generateQrCode($data, $errorLevel);

        return $matrix->toAscii();
    }
}
