<?php
// phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare, WordPress.DB.SlowDBQuery.slow_db_query_meta_key, WordPress.DB.DirectDatabaseQuery.SchemaChange
if ( ! defined( 'ABSPATH' ) ) exit;

/**
 * AJAX handlers for admin order metabox actions and settings.
 */
class PBUAIV_Ajax {

    private static ?PBUAIV_Ajax $instance = null;

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

    private function __construct() {
        $actions = [ 'issue', 'void', 'send', 'regenerate', 'xml', 'save_settings', 'upload_logo', 'reset_sequence', 'preview_template' ];
        foreach ( $actions as $a ) {
            add_action( 'wp_ajax_pbuaiv_' . $a, [ $this, 'handle_' . str_replace( '-', '_', $a ) ] );
        }
        add_action( 'wp_ajax_pbuaiv_xml', [ $this, 'handle_xml' ] );
    }

    // ── Security helper ───────────────────────────────────────────────────────

    private function verify() : void {
        if ( ! check_ajax_referer( 'pbuaiv_admin', 'nonce', false ) ) {
            wp_send_json_error( [ 'message' => __( 'Security check failed.', 'pb-invoicing-system' ) ], 403 );
        }
        if ( ! current_user_can( 'manage_woocommerce' ) ) {
            wp_send_json_error( [ 'message' => __( 'Permission denied.', 'pb-invoicing-system' ) ], 403 );
        }
    }

