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

class Manfiet_Invoice_Manager {
    public const POST_TYPE = 'manfiet_invoice';
    private const REST_NAMESPACE = 'manfi-expense-tracker/v1';

    public function __construct() {
        add_action('init', [$this, 'register_post_type']);
        add_action('rest_api_init', [$this, 'register_routes']);
        add_action('wp_enqueue_scripts', [$this, 'enqueue_invoice_styles'], 99999);
        add_filter('template_include', [$this, 'template_include']);
        add_filter('pre_get_document_title', [$this, 'custom_invoice_document_title'], 999);
    }

    public function enqueue_invoice_styles() {
        if (!is_singular(self::POST_TYPE)) {
            return;
        }

        // Dequeue other styles to prevent theme/plugin resets (like hello-elementor reset.css) from overriding our print layout.
        global $wp_styles;
        if (!empty($wp_styles->queue)) {
            foreach ($wp_styles->queue as $handle) {
                if ($handle !== 'manfiet-invoice-style' && $handle !== 'manfiet-google-fonts') {
                    wp_dequeue_style($handle);
                }
            }
        }

        $css_path = MANFIET_EXPENSE_TRACKER_PLUGIN_DIR . 'assets/css/invoice.css';
        $version = file_exists($css_path) ? filemtime($css_path) : MANFIET_EXPENSE_TRACKER_VERSION;

        wp_enqueue_style(
            'manfiet-invoice-style',
            MANFIET_EXPENSE_TRACKER_PLUGIN_URL . 'assets/css/invoice.css',
            [],
            $version
        );
    }

    public function custom_invoice_document_title($title) {
        if (is_singular(self::POST_TYPE)) {
            $post_id = get_the_ID();
            $invoice_no = (string) get_post_meta($post_id, '_manfiet_invoice_no', true);
            $client_id = (int) get_post_meta($post_id, '_manfiet_invoice_client_id', true);
            $client_name = '';

            if ($client_id > 0) {
                $client_post = get_post($client_id);
                if ($client_post && $client_post->post_type === 'manfiet_client') {
                    $client_name = (string) get_post_meta($client_id, '_manfiet_client_name', true);
                    if ($client_name === '') {
                        $client_name = get_the_title($client_post);
                    }
                }
            }

            if ($client_id <= 0 && $client_name === '') {
                $client_name = (string) get_post_meta($post_id, '_manfiet_invoice_client_name', true);
            }

            $client_slug = !empty($client_name) ? '-' . sanitize_title($client_name) : '';
            return $invoice_no ? $invoice_no . $client_slug : get_the_title();
        }
        return $title;
    }

    public static function install() {
        self::register_post_type_static();
        flush_rewrite_rules();
    }

    public function register_post_type() {
        self::register_post_type_static();
    }

    public static function register_post_type_static() {
        register_post_type(self::POST_TYPE, [
            'labels' => [
                'name' => __('Invoices', 'manfi-expense-tracker'),
                'singular_name' => __('Invoice', 'manfi-expense-tracker'),
            ],
            'public' => true,
            'show_ui' => true,
            'show_in_menu' => false,
            'show_in_rest' => false,
            'supports' => ['title', 'author'],
            'has_archive' => false,
            'rewrite' => [
                'slug' => 'invoice',
                'with_front' => false,
            ],
            'menu_icon' => 'dashicons-media-text',
        ]);
    }

    private function can_manage_invoices() {
        return current_user_can('manage_expenses') || current_user_can('manage_options');
    }

    public function require_manage_permission() {
        if (!$this->can_manage_invoices()) {
            return new WP_Error(
                'manfiet_invoice_forbidden',
                __('You do not have permission to manage invoices.', 'manfi-expense-tracker'),
                ['status' => 403]
            );
        }

        return true;
    }

    public function require_manage_permission_or_token(WP_REST_Request $request) {
        if ($this->can_manage_invoices()) {
            return true;
        }

        $invoice_id = absint($request['id']);
        $token = sanitize_text_field($request->get_param('token'));
        $saved_token = get_post_meta($invoice_id, '_manfiet_invoice_share_token', true);

        if (!empty($token) && !empty($saved_token) && hash_equals($saved_token, $token)) {
            return true;
        }

        return new WP_Error(
            'manfiet_invoice_forbidden',
            __('You do not have permission to view or download this PDF.', 'manfi-expense-tracker'),
            ['status' => 403]
        );
    }

    private function get_share_token($invoice_id) {
        $token = (string) get_post_meta($invoice_id, '_manfiet_invoice_share_token', true);
        if ($token === '') {
            $token = wp_generate_password(24, false, false);
            update_post_meta($invoice_id, '_manfiet_invoice_share_token', $token);
        }

        return $token;
    }

    private function normalize_campaigns($raw_campaigns) {
        if (!is_array($raw_campaigns)) {
            return [];
        }

        $campaigns = [];
        foreach ($raw_campaigns as $campaign) {
            if (!is_array($campaign)) {
                continue;
            }

            $name = sanitize_text_field((string) ($campaign['name'] ?? ''));
            $daily_budget = (float) ($campaign['daily_budget'] ?? $campaign['rate'] ?? $campaign['unit_price'] ?? 0);
            $raw_duration = $campaign['duration'] ?? $campaign['days'] ?? $campaign['qty'] ?? $campaign['quantity'] ?? $campaign['hours'] ?? null;
            $duration = ($raw_duration === '' || $raw_duration === null || (float)$raw_duration <= 0) ? 1.0 : (float) $raw_duration;
            $description = sanitize_text_field((string) ($campaign['description'] ?? ''));
            $calculated_amount = $daily_budget * $duration;
            $amount = (isset($campaign['amount']) && (float) $campaign['amount'] > 0) ? (float) $campaign['amount'] : $calculated_amount;

            if ($name === '' && $amount <= 0) {
                continue;
            }

            $campaigns[] = [
                'name' => $name,
                'daily_budget' => $daily_budget,
                'duration' => $duration,
                'description' => $description,
                'amount' => round($amount, 2),
            ];
        }

        return array_values($campaigns);
    }

    private function calculate_totals(array $campaigns, $exchange_rate, $discount_val, $vat_pct, $adjustment_bdt = 0, $invoice_type = 'standard', $discount_type = 'percentage') {
        $subtotal_usd = 0;
        foreach ($campaigns as $campaign) {
            $subtotal_usd += (float) ($campaign['amount'] ?? 0);
        }

        $exchange_rate = (float) $exchange_rate;
        if ($invoice_type !== 'daily_rate') {
            $effective_exchange_rate = 1.0;
        } else {
            $effective_exchange_rate = $exchange_rate > 0 ? $exchange_rate : 1.0;
        }

        $discount_val = max(0, (float) $discount_val);
        $discount_type = in_array($discount_type, ['flat', 'fixed', 'percentage'], true) ? $discount_type : 'percentage';

        $subtotal_bdt = $subtotal_usd * $effective_exchange_rate;

        if ($discount_type === 'flat' || $discount_type === 'fixed') {
            $discount_bdt = round(min($subtotal_bdt, $discount_val), 2);
            $discount_pct = $subtotal_bdt > 0 ? round(($discount_bdt / $subtotal_bdt) * 100, 2) : 0.0;
        } else {
            $discount_pct = $discount_val;
            $discount_bdt = round($subtotal_bdt * ($discount_pct / 100), 2);
        }

        $after_discount = round(max(0, $subtotal_bdt - $discount_bdt), 2);
        $vat_pct = max(0, (float) $vat_pct);
        $adjustment_bdt = (float) $adjustment_bdt;

        $vat_bdt = round($after_discount * ($vat_pct / 100), 2);
        $grand_total = round($after_discount + $vat_bdt + $adjustment_bdt, 2);

        return [
            'subtotal_usd' => round($subtotal_usd, 2),
            'subtotal' => round($subtotal_usd, 2), // alias for legacy/PDF usage
            'subtotal_bdt' => round($subtotal_bdt, 2),
            'discount_type' => $discount_type,
            'discount_val' => $discount_val,
            'discount_pct' => $discount_pct,
            'discount_bdt' => $discount_bdt,
            'discount' => $discount_bdt, // alias for legacy/PDF usage
            'after_discount' => $after_discount,
            'vat_bdt' => $vat_bdt,
            'vat' => $vat_bdt, // alias for legacy/PDF usage
            'adjustment_bdt' => $adjustment_bdt,
            'grand_total' => $grand_total,
        ];
    }
    
