<?php

declare(strict_types=1);

namespace Instinctor\Services;

use Instinctor\Core\Config;
use Instinctor\Core\DB;
use Instinctor\Core\Tenant;


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

/**
 * Invoice Service
 * Generates invoices and packing slips
 */
class InvoiceService
{
    /**
     * Get company info for documents
     */
    private static function getCompanyInfo(): array
    {
        return [
            'name' => Config::get('instinctor_company_name', get_bloginfo('name')),
            'address' => Config::get('instinctor_company_address', ''),
            'city' => Config::get('instinctor_company_city', ''),
            'state' => Config::get('instinctor_company_state', ''),
            'zip' => Config::get('instinctor_company_zip', ''),
            'country' => Config::get('instinctor_company_country', ''),
            'phone' => Config::get('instinctor_company_phone', ''),
            'email' => Config::get('instinctor_company_email', Config::get('admin_email', '')),
            'logo' => Config::get('instinctor_company_logo', ''),
            'tax_id' => Config::get('instinctor_company_tax_id', ''),
        ];
    }

    /**
     * Get order data for documents
     */
    private static function getOrderData(int $orderId): ?array
    {

        $p = DB::prefix();
        $order = DB::get_row(DB::prepare(
            "SELECT o.*, c.first_name, c.last_name, c.email, c.phone
             FROM {$p}instinctor_orders o
             LEFT JOIN {$p}instinctor_customers c ON o.customer_id = c.id
             WHERE o.id = %d",
            $orderId
        ));

        if (!$order) {
            return null;
        }

        $items = DB::get_results(DB::prepare(
            "SELECT * FROM {$p}instinctor_order_items WHERE order_id = %d",
            $orderId
        ));

        $billing = json_decode($order->billing_address, true) ?: [];
        $shipping = json_decode($order->shipping_address, true) ?: [];

        return [
            'order' => $order,
            'items' => $items,
            'billing' => $billing,
            'shipping' => $shipping,
        ];
    }