    private function get_order() : WC_Order {
        // nonce already verified in verify(); wp_unslash safe on int cast
        $order_id = (int) ( isset( $_POST['order_id'] ) ? wp_unslash( $_POST['order_id'] ) : ( isset( $_GET['order_id'] ) ? wp_unslash( $_GET['order_id'] ) : 0 ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
        $order    = wc_get_order( $order_id );
        if ( ! $order ) {
            wp_send_json_error( [ 'message' => __( 'Order not found.', 'pb-invoicing-system' ) ], 404 );
        }
        return $order;
    }

    private function get_doc( WC_Order $order ) : PBUAIV_Document {
        $type = sanitize_key( wp_unslash( $_POST['doc_type'] ?? ( $_GET['doc_type'] ?? 'invoice' ) ) ); // phpcs:ignore WordPress.Security.NonceVerification
        $doc  = PBUAIV_Email_Manager::factory( $type, $order );
        if ( ! $doc ) {
            wp_send_json_error( [ 'message' => __( 'Unknown document type.', 'pb-invoicing-system' ) ], 400 );
        }
        return $doc;
    }

    // ── Issue ─────────────────────────────────────────────────────────────────

    public function handle_issue() : void {
        $this->verify();
        $order = $this->get_order();
        $doc   = $this->get_doc( $order );

        if ( $doc->is_issued() ) {
            wp_send_json_error( [ 'message' => __( 'Document already issued.', 'pb-invoicing-system' ) ] );
        }

        if ( $doc->issue() ) {
            $data = $doc->get_data();
            wp_send_json_success( [
                /* translators: 1: document label, 2: document number */
                'message'      => sprintf( __( '%1$s issued: %2$s', 'pb-invoicing-system' ), $data['label'], $data['doc_number'] ),
                'doc_number'   => $data['doc_number'],
                'doc_date'     => $data['doc_date'],
                'download_url' => PBUAIV_Download_Handler::get_url( $order->get_id(), $doc->get_data()['type'], 'download' ),
                'view_url'     => PBUAIV_Download_Handler::get_url( $order->get_id(), $doc->get_data()['type'], 'view' ),
            ] );
        }

        wp_send_json_error( [ 'message' => __( 'Failed to issue document.', 'pb-invoicing-system' ) ] );
    }

    // ── Void ──────────────────────────────────────────────────────────────────

    public function handle_void() : void {
        $this->verify();
        $order = $this->get_order();
        $doc   = $this->get_doc( $order );

        if ( $doc->void() ) {
            wp_send_json_success( [ 'message' => __( 'Document voided.', 'pb-invoicing-system' ) ] );
        }
        wp_send_json_error( [ 'message' => __( 'Failed to void document.', 'pb-invoicing-system' ) ] );
    }

    // ── Send ──────────────────────────────────────────────────────────────────

    public function handle_send() : void {
        $this->verify();
        $order    = $this->get_order();
        $doc_type = sanitize_key( wp_unslash( $_POST['doc_type'] ?? 'invoice' ) ); // phpcs:ignore WordPress.Security.NonceVerification

        if ( PBUAIV_Email_Manager::send_manual( $order, $doc_type ) ) {
            wp_send_json_success( [ 'message' => __( 'Document emailed to customer.', 'pb-invoicing-system' ) ] );
        }
        wp_send_json_error( [ 'message' => __( 'Email failed. Check your WP mail configuration.', 'pb-invoicing-system' ) ] );
    }

    // ── Regenerate PDF ────────────────────────────────────────────────────────

    public function handle_regenerate() : void {
        $this->verify();
        $order    = $this->get_order();
        $doc      = $this->get_doc( $order );
        $doc_type = $doc->get_data()['type'];

        // Delete cached PDF using WP-safe helper
        $upload_dir = wp_upload_dir();
        $pdf_path   = $upload_dir['basedir'] . '/pbuaiv-documents/' . sanitize_file_name( $doc->get_pdf_filename() );
        if ( file_exists( $pdf_path ) ) {
            wp_delete_file( $pdf_path );
        }

        wp_send_json_success( [
            'message'      => __( 'PDF regenerated.', 'pb-invoicing-system' ),
            'download_url' => PBUAIV_Download_Handler::get_url( $order->get_id(), $doc_type, 'download' ),
        ] );
    }

    // ── XML Export ────────────────────────────────────────────────────────────

    public function handle_xml() : void {
        if ( ! current_user_can( 'manage_woocommerce' ) ) {
            wp_die( 'Permission denied' );
        }
        $nonce    = isset( $_GET['nonce'] )    ? sanitize_text_field( wp_unslash( $_GET['nonce'] ) )    : '';
        $order_id = isset( $_GET['order_id'] ) ? (int) wp_unslash( $_GET['order_id'] )                  : 0;
        if ( ! wp_verify_nonce( $nonce, 'pbuaiv_xml_' . $order_id ) ) {
            wp_die( 'Invalid nonce' );
        }

        $doc_type = sanitize_key( wp_unslash( $_GET['doc_type'] ?? 'invoice' ) );
        $order    = wc_get_order( $order_id );
        if ( ! $order ) {
            wp_die( 'Order not found' );
        }

        $doc  = PBUAIV_Email_Manager::factory( $doc_type, $order );
        $data = $doc->get_data();
        $xml  = PBUAIV_FTA_Compliance::generate_xml( $data );

        header( 'Content-Type: application/xml; charset=UTF-8' );
        header( 'Content-Disposition: attachment; filename="' . sanitize_file_name( $data['doc_number'] ?: $doc_type ) . '.xml"' );
        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- raw XML output, not HTML
        echo $xml;
        exit;
    }

    // ── Reset sequence ────────────────────────────────────────────────────────

    public function handle_reset_sequence() : void {
        $this->verify();
        $doc_type = sanitize_key( wp_unslash( $_POST['doc_type'] ?? 'invoice' ) ); // phpcs:ignore WordPress.Security.NonceVerification
        $next     = max( 1, (int) wp_unslash( $_POST['next_number'] ?? 1 ) );       // phpcs:ignore WordPress.Security.NonceVerification
        PBUAIV_Sequence::instance()->set_next( $doc_type, $next );
        wp_send_json_success( [
            /* translators: 1: document type, 2: next number */
            'message' => sprintf( __( 'Next %1$s number set to %2$d.', 'pb-invoicing-system' ), $doc_type, $next ),
            'preview' => PBUAIV_Sequence::instance()->peek( $doc_type ),
        ] );
    }

    // ── Save settings ─────────────────────────────────────────────────────────

    public function handle_save_settings() : void {
        $this->verify();
        $allowed = [
            'pbuaiv_company_name', 'pbuaiv_company_address', 'pbuaiv_company_city', 'pbuaiv_company_emirate',
            'pbuaiv_company_phone', 'pbuaiv_company_email', 'pbuaiv_company_website', 'pbuaiv_trn',
            'pbuaiv_bank_name', 'pbuaiv_bank_iban', 'pbuaiv_bank_swift', 'pbuaiv_bank_account',
            'pbuaiv_brand_primary', 'pbuaiv_brand_secondary', 'pbuaiv_logo_id',
            'pbuaiv_vat_rate', 'pbuaiv_currency_aed_rate', 'pbuaiv_default_template', 'pbuaiv_doc_language',
            'pbuaiv_invoice_prefix', 'pbuaiv_invoice_suffix', 'pbuaiv_invoice_padding', 'pbuaiv_invoice_reset',
            'pbuaiv_receipt_prefix', 'pbuaiv_receipt_suffix', 'pbuaiv_receipt_padding', 'pbuaiv_receipt_reset',
            'pbuaiv_credit_note_prefix', 'pbuaiv_credit_note_suffix', 'pbuaiv_credit_note_padding', 'pbuaiv_credit_note_reset',
            'pbuaiv_proforma_prefix', 'pbuaiv_proforma_suffix', 'pbuaiv_proforma_padding', 'pbuaiv_proforma_reset',
            'pbuaiv_packing_slip_prefix', 'pbuaiv_packing_slip_suffix', 'pbuaiv_packing_slip_padding', 'pbuaiv_packing_slip_reset',
            'pbuaiv_delivery_note_prefix', 'pbuaiv_delivery_note_suffix', 'pbuaiv_delivery_note_padding', 'pbuaiv_delivery_note_reset',
            'pbuaiv_paper_size', 'pbuaiv_invoice_notes', 'pbuaiv_payment_terms',
            'pbuaiv_auto_invoice_status', 'pbuaiv_auto_receipt_status', 'pbuaiv_auto_credit_note_status',
            'pbuaiv_attach_invoice_emails', 'pbuaiv_attach_receipt_emails', 'pbuaiv_attach_credit_note_emails',
            'pbuaiv_attach_proforma_emails',
            'pbuaiv_customer_download', 'pbuaiv_guest_download',
        ];

        $array_options = [
            'pbuaiv_auto_invoice_status',
            'pbuaiv_auto_receipt_status',
            'pbuaiv_auto_credit_note_status',
            'pbuaiv_attach_invoice_emails',
            'pbuaiv_attach_receipt_emails',
            'pbuaiv_attach_credit_note_emails',
            'pbuaiv_attach_proforma_emails',
        ];

        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        $data = isset( $_POST['settings'] ) ? wp_unslash( $_POST['settings'] ) : [];
        foreach ( $allowed as $key ) {
            if ( ! isset( $data[ $key ] ) ) {
                if ( in_array( $key, $array_options, true ) ) {
                    update_option( $key, [] );
                }
                continue;
            }
            $val = $data[ $key ];
            if ( is_array( $val ) ) {
                $val = array_map( 'sanitize_key', $val );
            } elseif ( strpos( $key, 'brand' ) !== false ) {
                $val = sanitize_hex_color( $val );
            } else {
                $val = sanitize_text_field( $val );
            }
            update_option( $key, $val );
        }

        wp_send_json_success( [ 'message' => __( 'Settings saved.', 'pb-invoicing-system' ) ] );
    }

    // ── Preview template ──────────────────────────────────────────────────────

    public function handle_preview_template() : void {
        $this->verify();
        $orders = wc_get_orders( [ 'limit' => 1, 'status' => 'any' ] );
        if ( empty( $orders ) ) {
            wp_send_json_error( [ 'message' => __( 'No orders found for preview.', 'pb-invoicing-system' ) ] );
        }
        $order    = $orders[0];
        $doc_type = sanitize_key( wp_unslash( $_POST['doc_type'] ?? 'invoice' ) ); // phpcs:ignore WordPress.Security.NonceVerification
        $template = sanitize_key( wp_unslash( $_POST['template'] ?? 'modern' ) );  // phpcs:ignore WordPress.Security.NonceVerification
        $doc      = PBUAIV_Email_Manager::factory( $doc_type, $order );
        if ( ! $doc ) {
            wp_send_json_error( [] );
        }

        $html = $doc->get_html( $template );
        wp_send_json_success( [ 'html' => $html ] );
    }

    // ── Upload logo ───────────────────────────────────────────────────────────

    public function handle_upload_logo() : void {
        $this->verify();
        $logo_id = (int) wp_unslash( $_POST['logo_id'] ?? 0 ); // phpcs:ignore WordPress.Security.NonceVerification
        update_option( 'pbuaiv_logo_id', $logo_id );
        wp_send_json_success( [ 'logo_url' => wp_get_attachment_image_url( $logo_id, 'medium' ) ] );
    }
}