    private function normalize_invoice_status($status) {
        $status = sanitize_key((string) $status);
        $allowed_statuses = ['pending', 'partial', 'paid', 'overdue', 'draft'];

        return in_array($status, $allowed_statuses, true) ? $status : 'pending';
    }

    private function calculate_payment_summary($grand_total, $previous_due_amount, $payment_received_amount) {
        $previous_due_amount = max(0, (float) $previous_due_amount);
        $payment_received_amount = max(0, (float) $payment_received_amount);
        $amount_due = round((float) $grand_total + $previous_due_amount, 2);
        $balance_due = round(max(0, $amount_due - $payment_received_amount), 2);
        $overpaid_amount = round(max(0, $payment_received_amount - $amount_due), 2);

        return [
            'previous_due_amount' => round($previous_due_amount, 2),
            'payment_received_amount' => round($payment_received_amount, 2),
            'amount_due' => $amount_due,
            'balance_due' => $balance_due,
            'overpaid_amount' => $overpaid_amount,
        ];
    }

    private function derive_invoice_status($requested_status, $amount_due, $payment_received_amount) {
        $requested_status = $this->normalize_invoice_status($requested_status);
        if ($requested_status === 'draft') {
            return $requested_status;
        }

        $amount_due = max(0, (float) $amount_due);
        $payment_received_amount = max(0, (float) $payment_received_amount);

        if ($requested_status === 'overdue' && $payment_received_amount <= 0) {
            return $requested_status;
        }

        if ($payment_received_amount <= 0) {
            return 'pending';
        }

        if ($payment_received_amount >= $amount_due) {
            return 'paid';
        }

        return 'partial';
    }

    public function get_invoice_payments($invoice_id) {
        $raw = get_post_meta($invoice_id, '_manfiet_invoice_payments', true);
        $payments = json_decode((string) $raw, true);
        if (!is_array($payments)) {
            $payments = [];
        }
        $received_amount = (float) get_post_meta($invoice_id, '_manfiet_invoice_payment_received_amount', true);
        if (empty($payments) && $received_amount > 0) {
            $invoice_date = (string) get_post_meta($invoice_id, '_manfiet_invoice_date', true);
            $payments = [
                [
                    'id' => 'pay_legacy_1',
                    'date' => ($invoice_date ?: current_time('Y-m-d')) . ' 12:00',
                    'amount' => round($received_amount, 2),
                    'method' => '',
                    'transaction_id' => '',
                    'note' => __('Initial recorded payment', 'manfi-expense-tracker'),
                ]
            ];
        }
        return $payments;
    }

    public function get_invoice_payload($invoice_id) {
        $invoice_id = absint($invoice_id);
        $post = get_post($invoice_id);
        if (!$post || $post->post_type !== self::POST_TYPE) {
            return null;
        }

        $campaigns = json_decode((string) get_post_meta($invoice_id, '_manfiet_invoice_campaigns', true), true) ?: [];
        $exchange_rate = (float) get_post_meta($invoice_id, '_manfiet_invoice_exchange_rate', true);
        $discount_type = (string) (get_post_meta($invoice_id, '_manfiet_invoice_discount_type', true) ?: 'percentage');
        $discount_val = (float) get_post_meta($invoice_id, '_manfiet_invoice_discount_val', true);
        if (!metadata_exists('post', $invoice_id, '_manfiet_invoice_discount_val')) {
            $discount_val = (float) get_post_meta($invoice_id, '_manfiet_invoice_discount_pct', true);
        }
        $discount_pct = (float) get_post_meta($invoice_id, '_manfiet_invoice_discount_pct', true);
        $vat_pct = (float) get_post_meta($invoice_id, '_manfiet_invoice_vat_pct', true);
        $adjustment_usd = (float) get_post_meta($invoice_id, '_manfiet_invoice_adjustment_usd', true);
        $adjustment_bdt = (float) get_post_meta($invoice_id, '_manfiet_invoice_adjustment_bdt', true);
        $adjustment_note = (string) get_post_meta($invoice_id, '_manfiet_invoice_adjustment_note', true);

        $previous_invoice_id = absint(get_post_meta($invoice_id, '_manfiet_invoice_previous_invoice_id', true));
        $previous_invoice_no = (string) get_post_meta($invoice_id, '_manfiet_invoice_previous_invoice_no', true);
        if ($previous_invoice_no === '' && $previous_invoice_id) {
            $previous_invoice_no = (string) get_post_meta($previous_invoice_id, '_manfiet_invoice_no', true);
        }
        $invoice_type = (string) (get_post_meta($invoice_id, '_manfiet_invoice_type', true) ?: 'standard');
        $service_type_label = (string) get_post_meta($invoice_id, '_manfiet_service_type_label', true);
        $currency = (string) (get_post_meta($invoice_id, '_manfiet_invoice_currency', true) ?: 'BDT');

        $totals = $this->calculate_totals($campaigns, $exchange_rate, $discount_val, $vat_pct, $adjustment_bdt, $invoice_type, $discount_type);

        // Use stored previous_due_amount — authoritative (set by user either via dropdown or manual entry)
        $previous_due_amount = (float) get_post_meta($invoice_id, '_manfiet_invoice_previous_due_amount', true);

        // Compute payments: always sum from the payments array; fall back to stored amount if no items
        $payments = $this->get_invoice_payments($invoice_id);
        $calc_payment_received = 0.0;
        foreach ($payments as $p) {
            $calc_payment_received += (float) ($p['amount'] ?? 0);
        }
        // If no structured payment items, fall back to stored raw amount
        if (empty($payments)) {
            $calc_payment_received = (float) get_post_meta($invoice_id, '_manfiet_invoice_payment_received_amount', true);
        }
        $calc_payment_received = round($calc_payment_received, 2);

        $payment_summary = $this->calculate_payment_summary(
            $totals['grand_total'],
            $previous_due_amount,
            $calc_payment_received
        );
        $status = $this->derive_invoice_status(
            get_post_meta($invoice_id, '_manfiet_invoice_status', true),
            $payment_summary['amount_due'],
            $payment_summary['payment_received_amount']
        );

        return [
            'id' => $post->ID,
            'title' => get_the_title($post),
            'invoice_type' => $invoice_type,
            'service_type_label' => $service_type_label,
            'currency' => strtoupper($currency),
            'vendor_id' => (int) get_post_meta($invoice_id, '_manfiet_invoice_vendor_id', true),
            'client_id' => (int) get_post_meta($invoice_id, '_manfiet_invoice_client_id', true),
            'client_name' => (string) get_post_meta($invoice_id, '_manfiet_invoice_client_name', true),
            'invoice_no' => (string) get_post_meta($invoice_id, '_manfiet_invoice_no', true),
            'date' => (string) get_post_meta($invoice_id, '_manfiet_invoice_date', true),
            'due_date' => (string) get_post_meta($invoice_id, '_manfiet_invoice_due_date', true),
            'address' => (string) get_post_meta($invoice_id, '_manfiet_invoice_address', true),
            'phone' => (string) get_post_meta($invoice_id, '_manfiet_invoice_phone', true),
            'email' => (string) get_post_meta($invoice_id, '_manfiet_invoice_email', true),
            'email2' => (string) get_post_meta($invoice_id, '_manfiet_invoice_email2', true),
            'bkash' => (string) get_post_meta($invoice_id, '_manfiet_invoice_bkash', true),
            'financial_account_ids' => json_decode((string) get_post_meta($invoice_id, '_manfiet_invoice_financial_account_ids', true), true) ?: [],
            'bank' => [
                'name' => (string) get_post_meta($invoice_id, '_manfiet_invoice_bank_name', true),
                'account' => (string) get_post_meta($invoice_id, '_manfiet_invoice_bank_account', true),
                'title' => (string) get_post_meta($invoice_id, '_manfiet_invoice_bank_title', true),
                'branch' => (string) get_post_meta($invoice_id, '_manfiet_invoice_bank_branch', true),
                'routing' => (string) get_post_meta($invoice_id, '_manfiet_invoice_bank_routing', true),
                'type' => (string) get_post_meta($invoice_id, '_manfiet_invoice_bank_type', true),
            ],
            'service_desc' => (string) get_post_meta($invoice_id, '_manfiet_invoice_service_desc', true),
            'notes' => (string) get_post_meta($invoice_id, '_manfiet_invoice_notes', true),
            'late_fee_pct' => (float) (get_post_meta($invoice_id, '_manfiet_invoice_late_fee_pct', true) ?: get_option('manfiet_invoice_late_fee_pct', 5.0)),
            'exchange_rate' => $exchange_rate,
            'discount_type' => $discount_type,
            'discount_val' => $discount_val,
            'discount_pct' => $discount_pct,
            'vat_pct' => $vat_pct,
            'adjustment_usd' => $adjustment_usd,
            'adjustment_bdt' => $adjustment_bdt,
            'adjustment_note' => $adjustment_note,
            'status' => $status,
            'campaigns' => $campaigns,
            'totals' => $totals,
            'previous_invoice_id' => $previous_invoice_id,
            'previous_invoice_no' => $previous_invoice_no,
            'previous_due_amount' => $payment_summary['previous_due_amount'],
            'payment_received_amount' => $payment_summary['payment_received_amount'],
            'payments' => $payments,
            'amount_due' => $payment_summary['amount_due'],
            'balance_due' => $payment_summary['balance_due'],
            'overpaid_amount' => $payment_summary['overpaid_amount'],
            'share_url' => get_permalink($post),
            'share_token' => $this->get_share_token($invoice_id),
            'payment_link' => (string) get_post_meta($invoice_id, '_manfiet_invoice_payment_link', true),
            'created_at' => get_the_date('Y-m-d', $post),
        ];
    }

