<?php
/**
 * Parser XML UPO (Urzędowe Potwierdzenie Odbioru) z KSeF v2.
 *
 * Namespace: http://upo.schematy.mf.gov.pl/KSeF/v4-3
 * Wyciąga: numer KSeF, data przyjęcia, kod kreskowy QR (opcjonalnie).
 *
 * @package KSEF\WordPress\V2
 */

declare(strict_types=1);

namespace KSEF\WordPress\V2;

use WP_Error;

class Upo_Parser {

	private const NS_UPO = 'http://upo.schematy.mf.gov.pl/KSeF/v4-3';

	/**
	 * @return array{ksef_number:string,issued_at:string,verification_url:string|null}|WP_Error
	 */
	public function parse( string $upo_xml ): array|WP_Error {
		if ( trim( $upo_xml ) === '' ) {
			return new WP_Error( 'upo_empty', 'UPO XML pusty.' );
		}

		libxml_use_internal_errors( true );
		$dom = new \DOMDocument();
		if ( ! $dom->loadXML( $upo_xml ) ) {
			$errs = array_map( static fn ( $e ) => trim( $e->message ), libxml_get_errors() );
			libxml_clear_errors();
			return new WP_Error( 'upo_xml_invalid', 'UPO XML nieprawidłowy: ' . implode( '; ', $errs ) );
		}

		$xpath = new \DOMXPath( $dom );
		// Try common namespace prefixes
		$xpath->registerNamespace( 'u', self::NS_UPO );

		$ksef_number = $this->first_text(
			$xpath,
			[
				'//u:NumerKSeFDokumentu',
				'//u:NumerKSeF',
				'//*[local-name()="NumerKSeFDokumentu"]',
				'//*[local-name()="NumerKSeF"]',
			]
		);
		$issued_at = $this->first_text(
			$xpath,
			[
				'//u:DataPrzyjeciaWKSeF',
				'//u:DataPrzyjeciaWKSeFRefSec',
				'//*[local-name()="DataPrzyjeciaWKSeF"]',
				'//*[local-name()="DataPrzyjecia"]',
			]
		);
		$verify_url = $this->first_text(
			$xpath,
			[
				'//u:AdresURL',
				'//*[local-name()="AdresURL"]',
			]
		);

		if ( $ksef_number === '' ) {
			return new WP_Error( 'upo_no_ksef_number', 'Brak NumerKSeFDokumentu w UPO XML.' );
		}

		return [
			'ksef_number'      => $ksef_number,
			'issued_at'        => $issued_at,
			'verification_url' => $verify_url !== '' ? $verify_url : null,
		];
	}

	/**
	 * @param list<string> $queries
	 */
	private function first_text( \DOMXPath $xpath, array $queries ): string {
		foreach ( $queries as $q ) {
			$nodes = $xpath->query( $q );
			if ( $nodes instanceof \DOMNodeList && $nodes->length > 0 ) {
				$text = trim( (string) $nodes->item( 0 )->textContent );
				if ( $text !== '' ) {
					return $text;
				}
			}
		}
		return '';
	}
}
