<?php
if ( ! defined( 'ABSPATH' ) ) exit;

/**
 * Handles secure PDF download requests.
 * Accessed via ?pbuaiv_action=download&doc_type=invoice&order_id=123&token=...
 */
class PBUAIV_Download_Handler {

    private static ?PBUAIV_Download_Handler $instance = null;

    public static function instance() : self {
        if ( null === self::$instance ) self::$instance = new self();
        return self::$instance;
    }

    private function __construct() {
        add_action( 'init', [ $this, 'handle_download' ] );
    }

    public function handle_download() : void {
        // phpcs:disable WordPress.Security.NonceVerification.Recommended,WordPress.Security.ValidatedSanitizedInput -- uses HMAC token auth, no nonce
        if ( empty( $_GET['pbuaiv_action'] ) ) return; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated
        if ( sanitize_key( wp_unslash( $_GET['pbuaiv_action'] ) ) !== 'download' ) return;

        $doc_type = sanitize_key( isset( $_GET['doc_type'] ) ? wp_unslash( $_GET['doc_type'] ) : 'invoice' );
        $order_id = (int) ( isset( $_GET['order_id'] ) ? wp_unslash( $_GET['order_id'] ) : 0 );
        $mode     = sanitize_key( isset( $_GET['mode'] )     ? wp_unslash( $_GET['mode'] )     : 'download' );
        $token    = sanitize_text_field( isset( $_GET['token'] ) ? wp_unslash( $_GET['token'] ) : '' );
        // phpcs:enable

        if ( ! $order_id ) wp_die( esc_html__( 'Invalid request.', 'pb-invoicing-system' ) );

        // Verify token (nonce-based, per order)
        if ( ! $this->verify_token( $token, $order_id, $doc_type ) ) {
            wp_die( esc_html__( 'Invalid or expired download link.', 'pb-invoicing-system' ) );
        }

        $order = wc_get_order( $order_id );
        if ( ! $order ) wp_die( esc_html__( 'Order not found.', 'pb-invoicing-system' ) );

        // Permission: admin can always download; customer only their own orders
        if ( ! current_user_can( 'manage_woocommerce' ) ) {
            $customer_allowed = get_option( 'pbuaiv_customer_download', 'yes' ) === 'yes';
            if ( ! $customer_allowed ) wp_die( esc_html__( 'Downloads are disabled.', 'pb-invoicing-system' ) );

            // Logged-in customer must own the order
            if ( is_user_logged_in() ) {
                if ( (int) $order->get_user_id() !== get_current_user_id() ) {
                    wp_die( esc_html__( 'Access denied.', 'pb-invoicing-system' ) );
                }
            } else {
                // Guest: check guest download setting
                if ( get_option( 'pbuaiv_guest_download', 'yes' ) !== 'yes' ) {
                    wp_die( esc_html__( 'Please log in to download documents.', 'pb-invoicing-system' ) );
                }
                // Guest token is validated above (contains order key)
            }
        }

        $doc = $this->make_document( $doc_type, $order );
        if ( ! $doc ) wp_die( esc_html__( 'Document type not found.', 'pb-invoicing-system' ) );

        if ( $mode === 'view' ) {
            // Show the HTML template in-browser — pixel-perfect preview
            $doc->stream_html_view();
        } else {
            // 'download' (default) and 'pdf' both generate a real server-side PDF download.
            // This avoids the browser print dialog and uses the same template HTML rendered in preview mode.
            $doc->stream_pdf( 'attachment' );
        }
    }

    /**
     * Generate a secure download URL for a document.
     */
    public static function get_url( int $order_id, string $doc_type, string $mode = 'download' ) : string {
        $token = self::make_token( $order_id, $doc_type );
        return add_query_arg( [
            'pbuaiv_action' => 'download',
            'doc_type'   => $doc_type,
            'order_id'   => $order_id,
            'mode'       => $mode,
            'token'      => $token,
        ], home_url( '/' ) );
    }

    /**
     * Generate token (HMAC of order_id + doc_type + order_key).
     */
    private static function make_token( int $order_id, string $doc_type ) : string {
        $order = wc_get_order( $order_id );
        $key   = $order ? $order->get_order_key() : '';
        return hash_hmac( 'sha256', $order_id . '|' . $doc_type . '|' . $key, wp_salt( 'auth' ) );
    }

    private function verify_token( string $token, int $order_id, string $doc_type ) : bool {
        $expected = self::make_token( $order_id, $doc_type );
        return hash_equals( $expected, $token );
    }

    private function make_document( string $type, WC_Order $order ) : ?PBUAIV_Document {
        $map = [
            'invoice'       => 'PBUAIV_Invoice',
            'receipt'       => 'PBUAIV_Receipt',
            'credit_note'   => 'PBUAIV_Credit_Note',
            'proforma'      => 'PBUAIV_Proforma',
            'packing_slip'  => 'PBUAIV_Packing_Slip',
            'delivery_note' => 'PBUAIV_Delivery_Note',
        ];
        if ( ! isset( $map[ $type ] ) ) return null;
        $class = $map[ $type ];
        return new $class( $order );
    }
}