    private function generate_invoice_no($post_id) {
        $ym = gmdate('Ym');
        $opt_key = 'manfiet_invoice_counter_' . $ym;
        $counter = (int) get_option($opt_key, 0);
        $counter++;
        update_option($opt_key, $counter);

        return sprintf('INV-%s-%05d', $ym, $counter);
    }

    private function save_invoice_meta($invoice_id, array $payload) {
        if (isset($payload['payments']) && is_array($payload['payments'])) {
            $payments = [];
            $total_paid = 0.0;
            foreach ($payload['payments'] as $item) {
                $amt = round(max(0, (float) ($item['amount'] ?? 0)), 2);
                if ($amt <= 0) {
                    continue;
                }
                $p_id = sanitize_text_field((string) ($item['id'] ?? ('pay_' . uniqid())));
                $p_date = sanitize_text_field((string) ($item['date'] ?? current_time('Y-m-d H:i')));
                $p_method = sanitize_text_field((string) ($item['method'] ?? ''));
                $p_trx = sanitize_text_field((string) ($item['transaction_id'] ?? ''));
                $p_note = sanitize_textarea_field((string) ($item['note'] ?? ''));
                $payments[] = [
                    'id' => $p_id,
                    'date' => $p_date,
                    'amount' => $amt,
                    'method' => $p_method,
                    'transaction_id' => $p_trx,
                    'note' => $p_note,
                ];
                $total_paid += $amt;
            }
            update_post_meta($invoice_id, '_manfiet_invoice_payments', wp_json_encode($payments));
            // Only override the manually entered amount if there are actual payment records
            if (!empty($payments)) {
                $payload['payment_received_amount'] = round($total_paid, 2);
            }
        }

        $fields = [
            '_manfiet_invoice_type' => sanitize_key((string) ($payload['invoice_type'] ?? 'standard')),
            '_manfiet_service_type_label' => sanitize_text_field((string) ($payload['service_type_label'] ?? '')),
            '_manfiet_invoice_currency' => sanitize_text_field(strtoupper((string) ($payload['currency'] ?? 'BDT'))),
            '_manfiet_invoice_vendor_id' => (int) ($payload['vendor_id'] ?? 0),
            '_manfiet_invoice_client_id' => (int) ($payload['client_id'] ?? 0),
            '_manfiet_invoice_client_name' => sanitize_text_field((string) ($payload['client_name'] ?? '')),
            '_manfiet_invoice_no' => sanitize_text_field((string) ($payload['invoice_no'] ?? '')),
            '_manfiet_invoice_date' => sanitize_text_field((string) ($payload['date'] ?? '')),
            '_manfiet_invoice_due_date' => sanitize_text_field((string) ($payload['due_date'] ?? '')),
            '_manfiet_invoice_late_fee_pct' => (float) ($payload['late_fee_pct'] ?? 0),
            '_manfiet_invoice_address' => sanitize_textarea_field((string) ($payload['address'] ?? '')),
            '_manfiet_invoice_phone' => sanitize_text_field((string) ($payload['phone'] ?? '')),
            '_manfiet_invoice_email' => sanitize_email((string) ($payload['email'] ?? '')),
            '_manfiet_invoice_email2' => sanitize_email((string) ($payload['email2'] ?? '')),
            '_manfiet_invoice_bkash' => sanitize_text_field((string) ($payload['bkash'] ?? '')),
            '_manfiet_invoice_bank_name' => sanitize_text_field((string) ($payload['bank']['name'] ?? '')),
            '_manfiet_invoice_bank_account' => sanitize_text_field((string) ($payload['bank']['account'] ?? '')),
            '_manfiet_invoice_bank_title' => sanitize_text_field((string) ($payload['bank']['title'] ?? '')),
            '_manfiet_invoice_bank_branch' => sanitize_text_field((string) ($payload['bank']['branch'] ?? '')),
            '_manfiet_invoice_bank_routing' => sanitize_text_field((string) ($payload['bank']['routing'] ?? '')),
            '_manfiet_invoice_bank_type' => sanitize_text_field((string) ($payload['bank']['type'] ?? '')),
            '_manfiet_invoice_service_desc' => sanitize_text_field((string) ($payload['service_desc'] ?? '')),
            '_manfiet_invoice_exchange_rate' => (float) ($payload['exchange_rate'] ?? 0),
            '_manfiet_invoice_discount_type' => sanitize_key((string) ($payload['discount_type'] ?? 'percentage')),
            '_manfiet_invoice_discount_val' => (float) ($payload['discount_val'] ?? $payload['discount_pct'] ?? 0),
            '_manfiet_invoice_discount_pct' => (float) ($payload['discount_pct'] ?? 0),
            '_manfiet_invoice_vat_pct' => (float) ($payload['vat_pct'] ?? 0),
            '_manfiet_invoice_adjustment_usd' => (float) ($payload['adjustment_usd'] ?? 0) !== 0.0 ? (float) $payload['adjustment_usd'] : (((float) ($payload['adjustment_bdt'] ?? 0) !== 0.0 && (float) ($payload['exchange_rate'] ?? 0) > 0) ? round((float) $payload['adjustment_bdt'] / (float) $payload['exchange_rate'], 2) : 0.0),
            '_manfiet_invoice_adjustment_bdt' => (float) ($payload['adjustment_bdt'] ?? 0) !== 0.0 ? (float) $payload['adjustment_bdt'] : (((float) ($payload['adjustment_usd'] ?? 0) !== 0.0 && (float) ($payload['exchange_rate'] ?? 0) > 0) ? round((float) $payload['adjustment_usd'] * (float) $payload['exchange_rate'], 2) : 0.0),
            '_manfiet_invoice_adjustment_note' => sanitize_text_field((string) ($payload['adjustment_note'] ?? '')),
            '_manfiet_invoice_status' => $this->normalize_invoice_status($payload['status'] ?? 'pending'),
            '_manfiet_invoice_previous_invoice_id' => absint($payload['previous_invoice_id'] ?? 0),
            '_manfiet_invoice_previous_invoice_no' => sanitize_text_field((string) ($payload['previous_invoice_no'] ?? '')),
            '_manfiet_invoice_previous_due_amount' => max(0, (float) ($payload['previous_due_amount'] ?? 0)),
            '_manfiet_invoice_payment_received_amount' => max(0, (float) ($payload['payment_received_amount'] ?? 0)),
            '_manfiet_invoice_campaigns' => wp_json_encode($this->normalize_campaigns($payload['campaigns'] ?? [])),
            '_manfiet_invoice_financial_account_ids' => wp_json_encode(array_values(array_filter(array_map('absint', (array) ($payload['financial_account_ids'] ?? []))))),
            '_manfiet_invoice_notes' => sanitize_textarea_field((string) ($payload['notes'] ?? '')),
            '_manfiet_invoice_payment_link' => esc_url_raw((string) ($payload['payment_link'] ?? '')),
        ];

        foreach ($fields as $meta_key => $value) {
            update_post_meta($invoice_id, $meta_key, $value);
        }

        $token = sanitize_text_field((string) ($payload['share_token'] ?? ''));
        if ($token === '') {
            $token = wp_generate_password(24, false, false);
        }
        update_post_meta($invoice_id, '_manfiet_invoice_share_token', $token);

        $payload['share_token'] = $token;
    }