    /**
     * Generate invoice HTML
     */
    public static function generateInvoice(int $orderId): ?string
    {
        $data = self::getOrderData($orderId);
        if (!$data) {
            return null;
        }

        $company = self::getCompanyInfo();
        $order = $data['order'];
        $items = $data['items'];
        $billing = $data['billing'];

        ob_start();
        ?>
        <!DOCTYPE html>
        <html>
        <head>
            <meta charset="UTF-8">
            <title>Invoice #<?php echo esc_html($order->order_number); ?></title>
            <style>
                * { margin: 0; padding: 0; box-sizing: border-box; }
                body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; font-size: 14px; line-height: 1.5; color: #333; padding: 40px; }
                .invoice { max-width: 800px; margin: 0 auto; }
                .header { display: flex; justify-content: space-between; margin-bottom: 40px; }
                .logo img { max-height: 60px; }
                .company-info { text-align: right; font-size: 12px; color: #666; }
                .invoice-title { font-size: 28px; font-weight: bold; color: #1d1d1f; margin-bottom: 20px; }
                .invoice-meta { display: flex; justify-content: space-between; margin-bottom: 40px; }
                .meta-block { }
                .meta-block h3 { font-size: 12px; text-transform: uppercase; color: #666; margin-bottom: 5px; }
                .meta-block p { margin: 2px 0; }
                table { width: 100%; border-collapse: collapse; margin: 20px 0; }
                th { text-align: left; padding: 12px; background: #f5f5f7; border-bottom: 2px solid #ddd; font-size: 12px; text-transform: uppercase; color: #666; }
                td { padding: 12px; border-bottom: 1px solid #eee; }
                .text-right { text-align: right; }
                .totals { margin-top: 20px; margin-left: auto; width: 300px; }
                .totals-row { display: flex; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid #eee; }
                .totals-row.total { font-size: 18px; font-weight: bold; border-top: 2px solid #333; border-bottom: none; padding-top: 12px; }
                .footer { margin-top: 60px; padding-top: 20px; border-top: 1px solid #eee; text-align: center; font-size: 12px; color: #666; }
                .status { display: inline-block; padding: 4px 12px; border-radius: 4px; font-size: 12px; font-weight: 500; }
                .status-paid { background: #d4edda; color: #155724; }
                .status-pending { background: #fff3cd; color: #856404; }
                @media print { body { padding: 20px; } .no-print { display: none; } }
            </style>
        </head>
        <body>
            <div class="invoice">
                <div class="header">
                    <div class="logo">
                        <?php if ($company['logo']): ?>
                            <img src="<?php echo esc_url($company['logo']); ?>" alt="<?php echo esc_attr($company['name']); ?>">
                        <?php else: ?>
                            <h1 style="font-size: 24px;"><?php echo esc_html($company['name']); ?></h1>
                        <?php endif; ?>
                    </div>
                    <div class="company-info">
                        <strong><?php echo esc_html($company['name']); ?></strong><br>
                        <?php if ($company['address']): ?><?php echo esc_html($company['address']); ?><br><?php endif; ?>
                        <?php if ($company['city'] || $company['state'] || $company['zip']): ?>
                            <?php echo esc_html($company['city']); ?>, <?php echo esc_html($company['state']); ?> <?php echo esc_html($company['zip']); ?><br>
                        <?php endif; ?>
                        <?php if ($company['phone']): ?><?php echo esc_html($company['phone']); ?><br><?php endif; ?>
                        <?php if ($company['email']): ?><?php echo esc_html($company['email']); ?><br><?php endif; ?>
                        <?php if ($company['tax_id']): ?>Tax ID: <?php echo esc_html($company['tax_id']); ?><?php endif; ?>
                    </div>
                </div>

                <h1 class="invoice-title">
                    Invoice #<?php echo esc_html($order->order_number); ?>
                    <span class="status status-<?php echo $order->status === 'completed' ? 'paid' : 'pending'; ?>">
                        <?php echo esc_html( $order->status === 'completed' ? 'PAID' : strtoupper( (string) $order->status ) ); ?>
                    </span>
                </h1>

                <div class="invoice-meta">
                    <div class="meta-block">
                        <h3>Bill To</h3>
                        <p><strong><?php echo esc_html(($billing['first_name'] ?? '') . ' ' . ($billing['last_name'] ?? '')); ?></strong></p>
                        <?php if (!empty($billing['company'])): ?><p><?php echo esc_html($billing['company']); ?></p><?php endif; ?>
                        <p><?php echo esc_html($billing['address_1'] ?? ''); ?></p>
                        <?php if (!empty($billing['address_2'])): ?><p><?php echo esc_html($billing['address_2']); ?></p><?php endif; ?>
                        <p><?php echo esc_html(($billing['city'] ?? '') . ', ' . ($billing['state'] ?? '') . ' ' . ($billing['postcode'] ?? '')); ?></p>
                        <p><?php echo esc_html($billing['country'] ?? ''); ?></p>
                        <?php if (!empty($billing['email'])): ?><p><?php echo esc_html($billing['email']); ?></p><?php endif; ?>
                    </div>
                    <div class="meta-block" style="text-align: right;">
                        <h3>Invoice Details</h3>
                        <p><strong>Invoice Date:</strong> <?php echo esc_html( date('F j, Y', strtotime($order->created_at)) ); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date -- intentional local-time display ?></p>
                        <p><strong>Order Date:</strong> <?php echo esc_html( date('F j, Y', strtotime($order->created_at)) ); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date -- intentional local-time display ?></p>
                        <?php if ($order->payment_method): ?>
                        <p><strong>Payment Method:</strong> <?php echo esc_html(ucfirst($order->payment_method)); ?></p>
                        <?php endif; ?>
                    </div>
                </div>

                <table>
                    <thead>
                        <tr>
                            <th>Item</th>
                            <th>SKU</th>
                            <th class="text-right">Qty</th>
                            <th class="text-right">Unit Price</th>
                            <th class="text-right">Total</th>
                        </tr>
                    </thead>
                    <tbody>
                        <?php foreach ($items as $item): ?>
                        <tr>
                            <td><?php echo esc_html($item->name); ?></td>
                            <td><?php echo esc_html($item->sku ?: '-'); ?></td>
                            <td class="text-right"><?php echo esc_html($item->quantity); ?></td>
                            <td class="text-right"><?php echo esc_html(CurrencyService::formatPrice($item->price)); ?></td>
                            <td class="text-right"><?php echo esc_html(CurrencyService::formatPrice($item->total)); ?></td>
                        </tr>
                        <?php endforeach; ?>
                    </tbody>
                </table>

                <div class="totals">
                    <div class="totals-row">
                        <span>Subtotal</span>
                        <span><?php echo esc_html(CurrencyService::formatPrice($order->subtotal)); ?></span>
                    </div>
                    <?php if ($order->discount_total > 0): ?>
                    <div class="totals-row">
                        <span>Discount</span>
                        <span>-<?php echo esc_html(CurrencyService::formatPrice($order->discount_total)); ?></span>
                    </div>
                    <?php endif; ?>
                    <?php if ($order->shipping_total > 0): ?>
                    <div class="totals-row">
                        <span>Shipping</span>
                        <span><?php echo esc_html(CurrencyService::formatPrice($order->shipping_total)); ?></span>
                    </div>
                    <?php endif; ?>
                    <?php if ($order->tax_total > 0): ?>
                    <div class="totals-row">
                        <span>Tax</span>
                        <span><?php echo esc_html(CurrencyService::formatPrice($order->tax_total)); ?></span>
                    </div>
                    <?php endif; ?>
                    <div class="totals-row total">
                        <span>Total</span>
                        <span><?php echo esc_html(CurrencyService::formatPrice($order->total)); ?></span>
                    </div>
                </div>

                <div class="footer">
                    <p>Thank you for your business!</p>
                    <p class="no-print" style="margin-top: 20px;">
                        <button onclick="window.print()" style="padding: 10px 20px; cursor: pointer;">Print Invoice</button>
                    </p>
                </div>
            </div>
        </body>
        </html>
        <?php
        return ob_get_clean();
    }

    /**
     * Generate packing slip HTML
     */
    public static function generatePackingSlip(int $orderId): ?string
    {
        $data = self::getOrderData($orderId);
        if (!$data) {
            return null;
        }

        $company = self::getCompanyInfo();
        $order = $data['order'];
        $items = $data['items'];
        $shipping = $data['shipping'];

        ob_start();
        ?>
        <!DOCTYPE html>
        <html>
        <head>
            <meta charset="UTF-8">
            <title>Packing Slip - Order #<?php echo esc_html($order->order_number); ?></title>
            <style>
                * { margin: 0; padding: 0; box-sizing: border-box; }
                body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; font-size: 14px; line-height: 1.5; color: #333; padding: 40px; }
                .slip { max-width: 800px; margin: 0 auto; }
                .header { display: flex; justify-content: space-between; margin-bottom: 30px; padding-bottom: 20px; border-bottom: 2px solid #333; }
                .logo img { max-height: 50px; }
                .title { font-size: 24px; font-weight: bold; }
                .addresses { display: flex; gap: 40px; margin-bottom: 30px; }
                .address-block { flex: 1; }
                .address-block h3 { font-size: 12px; text-transform: uppercase; color: #666; margin-bottom: 10px; border-bottom: 1px solid #ddd; padding-bottom: 5px; }
                .order-info { background: #f5f5f7; padding: 15px; margin-bottom: 30px; display: flex; gap: 40px; }
                .order-info div { }
                .order-info label { font-size: 11px; text-transform: uppercase; color: #666; }
                .order-info strong { display: block; font-size: 14px; }
                table { width: 100%; border-collapse: collapse; }
                th { text-align: left; padding: 12px; background: #f5f5f7; border: 1px solid #ddd; font-size: 12px; text-transform: uppercase; }
                td { padding: 12px; border: 1px solid #ddd; }
                .text-center { text-align: center; }
                .checkbox { width: 20px; height: 20px; border: 2px solid #333; display: inline-block; }
                .notes { margin-top: 30px; padding: 15px; background: #fffbe6; border: 1px solid #ffe58f; }
                .footer { margin-top: 40px; text-align: center; font-size: 12px; color: #666; }
                @media print { body { padding: 20px; } .no-print { display: none; } }
            </style>
        </head>
        <body>
            <div class="slip">
                <div class="header">
                    <div class="logo">
                        <?php if ($company['logo']): ?>
                            <img src="<?php echo esc_url($company['logo']); ?>" alt="">
                        <?php else: ?>
                            <strong><?php echo esc_html($company['name']); ?></strong>
                        <?php endif; ?>
                    </div>
                    <div class="title">PACKING SLIP</div>
                </div>

                <div class="order-info">
                    <div>
                        <label>Order Number</label>
                        <strong><?php echo esc_html($order->order_number); ?></strong>
                    </div>
                    <div>
                        <label>Order Date</label>
                        <strong><?php echo esc_html( date('M j, Y', strtotime($order->created_at)) ); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date -- intentional local-time display ?></strong>
                    </div>
                    <div>
                        <label>Shipping Method</label>
                        <strong><?php echo esc_html($order->shipping_method ?: 'Standard'); ?></strong>
                    </div>
                </div>

                <div class="addresses">
                    <div class="address-block">
                        <h3>Ship From</h3>
                        <p><?php echo esc_html($company['name']); ?></p>
                        <?php if ($company['address']): ?><p><?php echo esc_html($company['address']); ?></p><?php endif; ?>
                        <p><?php echo esc_html($company['city'] . ', ' . $company['state'] . ' ' . $company['zip']); ?></p>
                    </div>
                    <div class="address-block">
                        <h3>Ship To</h3>
                        <p><strong><?php echo esc_html(($shipping['first_name'] ?? '') . ' ' . ($shipping['last_name'] ?? '')); ?></strong></p>
                        <?php if (!empty($shipping['company'])): ?><p><?php echo esc_html($shipping['company']); ?></p><?php endif; ?>
                        <p><?php echo esc_html($shipping['address_1'] ?? ''); ?></p>
                        <?php if (!empty($shipping['address_2'])): ?><p><?php echo esc_html($shipping['address_2']); ?></p><?php endif; ?>
                        <p><?php echo esc_html(($shipping['city'] ?? '') . ', ' . ($shipping['state'] ?? '') . ' ' . ($shipping['postcode'] ?? '')); ?></p>
                        <p><?php echo esc_html($shipping['country'] ?? ''); ?></p>
                        <?php if (!empty($shipping['phone'])): ?><p>Phone: <?php echo esc_html($shipping['phone']); ?></p><?php endif; ?>
                    </div>
                </div>

                <table>
                    <thead>
                        <tr>
                            <th style="width: 40px;">Packed</th>
                            <th>Item</th>
                            <th>SKU</th>
                            <th class="text-center" style="width: 80px;">Qty</th>
                        </tr>
                    </thead>
                    <tbody>
                        <?php foreach ($items as $item): ?>
                        <tr>
                            <td class="text-center"><span class="checkbox"></span></td>
                            <td><?php echo esc_html($item->name); ?></td>
                            <td><?php echo esc_html($item->sku ?: '-'); ?></td>
                            <td class="text-center"><strong><?php echo esc_html($item->quantity); ?></strong></td>
                        </tr>
                        <?php endforeach; ?>
                    </tbody>
                </table>

                <?php if ($order->customer_note): ?>
                <div class="notes">
                    <strong>Customer Notes:</strong><br>
                    <?php echo esc_html($order->customer_note); ?>
                </div>
                <?php endif; ?>

                <div class="footer">
                    <p>Packed by: _________________ Date: _________________</p>
                    <p class="no-print" style="margin-top: 20px;">
                        <button onclick="window.print()" style="padding: 10px 20px; cursor: pointer;">Print Packing Slip</button>
                    </p>
                </div>
            </div>
        </body>
        </html>
        <?php
        return ob_get_clean();
    }

    /**
     * Generate bulk invoices
     */
    public static function generateBulkInvoices(array $orderIds): string
    {
        $html = '<!DOCTYPE html><html><head><style>
            .page-break { page-break-after: always; }
        </style></head><body>';

        foreach ($orderIds as $i => $orderId) {
            $invoice = self::generateInvoice($orderId);
            if ($invoice) {
                // Extract just the invoice div content
                preg_match('/<div class="invoice">.*?<\/div>\s*<\/body>/s', $invoice, $matches);
                if ($matches) {
                    $html .= '<div class="invoice">' . $matches[0];
                    if ($i < count($orderIds) - 1) {
                        $html .= '<div class="page-break"></div>';
                    }
                }
            }
        }

        $html .= '</body></html>';
        return $html;
    }

    // ─────────────────────────────────────────────────────────────────────────
    // Owner-created invoices with an own-branded public pay page (Home Services).
    // An invoice is recorded as an order carrying a random `invoice_token`; the
    // client pays at /invoice/{token} via the Stripe Payment Element (the same
    // primitive as the booking deposit). Line items live in the order meta so
    // this needs no order_items rows.
    // ─────────────────────────────────────────────────────────────────────────

    /**
     * Create an invoice. $data: client_name, client_email, client_phone, note,
     * items[] (each ['desc' => string, 'amount' => float]). Returns
     * ['success','order_id','token','pay_url','total'] or ['success'=>false,'error'].
     */
    public static function createInvoice(array $data): array
    {
        $p = DB::prefix();

        $items = [];
        $total = 0.0;
        foreach ((array) ($data['items'] ?? []) as $row) {
            $desc   = trim((string) ($row['desc'] ?? ''));
            $amount = round((float) ($row['amount'] ?? 0), 2);
            if ($desc === '' && $amount <= 0) continue;
            $items[] = ['desc' => $desc, 'amount' => $amount];
            $total  += $amount;
        }
        $total = round($total, 2);
        if (!$items || $total <= 0) {
            return ['success' => false, 'error' => 'Add at least one line item with an amount.'];
        }

        $name  = sanitize_text_field((string) ($data['client_name']  ?? ''));
        $email = sanitize_email((string) ($data['client_email'] ?? ''));
        $phone = sanitize_text_field((string) ($data['client_phone'] ?? ''));
        $note  = sanitize_textarea_field((string) ($data['note'] ?? ''));

        // Email is unique per owner (0058); both callers carry the right ambient
        // scope (the admin panel is the vendor, estimate approval runs inside
        // Tenant::withOwner of the estimate's owner).
        $customerId = 0;
        if ($email !== '') {
            $existing = DB::get_row(DB::prepare(
                "SELECT id FROM {$p}instinctor_customers WHERE email = %s AND " . Tenant::scopeSql('owner_id'),
                $email
            ));
            if ($existing) {
                $customerId = (int) $existing->id;
                if ($phone) DB::update($p . 'instinctor_customers', ['phone' => $phone], ['id' => $customerId]);
            } else {
                $parts = explode(' ', $name, 2);
                DB::insert($p . 'instinctor_customers', [
                    'email'      => $email,
                    'first_name' => $parts[0] ?? '',
                    'last_name'  => $parts[1] ?? '',
                    'phone'      => $phone,
                    'owner_id'   => Tenant::currentOwnerId(),
                    'created_at' => current_time('mysql'),
                ]);
                $customerId = (int) DB::insert_id();
            }
        }

        $token = bin2hex(random_bytes(20));
        DB::insert($p . 'instinctor_orders', [
            'order_number'    => 'PENDING',
            'customer_id'     => $customerId,
            'status'          => 'pending',
            'currency'        => Config::get('instinctor_currency', 'USD'),
            'subtotal'        => $total,
            'tax_total'       => 0,
            'shipping_total'  => 0,
            
            'discount_total'  => 0,
            'total'           => $total,
            'payment_method'  => 'stripe',
            'payment_status'  => 'unpaid',
            'invoice_token'   => $token,
            'customer_note'   => $note,
            'meta'            => wp_json_encode([
                'type'         => 'invoice',
                'items'        => $items,
                'client_name'  => $name,
                'client_phone' => $phone,
            ]),
            'created_at'      => current_time('mysql'),
        ]);
        $orderId = (int) DB::insert_id();
        if ($orderId <= 0) return ['success' => false, 'error' => 'Could not create the invoice.'];

        DB::update($p . 'instinctor_orders', ['order_number' => 'INV-' . str_pad((string) $orderId, 5, '0', STR_PAD_LEFT)], ['id' => $orderId]);

        return [
            'success'  => true,
            'order_id' => $orderId,
            'token'    => $token,
            'total'    => $total,
            'pay_url'  => self::payUrl($token),
        ];
    }

    /** Public pay-page URL for an invoice token. */
    public static function payUrl(string $token): string
    {
        return function_exists('home_url') ? home_url('/invoice/' . $token) : '/invoice/' . $token;
    }

    /** Fetch an invoice order by its public token (with decoded meta). Null if not found / not an invoice. */
    public static function getByToken(string $token): ?object
    {
        $token = trim($token);
        if ($token === '' || !ctype_xdigit($token)) return null;
        $p = DB::prefix();
        $order = DB::get_row(DB::prepare("SELECT * FROM {$p}instinctor_orders WHERE invoice_token = %s LIMIT 1", $token));
        if (!$order) return null;
        $meta = json_decode($order->meta ?? '{}', true) ?: [];
        if (($meta['type'] ?? '') !== 'invoice') return null;
        $order->invoice_meta = $meta;
        return $order;
    }

    /**
     * Create a Stripe PaymentIntent for the invoice total. Returns
     * ['success','client_secret','payment_intent_id','pk'] or ['success'=>false,'error'].
     */
    public static function createPayIntent(object $order): array
    {
        $secret = (string) Config::get('instinctor_stripe_secret_key', '');
        $pk     = (string) Config::get('instinctor_stripe_publishable_key', '');
        if ($secret === '' || $pk === '') return ['success' => false, 'error' => 'Payments are not set up.'];

        $resp = wp_remote_post('https://api.stripe.com/v1/payment_intents', [
            'headers' => [
                'Authorization' => 'Bearer ' . $secret,
                'Content-Type'  => 'application/x-www-form-urlencoded',
            ],
            'body' => [
                'amount'                    => (int) round((float) $order->total * 100),
                'currency'                  => strtolower((string) ($order->currency ?: 'USD')),
                'automatic_payment_methods' => ['enabled' => 'true'],
                'metadata'                  => ['type' => 'invoice', 'order_id' => (int) $order->id],
            ],
        ]);
        if (is_wp_error($resp)) return ['success' => false, 'error' => $resp->get_error_message()];
        $body = json_decode(wp_remote_retrieve_body($resp), true);
        if (!empty($body['error'])) return ['success' => false, 'error' => $body['error']['message']];

        return [
            'success'           => true,
            'client_secret'     => $body['client_secret'] ?? '',
            'payment_intent_id' => $body['id'] ?? '',
            'pk'                => $pk,
        ];
    }

    /**
     * Mark an invoice paid after verifying the PaymentIntent succeeded for the
     * full amount. Idempotent: a second call on a paid invoice is a no-op.
     */
    public static function markPaidByToken(string $token, string $paymentIntentId): array
    {
        $order = self::getByToken($token);
        if (!$order) return ['success' => false, 'error' => 'Invoice not found.'];
        if (($order->payment_status ?? '') === 'paid') return ['success' => true, 'already' => true];

        $secret = (string) Config::get('instinctor_stripe_secret_key', '');
        if ($secret === '' || trim($paymentIntentId) === '') return ['success' => false, 'error' => 'Payment could not be verified.'];

        $resp = wp_remote_get('https://api.stripe.com/v1/payment_intents/' . rawurlencode($paymentIntentId), [
            'headers' => ['Authorization' => 'Bearer ' . $secret],
        ]);
        if (is_wp_error($resp)) return ['success' => false, 'error' => 'Payment could not be verified.'];
        $body = json_decode(wp_remote_retrieve_body($resp), true);
        if (($body['status'] ?? '') !== 'succeeded') return ['success' => false, 'error' => 'Payment not completed.'];
        if ((int) ($body['amount_received'] ?? $body['amount'] ?? 0) !== (int) round((float) $order->total * 100)) {
            return ['success' => false, 'error' => 'Payment amount mismatch.'];
        }

        $p = DB::prefix();
        DB::update($p . 'instinctor_orders', [
            'payment_status'    => 'paid',
            'status'            => 'completed',
            'payment_intent_id' => $paymentIntentId,
            'transaction_id'    => $paymentIntentId,
        ], ['id' => (int) $order->id]);

        return ['success' => true];
    }

    /**
     * Email + SMS the client their pay link. Both channels are non-fatal.
     */
    public static function sendInvoice(int $orderId): bool
    {
        $p = DB::prefix();
        $order = DB::get_row(DB::prepare("SELECT * FROM {$p}instinctor_orders WHERE id = %d", $orderId));
        if (!$order || empty($order->invoice_token)) return false;
        $meta  = json_decode($order->meta ?? '{}', true) ?: [];
        $url   = self::payUrl((string) $order->invoice_token);
        $biz   = (string) (Config::get('instinctor_store_name', '') ?: 'your contractor');
        $total = number_format((float) $order->total, 2);

        $phone = (string) ($meta['client_phone'] ?? '');
        if ($phone !== '' && class_exists('\\Instinctor\\Core\\Sms')) {
            try { \Instinctor\Core\Sms::send($phone, "Invoice from {$biz}: \${$total}. Pay securely: {$url}"); } catch (\Throwable $e) {}
        }

        $email = '';
        if ((int) $order->customer_id > 0) {
            $email = (string) DB::get_var(DB::prepare("SELECT email FROM {$p}instinctor_customers WHERE id = %d", (int) $order->customer_id));
        }
        if ($email !== '' && function_exists('wp_mail')) {
            $subject = "Invoice {$order->order_number} from {$biz}";
            $bodyTxt = "Your invoice from {$biz} is \${$total}.\n\nPay securely here:\n{$url}\n\nThank you.";
            try { wp_mail($email, $subject, $bodyTxt); } catch (\Throwable $e) {}
        }

        return true;
    }
}
