<?php
/* Copyright (C) 2025 Eduard Wisch <data@data-it-solution.de>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
 */

/**
 * \file    lib/qrcode.class.php
 * \ingroup epcqr
 * \brief   QR-Code Generator mit lokalem Caching
 */

/**
 * QRCode Generator Klasse
 * Generiert QR-Codes und cached sie lokal für Wiederverwendung
 */
class QRCodeGenerator
{
	private $db;
	private $cacheDir;

	/**
	 * Constructor
	 *
	 * @param DoliDB $db Database handler
	 */
	public function __construct($db)
	{
		global $conf;

		$this->db = $db;

		// Cache-Verzeichnis für QR-Codes
		$this->cacheDir = $conf->epcqr->dir_output.'/qrcodes';

		// Verzeichnis erstellen falls nicht vorhanden
		if (!is_dir($this->cacheDir)) {
			dol_mkdir($this->cacheDir);
		}
	}

	/**
	 * Generiert einen EPC-QR-Code für SEPA-Überweisungen
	 *
	 * @param  string  $accountHolder  Kontoinhaber Name
	 * @param  string  $iban           IBAN
	 * @param  string  $bic            BIC (optional)
	 * @param  float   $amount         Betrag
	 * @param  string  $reference      Verwendungszweck
	 * @return string|false            Pfad zur generierten QR-Code-Datei oder false bei Fehler
	 */
	public function generateEPCQRCode($accountHolder, $iban, $bic, $amount, $reference)
	{
		// Eindeutigen Dateinamen generieren basierend auf Parametern
		$hash = md5($accountHolder.$iban.$bic.$amount.$reference);
		$filename = 'epc_'.$hash.'.png';
		$filepath = $this->cacheDir.'/'.$filename;

		// Prüfen ob QR-Code bereits cached ist
		if (file_exists($filepath)) {
			dol_syslog("QRCodeGenerator: QR-Code aus Cache geladen: ".$filepath, LOG_DEBUG);
			return $filepath;
		}

		// QR-Code generieren
		$qrData = $this->generateEPCData($accountHolder, $iban, $bic, $amount, $reference);
		$result = $this->generateQRImage($qrData, $filepath);

		if ($result) {
			dol_syslog("QRCodeGenerator: QR-Code generiert: ".$filepath, LOG_DEBUG);
			return $filepath;
		}

		dol_syslog("QRCodeGenerator: Fehler beim Generieren des QR-Codes", LOG_ERR);
		return false;
	}

	/**
	 * Generiert einen generischen QR-Code aus beliebigem Text
	 *
	 * @param  string  $data           Daten für QR-Code
	 * @param  string  $prefix         Präfix für Dateinamen (default: 'qr')
	 * @return string|false            Pfad zur generierten QR-Code-Datei oder false bei Fehler
	 */
	public function generateQRCode($data, $prefix = 'qr')
	{
		// Eindeutigen Dateinamen generieren
		$hash = md5($data);
		$filename = $prefix.'_'.$hash.'.png';
		$filepath = $this->cacheDir.'/'.$filename;

		// Prüfen ob QR-Code bereits cached ist
		if (file_exists($filepath)) {
			dol_syslog("QRCodeGenerator: QR-Code aus Cache geladen: ".$filepath, LOG_DEBUG);
			return $filepath;
		}

		// QR-Code generieren
		$result = $this->generateQRImage($data, $filepath);

		if ($result) {
			dol_syslog("QRCodeGenerator: QR-Code generiert: ".$filepath, LOG_DEBUG);
			return $filepath;
		}

		dol_syslog("QRCodeGenerator: Fehler beim Generieren des QR-Codes", LOG_ERR);
		return false;
	}

	/**
	 * Generiert EPC-Datenstring für SEPA-QR-Codes
	 *
	 * @param  string  $accountHolder  Kontoinhaber Name
	 * @param  string  $iban           IBAN
	 * @param  string  $bic            BIC
	 * @param  float   $amount         Betrag
	 * @param  string  $reference      Verwendungszweck
	 * @return string                  EPC-Datenstring
	 */
	private function generateEPCData($accountHolder, $iban, $bic, $amount, $reference)
	{
		// EPC QR-Code Format (GiroCode Standard)
		$epcData = array(
			'BCD',                           // Service Tag
			'002',                           // Version
			'1',                             // Character set (1 = UTF-8)
			'SCT',                           // Identification (SEPA Credit Transfer)
			$bic,                            // BIC
			$accountHolder,                  // Empfänger Name
			$iban,                           // Empfänger IBAN
			'EUR'.number_format($amount, 2, '.', ''), // Betrag
			'',                              // Purpose (optional)
			$reference,                      // Verwendungszweck
			''                               // Beneficiary to originator information (optional)
		);

		return implode("\n", $epcData);
	}

	/**
	 * Generiert QR-Code-Bild aus Daten
	 *
	 * Nutzt zunächst den externen Service, später kann dies durch
	 * eine native PHP-Implementierung ersetzt werden
	 *
	 * @param  string  $data      Daten für QR-Code
	 * @param  string  $filepath  Zielpfad für PNG-Datei
	 * @return bool               true bei Erfolg, false bei Fehler
	 */
	private function generateQRImage($data, $filepath)
	{
		// Methode 1: Externe API (aktuell)
		// TODO: Später durch native PHP-Generierung ersetzen
		$url = 'https://qr.data-it-solution.de/generate?data='.urlencode($data).'&size=300';

		// Bild von URL holen
		$imageData = @file_get_contents($url);

		if ($imageData === false) {
			// Fallback: Versuche mit cURL
			if (function_exists('curl_init')) {
				$ch = curl_init($url);
				curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
				curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
				curl_setopt($ch, CURLOPT_TIMEOUT, 10);
				$imageData = curl_exec($ch);
				$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
				curl_close($ch);

				if ($httpCode !== 200 || $imageData === false) {
					return false;
				}
			} else {
				return false;
			}
		}

		// Bild speichern
		$result = file_put_contents($filepath, $imageData);

		return ($result !== false);
	}

	/**
	 * Löscht gecachte QR-Codes die älter als X Tage sind
	 *
	 * @param  int  $days  Anzahl Tage (default: 30)
	 * @return int         Anzahl gelöschter Dateien
	 */
	public function cleanCache($days = 30)
	{
		$deleted = 0;
		$threshold = time() - ($days * 86400);

		if (!is_dir($this->cacheDir)) {
			return 0;
		}

		$files = scandir($this->cacheDir);
		foreach ($files as $file) {
			if ($file === '.' || $file === '..') {
				continue;
			}

			$filepath = $this->cacheDir.'/'.$file;

			if (is_file($filepath) && filemtime($filepath) < $threshold) {
				if (unlink($filepath)) {
					$deleted++;
				}
			}
		}

		dol_syslog("QRCodeGenerator: ".$deleted." alte QR-Codes gelöscht", LOG_INFO);
		return $deleted;
	}
}