    public function register_routes() {
        register_rest_route(self::REST_NAMESPACE, '/invoices', [
            [
                'methods' => 'GET',
                'callback' => [$this, 'rest_list_invoices'],
                'permission_callback' => [$this, 'require_manage_permission'],
            ],
            [
                'methods' => 'POST',
                'callback' => [$this, 'rest_create_invoice'],
                'permission_callback' => [$this, 'require_manage_permission'],
            ],
        ]);

        register_rest_route(self::REST_NAMESPACE, '/invoices/(?P<id>\d+)', [
            [
                'methods' => 'GET',
                'callback' => [$this, 'rest_get_invoice'],
                'permission_callback' => [$this, 'require_manage_permission'],
            ],
            [
                'methods' => 'PUT,PATCH',
                'callback' => [$this, 'rest_update_invoice'],
                'permission_callback' => [$this, 'require_manage_permission'],
            ],
            [
                'methods' => 'DELETE',
                'callback' => [$this, 'rest_delete_invoice'],
                'permission_callback' => [$this, 'require_manage_permission'],
            ],
        ]);

        register_rest_route(self::REST_NAMESPACE, '/invoices/(?P<id>\d+)/payment', [
            [
                'methods' => 'POST',
                'callback' => [$this, 'rest_record_invoice_payment'],
                'permission_callback' => [$this, 'require_manage_permission'],
            ],
        ]);

        register_rest_route(self::REST_NAMESPACE, '/invoices/(?P<id>\d+)/payment/(?P<payment_id>[a-zA-Z0-9_\-]+)', [
            [
                'methods' => 'DELETE',
                'callback' => [$this, 'rest_delete_invoice_payment'],
                'permission_callback' => [$this, 'require_manage_permission'],
            ],
        ]);

        register_rest_route(self::REST_NAMESPACE, '/invoice-report', [
            'methods' => 'GET',
            'callback' => [$this, 'rest_invoice_report'],
            'permission_callback' => [$this, 'require_manage_permission'],
        ]);

        register_rest_route(self::REST_NAMESPACE, '/invoices/(?P<id>\d+)/pdf', [
            [
                'methods' => 'GET',
                'callback' => [$this, 'rest_download_invoice_pdf'],
                'permission_callback' => [$this, 'require_manage_permission_or_token'],
            ],
        ]);
    }

    public function rest_list_invoices() {
        $posts = get_posts([
            'post_type' => self::POST_TYPE,
            'post_status' => ['publish', 'draft', 'pending', 'private'],
            'numberposts' => -1,
            'orderby' => 'date',
            'order' => 'DESC',
        ]);

        $items = [];
        foreach ($posts as $post) {
            $payload = $this->get_invoice_payload($post->ID);
            if ($payload) {
                $items[] = $payload;
            }
        }

        return rest_ensure_response($items);
    }

    public function rest_get_invoice(WP_REST_Request $request) {
        $invoice_id = absint($request['id']);
        $payload = $this->get_invoice_payload($invoice_id);
        if (!$payload) {
            return new WP_Error('manfiet_invoice_not_found', __('Invoice not found.', 'manfi-expense-tracker'), ['status' => 404]);
        }

        return rest_ensure_response($payload);
    }

