<?php
declare(strict_types=1);

namespace Itdatex\Rechnungseingang;

if ( ! defined( 'ABSPATH' ) ) { exit; }

/**
 * Sichere Datei-Auslieferung der Originalrechnung.
 *
 * Nie per direkter URL auf das Upload-Verzeichnis — der Pfad wird per
 * stored_name in der DB referenziert, der Endpoint prueft Capability +
 * Nonce + tatsaechliche Existenz, dann readfile().
 */
final class DownloadHandler
{
    public const ACTION = 'reing_download';
    public const NONCE  = 'reing_download_nonce';

    public function register(): void
    {
        add_action( 'admin_post_' . self::ACTION, [ $this, 'handle' ] );
    }

    public function handle(): void
    {
        if ( ! current_user_can( Plugin::CAPABILITY ) ) {
            wp_die( esc_html__( 'Keine Berechtigung.', 'itdatex-e-invoice-intake' ), '', [ 'response' => 403 ] );
        }

        $fileId = isset( $_GET['file_id'] ) ? (int) $_GET['file_id'] : 0;
        if ( $fileId <= 0 ) {
            wp_die( 'Ungueltige Anfrage.', '', [ 'response' => 400 ] );
        }
        check_admin_referer( self::ACTION . '_' . $fileId, self::NONCE );

        $repo = new InvoiceRepository();
        $file = $repo->findFile( $fileId );
        if ( ! $file ) {
            wp_die( 'Datei nicht gefunden.', '', [ 'response' => 404 ] );
        }

        $storage  = new Storage();
        $fullPath = $storage->fullPath( (string) $file->stored_name );
        if ( ! is_file( $fullPath ) || ! is_readable( $fullPath ) ) {
            wp_die( 'Datei nicht lesbar.', '', [ 'response' => 500 ] );
        }

        $repo->appendAudit(
            null,
            wp_get_current_user()->user_login ?: 'system',
            'downloaded',
            "file_id={$fileId}"
        );

        nocache_headers();
        header( 'Content-Type: ' . ( $file->mime ?: 'application/octet-stream' ) );
        header( 'Content-Disposition: attachment; filename="' . self::safeFilename( (string) $file->original_name ) . '"' );
        header( 'Content-Length: ' . (int) $file->size_bytes );
        header( 'X-Content-Type-Options: nosniff' );

        readfile( $fullPath );
        exit;
    }

    private static function safeFilename( string $name ): string
    {
        // Filtere CR/LF aus dem Header und ggf. Anfuehrungszeichen
        return str_replace( [ "\r", "\n", '"' ], '', $name );
    }
}