    public function rest_create_invoice(WP_REST_Request $request) {
        $data = $request->get_json_params();
        $campaigns = $this->normalize_campaigns($data['campaigns'] ?? []);
        if (empty($campaigns)) {
            return new WP_Error('manfiet_invoice_campaigns_required', __('Add at least one campaign.', 'manfi-expense-tracker'), ['status' => 400]);
        }


        $client_name = sanitize_text_field((string) ($data['client_name'] ?? ''));
        $invoice_no = sanitize_text_field((string) ($data['invoice_no'] ?? ''));
        if ($client_name === '') {
            return new WP_Error('manfiet_invoice_required', __('Client name is required.', 'manfi-expense-tracker'), ['status' => 400]);
        }

        // Insert post first, we'll set title once invoice number is available.
        $post_title = $client_name;
        if ($invoice_no !== '') {
            $post_title = $invoice_no . ' - ' . $client_name;
        }

        $post_id = wp_insert_post([
            'post_type' => self::POST_TYPE,
            'post_status' => 'publish',
            'post_title' => $post_title,
            'post_content' => '',
            'post_author' => get_current_user_id(),
        ], true);

        if (is_wp_error($post_id)) {
            return $post_id;
        }

        // ensure invoice number exists (generate if not provided)
        if ($invoice_no === '') {
            $invoice_no = $this->generate_invoice_no($post_id);
            // update post title to include generated invoice number
            wp_update_post([
                'ID' => $post_id,
                'post_title' => $invoice_no . ' - ' . $client_name,
            ]);
        }

        $discount_type = sanitize_key((string) ($data['discount_type'] ?? 'percentage'));
        $discount_val = (float) ($data['discount_val'] ?? $data['discount_pct'] ?? 0);

        $payment_summary = $this->calculate_payment_summary(
            $this->calculate_totals($campaigns, $data['exchange_rate'] ?? 150, $discount_val, $data['vat_pct'] ?? 0, $data['adjustment_bdt'] ?? 0, $data['invoice_type'] ?? 'standard', $discount_type)['grand_total'],
            $data['previous_due_amount'] ?? 0,
            $data['payment_received_amount'] ?? 0
        );

        $payload = [
            'invoice_type' => sanitize_key((string) ($data['invoice_type'] ?? 'standard')),
            'service_type_label' => sanitize_text_field((string) ($data['service_type_label'] ?? '')),
            'currency' => sanitize_text_field(strtoupper((string) ($data['currency'] ?? 'BDT'))),
            'vendor_id' => (int) ($data['vendor_id'] ?? 0),
            'client_id' => (int) ($data['client_id'] ?? 0),
            'client_name' => $client_name,
            'invoice_no' => $invoice_no,
            'date' => $data['date'] ?? '',
            'due_date' => $data['due_date'] ?? '',
            'late_fee_pct' => (float) ($data['late_fee_pct'] ?? 0),
            'address' => $data['address'] ?? '',
            'phone' => $data['phone'] ?? '',
            'email' => $data['email'] ?? '',
            'email2' => $data['email2'] ?? '',
            'bkash' => $data['bkash'] ?? '',
            'financial_account_ids' => $data['financial_account_ids'] ?? [],
            'bank' => $data['bank'] ?? [],
            'service_desc' => $data['service_desc'] ?? '',
            'exchange_rate' => $data['exchange_rate'] ?? 150,
            'discount_type' => $discount_type,
            'discount_val' => $discount_val,
            'discount_pct' => $data['discount_pct'] ?? 0,
            'vat_pct' => $data['vat_pct'] ?? 0,
            'adjustment_usd' => $data['adjustment_usd'] ?? 0,
            'adjustment_bdt' => $data['adjustment_bdt'] ?? 0,
            'adjustment_note' => $data['adjustment_note'] ?? '',
            'status' => $this->derive_invoice_status($data['status'] ?? 'pending', $payment_summary['amount_due'], $payment_summary['payment_received_amount']),
            'campaigns' => $campaigns,
            'previous_invoice_id' => (int) ($data['previous_invoice_id'] ?? 0),
            'previous_invoice_no' => sanitize_text_field((string) ($data['previous_invoice_no'] ?? '')),
            'previous_due_amount' => $data['previous_due_amount'] ?? 0,
            'payment_received_amount' => $data['payment_received_amount'] ?? 0,
            'payments' => $data['payments'] ?? [],
            'notes' => sanitize_textarea_field((string) ($data['notes'] ?? '')),
            'payment_link' => esc_url_raw((string) ($data['payment_link'] ?? '')),
            'share_token' => wp_generate_password(24, false, false),
        ];
        $this->save_invoice_meta($post_id, $payload);

        return rest_ensure_response($this->get_invoice_payload($post_id));
    }

    public function rest_update_invoice(WP_REST_Request $request) {
        $invoice_id = absint($request['id']);
        if (!$this->get_invoice_payload($invoice_id)) {
            return new WP_Error('manfiet_invoice_not_found', __('Invoice not found.', 'manfi-expense-tracker'), ['status' => 404]);
        }

        $data = $request->get_json_params();
        $campaigns = $this->normalize_campaigns($data['campaigns'] ?? []);
        if (empty($campaigns)) {
            return new WP_Error('manfiet_invoice_campaigns_required', __('Add at least one campaign.', 'manfi-expense-tracker'), ['status' => 400]);
        }

        $client_name = sanitize_text_field((string) ($data['client_name'] ?? ''));
        $invoice_no = sanitize_text_field((string) ($data['invoice_no'] ?? ''));
        $existing_no = (string) get_post_meta($invoice_id, '_manfiet_invoice_no', true);
        if ($client_name === '') {
            return new WP_Error('manfiet_invoice_required', __('Client name is required.', 'manfi-expense-tracker'), ['status' => 400]);
        }

        // If invoice_no not provided in update, keep existing one. If there is no existing
        // invoice number and none provided, require it.
        if ($invoice_no === '') {
            if ($existing_no === '') {
                return new WP_Error('manfiet_invoice_required', __('Invoice number is required.', 'manfi-expense-tracker'), ['status' => 400]);
            }
            $invoice_no = $existing_no;
        }

        wp_update_post([
            'ID' => $invoice_id,
            'post_title' => $invoice_no . ' - ' . $client_name,
        ]);

        $discount_type = sanitize_key((string) ($data['discount_type'] ?? 'percentage'));
        $discount_val = (float) ($data['discount_val'] ?? $data['discount_pct'] ?? 0);

        $payment_summary = $this->calculate_payment_summary(
            $this->calculate_totals($campaigns, $data['exchange_rate'] ?? 150, $discount_val, $data['vat_pct'] ?? 0, $data['adjustment_bdt'] ?? 0, $data['invoice_type'] ?? 'standard', $discount_type)['grand_total'],
            $data['previous_due_amount'] ?? 0,
            $data['payment_received_amount'] ?? 0
        );

        $payload = [
            'invoice_type' => sanitize_key((string) ($data['invoice_type'] ?? 'standard')),
            'service_type_label' => sanitize_text_field((string) ($data['service_type_label'] ?? '')),
            'currency' => sanitize_text_field(strtoupper((string) ($data['currency'] ?? 'BDT'))),
            'vendor_id' => (int) ($data['vendor_id'] ?? 0),
            'client_id' => (int) ($data['client_id'] ?? 0),
            'client_name' => $client_name,
            'invoice_no' => $invoice_no,
            'date' => $data['date'] ?? '',
            'due_date' => $data['due_date'] ?? '',
            'late_fee_pct' => (float) ($data['late_fee_pct'] ?? 0),
            'address' => $data['address'] ?? '',
            'phone' => $data['phone'] ?? '',
            'email' => $data['email'] ?? '',
            'email2' => $data['email2'] ?? '',
            'bkash' => $data['bkash'] ?? '',
            'financial_account_ids' => $data['financial_account_ids'] ?? [],
            'bank' => $data['bank'] ?? [],
            'service_desc' => $data['service_desc'] ?? '',
            'exchange_rate' => $data['exchange_rate'] ?? 150,
            'discount_type' => $discount_type,
            'discount_val' => $discount_val,
            'discount_pct' => $data['discount_pct'] ?? 0,
            'vat_pct' => $data['vat_pct'] ?? 0,
            'adjustment_usd' => $data['adjustment_usd'] ?? 0,
            'adjustment_bdt' => $data['adjustment_bdt'] ?? 0,
            'adjustment_note' => $data['adjustment_note'] ?? '',
            'status' => $this->derive_invoice_status($data['status'] ?? 'pending', $payment_summary['amount_due'], $payment_summary['payment_received_amount']),
            'campaigns' => $campaigns,
            'previous_invoice_id' => (int) ($data['previous_invoice_id'] ?? 0),
            'previous_invoice_no' => sanitize_text_field((string) ($data['previous_invoice_no'] ?? '')),
            'previous_due_amount' => $data['previous_due_amount'] ?? 0,
            'payment_received_amount' => $data['payment_received_amount'] ?? 0,
            'payments' => isset($data['payments']) && is_array($data['payments']) ? $data['payments'] : $this->get_invoice_payments($invoice_id),
            'notes' => sanitize_textarea_field((string) ($data['notes'] ?? '')),
            'payment_link' => esc_url_raw((string) ($data['payment_link'] ?? '')),
            'share_token' => get_post_meta($invoice_id, '_manfiet_invoice_share_token', true),
        ];
        $this->save_invoice_meta($invoice_id, $payload);

        return rest_ensure_response($this->get_invoice_payload($invoice_id));
    }

    public function rest_record_invoice_payment(WP_REST_Request $request) {
        $invoice_id = absint($request['id']);
        $existing = $this->get_invoice_payload($invoice_id);
        if (!$existing) {
            return new WP_Error('manfiet_invoice_not_found', __('Invoice not found.', 'manfi-expense-tracker'), ['status' => 404]);
        }

        $data = $request->get_json_params() ?: [];
        $payment_amount = max(0, (float) ($data['payment_amount'] ?? 0));
        if ($payment_amount <= 0) {
            return new WP_Error('manfiet_invoice_payment_required', __('Enter a payment amount greater than zero.', 'manfi-expense-tracker'), ['status' => 400]);
        }

        $payment_date = sanitize_text_field((string) ($data['payment_date'] ?? ''));
        if (empty($payment_date)) {
            $payment_date = current_time('Y-m-d H:i');
        } else {
            $payment_date = str_replace('T', ' ', $payment_date);
        }
        $payment_method = sanitize_text_field((string) ($data['payment_method'] ?? ''));
        $transaction_id = sanitize_text_field((string) ($data['transaction_id'] ?? ''));
        $note = sanitize_textarea_field((string) ($data['note'] ?? ''));

        $payments = $existing['payments'] ?? [];
        $payments[] = [
            'id' => 'pay_' . uniqid() . '_' . time(),
            'date' => $payment_date,
            'amount' => round($payment_amount, 2),
            'method' => $payment_method,
            'transaction_id' => $transaction_id,
            'note' => $note,
        ];

        $new_payment_received_amount = 0.0;
        foreach ($payments as $p) {
            $new_payment_received_amount += (float) ($p['amount'] ?? 0);
        }
        $new_payment_received_amount = round($new_payment_received_amount, 2);

        $status = $this->derive_invoice_status(
            $existing['status'] ?? 'pending',
            (float) ($existing['amount_due'] ?? 0),
            $new_payment_received_amount
        );

        $payload = $existing;
        $payload['status'] = $status;
        $payload['payments'] = $payments;
        $payload['payment_received_amount'] = $new_payment_received_amount;
        $payload['previous_due_amount'] = $existing['previous_due_amount'] ?? 0;
        $this->save_invoice_meta($invoice_id, $payload);

        return rest_ensure_response($this->get_invoice_payload($invoice_id));
    }

    public function rest_delete_invoice_payment(WP_REST_Request $request) {
        $invoice_id = absint($request['id']);
        $payment_id = sanitize_text_field((string) ($request['payment_id'] ?? ''));
        $existing = $this->get_invoice_payload($invoice_id);
        if (!$existing) {
            return new WP_Error('manfiet_invoice_not_found', __('Invoice not found.', 'manfi-expense-tracker'), ['status' => 404]);
        }

        $payments = $existing['payments'] ?? [];
        $filtered = [];
        foreach ($payments as $p) {
            if (($p['id'] ?? '') !== $payment_id) {
                $filtered[] = $p;
            }
        }

        $new_payment_received_amount = 0.0;
        foreach ($filtered as $p) {
            $new_payment_received_amount += (float) ($p['amount'] ?? 0);
        }
        $new_payment_received_amount = round($new_payment_received_amount, 2);

        $status = $this->derive_invoice_status(
            $existing['status'] ?? 'pending',
            (float) ($existing['amount_due'] ?? 0),
            $new_payment_received_amount
        );

        $payload = $existing;
        $payload['status'] = $status;
        $payload['payments'] = $filtered;
        $payload['payment_received_amount'] = $new_payment_received_amount;
        $payload['previous_due_amount'] = $existing['previous_due_amount'] ?? 0;
        $this->save_invoice_meta($invoice_id, $payload);

        return rest_ensure_response($this->get_invoice_payload($invoice_id));
    }

    public function rest_delete_invoice(WP_REST_Request $request) {
        $invoice_id = absint($request['id']);
        $result = wp_trash_post($invoice_id);
        if (!$result) {
            return new WP_Error('manfiet_invoice_delete_failed', __('Failed to delete invoice.', 'manfi-expense-tracker'), ['status' => 400]);
        }

        return rest_ensure_response(['deleted' => true]);
    }

    public function rest_invoice_report() {
        $invoices = $this->rest_list_invoices()->get_data();
        $monthly = [];
        $status_counts = [
            'pending' => 0,
            'partial' => 0,
            'paid' => 0,
            'overdue' => 0,
            'draft' => 0,
        ];
        $total = 0;

        foreach ($invoices as $invoice) {
            $grand = (float) ($invoice['totals']['grand_total'] ?? 0);
            $total += $grand;

            $created_at = substr((string) ($invoice['created_at'] ?? ''), 0, 7);
            if ($created_at !== '') {
                $monthly[$created_at] = ($monthly[$created_at] ?? 0) + $grand;
            }

            $status = strtolower((string) ($invoice['status'] ?? 'pending'));
            if (!isset($status_counts[$status])) {
                $status_counts[$status] = 0;
            }
            $status_counts[$status]++;
        }

        ksort($monthly);

        return rest_ensure_response([
            'summary' => [
                'count' => count($invoices),
                'total' => round($total, 2),
                'average' => count($invoices) ? round($total / count($invoices), 2) : 0,
            ],
            'monthly' => array_map(static function ($month, $value) {
                return [
                    'label' => $month,
                    'value' => round($value, 2),
                ];
            }, array_keys($monthly), array_values($monthly)),
            'status_counts' => $status_counts,
        ]);
    }

    public function rest_download_invoice_pdf(WP_REST_Request $request) {
        $invoice_id = absint($request['id']);
        $invoice = $this->get_invoice_payload($invoice_id);

        if (!$invoice) {
            return new WP_Error('manfiet_invoice_not_found', __('Invoice not found.', 'manfi-expense-tracker'), ['status' => 404]);
        }

        // Generate HTML from the invoice data
        $html = $this->generate_invoice_html($invoice);

        // Use dompdf to generate PDF
        try {
            $dompdf = new \Dompdf\Dompdf([
                'isPhpEnabled' => true,
                'isRemoteEnabled' => true,
                'defaultMediaType' => 'screen',
            ]);

            $dompdf->setPaper('A4');
            $dompdf->loadHtml($html);
            $dompdf->render();

            $filename = sanitize_file_name($invoice['invoice_no'] . ' - ' . $invoice['client_name'] . '.pdf');

            // Send headers
            header('Content-Type: application/pdf');
            header('Content-Disposition: attachment; filename="' . $filename . '"');
            header('Cache-Control: no-cache, no-store, must-revalidate');
            header('Pragma: no-cache');
            header('Expires: 0');

            // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Outputting binary PDF content from Dompdf.
            echo $dompdf->output();
            exit;
        } catch (\Exception $e) {
            return new WP_Error('manfiet_pdf_generation_failed', __('Failed to generate PDF: ', 'manfi-expense-tracker') . $e->getMessage(), ['status' => 500]);
        }
    }

    private function generate_invoice_html($invoice) {
        $vendor_id = (int) $invoice['vendor_id'];
        $vendor_logo = '';
        $vendor_company = '';
        $vendor_tagline = '';

        if ($vendor_id > 0) {
            $vendor_post = get_post($vendor_id);
            if ($vendor_post && $vendor_post->post_type === 'manfiet_vendor') {
                $vendor_company = (string) get_post_meta($vendor_id, '_manfiet_vendor_company_name', true);
                if ($vendor_company === '') {
                    $vendor_company = get_the_title($vendor_post);
                }
                $vendor_logo = (string) get_post_meta($vendor_id, '_manfiet_vendor_logo_url', true);
                $vendor_tagline = (string) get_post_meta($vendor_id, '_manfiet_vendor_tagline', true);
            }
        }

        $css_file = MANFIET_EXPENSE_TRACKER_PLUGIN_DIR . 'assets/css/invoice-pdf.css';
        $css_content = file_exists($css_file) ? file_get_contents($css_file) : '';

        $html = '<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    ' . sprintf('<%1$s>%2$s</%1$s>', 'style', $css_content) . '
</head>
<body>
    <div class="container">
        <!-- Header -->
        <div class="header">
            <div class="company-info">
                ' . (!empty($vendor_logo) ? '<img src="' . esc_attr($vendor_logo) . '" class="company-logo" alt="Logo">' : '') . '
                <div class="company-name">' . esc_html($vendor_company) . '</div>
                ' . (!empty($vendor_tagline) ? '<div class="company-tagline">' . esc_html($vendor_tagline) . '</div>' : '') . '
                <div class="company-details">
                    ' . esc_html($invoice['phone']) . '<br>
                    ' . esc_html($invoice['email']) . '
                    ' . (!empty($invoice['email2']) ? '<br>' . esc_html($invoice['email2']) : '') . '
                    ' . (!empty($invoice['address']) ? '<br>' . esc_html($invoice['address']) : '') . '
                </div>
            </div>
            <div class="invoice-title">
                <h1>INVOICE</h1>
                <div class="invoice-meta">
                    <strong>Invoice #:</strong> ' . esc_html($invoice['invoice_no']) . '<br>
                    <strong>Date:</strong> ' . esc_html($invoice['date']) . '<br>
                    ' . (!empty($invoice['due_date']) ? '<strong>Due Date:</strong> ' . esc_html($invoice['due_date']) . '<br>' : '') . '
                    <strong>Status:</strong> ' . ucfirst(esc_html($invoice['status'])) . '
                </div>
            </div>
        </div>

        <!-- Bill To -->
        <div class="content-section">
            <div class="section-title">Bill To</div>
            <div class="bill-to">
                <div class="address-block">
                    <strong>' . esc_html($invoice['client_name']) . '</strong><br>
                    ' . esc_html($invoice['phone']) . '<br>
                    ' . esc_html($invoice['email']) . '
                    ' . (!empty($invoice['email2']) ? '<br>' . esc_html($invoice['email2']) : '') . '
                    ' . (!empty($invoice['address']) ? '<br>' . esc_html($invoice['address']) : '') . '
                </div>
            </div>
        </div>

        <!-- Service Description -->
        ' . (!empty($invoice['service_desc']) ? '<div class="content-section"><div class="section-title">Service Description</div><div class="service-desc">' . esc_html($invoice['service_desc']) . '</div></div>' : '') . '

        <!-- Campaigns/Line Items -->
        <div class="content-section no-page-break">
            <table class="campaigns-table">
                <thead>
                    <tr>
                        <th style="width: 50%;">Campaign/Service</th>
                        <th style="width: 12.5%;">Daily Budget</th>
                        <th style="width: 12.5%;">Duration</th>
                        <th style="width: 25%; text-align: right;">Amount</th>
                    </tr>
                </thead>
                <tbody>
                    ' . $this->render_campaigns_for_pdf($invoice['campaigns']) . '
                    ' . (!empty($invoice['adjustment_usd']) || !empty($invoice['adjustment_bdt']) || !empty($invoice['adjustment_note']) ? (function() use ($invoice) {
                        $adj_val = !empty($invoice['adjustment_usd']) ? (float) $invoice['adjustment_usd'] : ((!empty($invoice['adjustment_bdt']) && !empty($invoice['exchange_rate'])) ? ((float) $invoice['adjustment_bdt'] / (float) $invoice['exchange_rate']) : (float) ($invoice['adjustment_bdt'] ?? 0));
                        $color = $adj_val < 0 ? '#b91c1c' : '#15803d';
                        $sign = $adj_val < 0 ? '-' : '+';
                        return '<tr style="background: #fafaf9; font-style: italic;">
                            <td colspan="3" style="border: 1px solid #ddd; padding: 8px;">
                                <strong>' . esc_html__('Adjustment:', 'manfi-expense-tracker') . '</strong> ' . esc_html($invoice['adjustment_note'] ?: __('Invoice adjustment', 'manfi-expense-tracker')) . '
                            </td>
                            <td class="amount" style="border: 1px solid #ddd; padding: 8px; font-weight: bold; text-align: right; color: ' . $color . ';">
                                ' . $sign . '$' . number_format(abs($adj_val), 2) . '
                            </td>
                        </tr>';
                    })() : '') . '
                </tbody>
            </table>
        </div>

        <!-- Summary -->
        <div class="summary-section no-page-break">
            <div class="summary-left"></div>
            <div class="summary-right">
                <table class="summary-table">
                    <tr>
                        <td>SUBTOTAL (USD):</td>
                        <td class="amount">' . number_format($invoice['totals']['subtotal'], 2) . '</td>
                    </tr>
                    <tr>
                        <td>EXCHANGE RATE:</td>
                        <td class="amount">1 USD = ' . number_format($invoice['exchange_rate'], 2) . '</td>
                    </tr>
                    <tr>
                        <td>SUBTOTAL (BDT):</td>
                        <td class="amount">' . number_format($invoice['totals']['subtotal_bdt'], 2) . '</td>
                    </tr>
                    ' . (!empty($invoice['totals']['discount_bdt']) ? '<tr><td>' . esc_html(($invoice['totals']['discount_type'] === 'flat' || $invoice['totals']['discount_type'] === 'fixed') ? 'DISCOUNT (FLAT):' : 'DISCOUNT (' . number_format($invoice['totals']['discount_pct'], 2) . '%):') . '</td><td class="amount">- ' . number_format($invoice['totals']['discount'], 2) . '</td></tr>' : '') . '
                    ' . (!empty($invoice['vat_pct']) ? '<tr><td>VAT (' . $invoice['vat_pct'] . '%):</td><td class="amount">+ ' . number_format($invoice['totals']['vat'], 2) . '</td></tr>' : '') . '
                    ' . (!empty($invoice['adjustment_bdt']) ? '
                    <tr>
                        <td>' . esc_html__('ADJUSTMENT:', 'manfi-expense-tracker') . '</td>
                        <td class="amount" style="color: ' . ($invoice['adjustment_bdt'] < 0 ? '#b91c1c' : '#15803d') . ';">
                            ' . ($invoice['adjustment_bdt'] < 0 ? '-' : '+') . ' ' . number_format(abs($invoice['adjustment_bdt']), 2) . ' BDT
                        </td>
                    </tr>
                    ' : '') . '
                </table>
                <div class="grand-total">
                    <span>GRAND TOTAL (BDT)</span>
                    <span>' . number_format($invoice['totals']['grand_total'], 2) . '</span>
                </div>
            </div>
        </div>

        <!-- Payment Status -->
        <div class="content-section no-page-break">
            <div class="payment-info">
                <div class="payment-box">
                    <div class="payment-label">PAID AMOUNT</div>
                    <div class="payment-amount">' . number_format($invoice['payment_received_amount'], 2) . '</div>
                </div>
                <div class="payment-box">
                    <div class="payment-label">DUE AMOUNT</div>
                    <div class="payment-amount due-amount">' . number_format($invoice['balance_due'], 2) . '</div>
                </div>
            </div>
        </div>

        <!-- Payment Methods -->
        ' . $this->render_payment_info_for_pdf($invoice) . '

        <!-- Footer -->
        <div class="footer">
            <p>Thank you for your business!</p>
            <p style="margin-top: 10px; color: #ccc;">Generated on ' . current_time('Y-m-d H:i:s') . '</p>
        </div>
    </div>
</body>
</html>';

        return $html;
    }

    private function render_campaigns_for_pdf($campaigns) {
        $html = '';
        if (!is_array($campaigns)) {
            return $html;
        }

        foreach ($campaigns as $campaign) {
            $name = sanitize_text_field((string) ($campaign['name'] ?? ''));
            $desc = sanitize_text_field((string) ($campaign['description'] ?? ''));
            $daily = (float) ($campaign['daily_budget'] ?? 0);
            $duration = (int) ($campaign['duration'] ?? 0);
            $total = $daily * $duration;

            $desc_html = !empty($desc) ? '<div style="font-size: 9px; color: #666; margin-top: 2px;">' . esc_html($desc) . '</div>' : '';

            $html .= '<tr>
                <td>
                    <div style="font-weight: bold; color: #003d7a;">' . esc_html($name) . '</div>
                    ' . $desc_html . '
                </td>
                <td>' . esc_html(number_format($daily, 2)) . '</td>
                <td>' . esc_html((string) $duration) . '</td>
                <td class="amount">' . esc_html(number_format($total, 2)) . '</td>
            </tr>';
        }

        return $html;
    }

    private function render_payment_info_for_pdf($invoice) {
        $html = '';

        $payment_notes = __('Please note: Previous invoice tracking', 'manfi-expense-tracker');
        if (!empty($invoice['previous_invoice_no']) && !empty($invoice['previous_due_amount'])) {
            $payment_notes = sprintf(
                /* translators: 1: previous invoice number, 2: previous balance amount */
                __('Previous Invoice: %1$s | Previous Balance: %2$s', 'manfi-expense-tracker'),
                $invoice['previous_invoice_no'],
                number_format($invoice['previous_due_amount'], 2)
            );
        }

        $html .= '<div class="payment-notes">
            <strong>' . __('PAYMENT NOTES:', 'manfi-expense-tracker') . '</strong><br>
            ' . esc_html($payment_notes) . '
        </div>';

        $late_fee_pct = !empty($invoice['late_fee_pct']) ? (float) $invoice['late_fee_pct'] : (float) get_option('manfiet_invoice_late_fee_pct', 5.0);

        /* translators: %s: Due date. */
        $due_date_clause = !empty($invoice['due_date']) ? '• ' . sprintf(esc_html__('Payment is due on or before %s.', 'manfi-expense-tracker'), esc_html($invoice['due_date'])) . '<br>' : '';
        /* translators: %s: Late fee percentage. */
        $late_fee_clause = ($late_fee_pct > 0) ? '• ' . sprintf(esc_html__('An overdue late fee of %s%% will apply to any unpaid balance after the due date.', 'manfi-expense-tracker'), esc_html((string) $late_fee_pct)) . '<br>' : '';
        /* translators: %s: Invoice number. */
        $invoice_ref_clause = '• ' . sprintf(esc_html__('Please quote invoice %s as reference.', 'manfi-expense-tracker'), esc_html($invoice['invoice_no']));

        $html .= '<div class="payment-notes" style="margin-top: 15px; border-left: 3px solid #b8963e; background: #fafaf8;">
            <strong>' . esc_html__('TERMS & CONDITIONS:', 'manfi-expense-tracker') . '</strong><br>
            ' . $due_date_clause . '
            ' . $late_fee_clause . '
            ' . $invoice_ref_clause . '
            ' . (!empty($invoice['notes']) ? '<br><br>' . nl2br(esc_html($invoice['notes'])) : '') . '
        </div>';

        // Render payment accounts if available
        $bank_info = [
            'name' => $invoice['bank']['name'] ?? '',
            'account' => $invoice['bank']['account'] ?? '',
            'title' => $invoice['bank']['title'] ?? '',
        ];

        $bkash = $invoice['bkash'] ?? '';

        if (!empty($bank_info['name']) || !empty($bank_info['account']) || !empty($bkash)) {
            $html .= '<div class="payment-accounts">
                <div style="font-weight: bold; margin-bottom: 8px; color: #003d7a;">' . __('PAYMENT ACCOUNTS:', 'manfi-expense-tracker') . '</div>';

            if (!empty($bank_info['name'])) {
                $html .= '<div class="account">
                    <span class="account-type">' . __('Bank Account:', 'manfi-expense-tracker') . '</span><br>
                    ' . esc_html($bank_info['name']) . '<br>
                    ' . (!empty($bank_info['account']) ? esc_html($bank_info['account']) . '<br>' : '') . '
                    ' . (!empty($bank_info['title']) ? esc_html($bank_info['title']) : '') . '
                </div>';
            }

            if (!empty($bkash)) {
                $html .= '<div class="account">
                    <span class="account-type">bKash:</span><br>
                    ' . esc_html($bkash) . '
                </div>';
            }

            $html .= '</div>';
        }

        return $html;
    }

    public function template_include($template) {
        if (is_singular(self::POST_TYPE)) {
            if (!defined('DONOTCACHEPAGE')) {
                // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound -- DONOTCACHEPAGE is a standard WordPress caching constant.
                define('DONOTCACHEPAGE', true);
            }
            nocache_headers();
            $plugin_template = plugin_dir_path(__FILE__) . '../templates/single-manfiet-invoice.php';
            if (file_exists($plugin_template)) {
                return $plugin_template;
            }
        }

        return $template;
    }
}
