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

class DevsAccounting_Purchases
{
    public function __construct()
    {
        add_action('rest_api_init', [$this, 'purchases_api_endpoint']);
    }

    public function purchases_api_endpoint()
    {
        register_rest_route('devs-accounting/v1', '/add-purchase', [
            'methods' => 'POST',
            'callback' => [$this, 'save_purchases_data'],
            'permission_callback' => [$this, 'verify_purchases_nonce'],
        ]);

        register_rest_route('devs-accounting/v1', '/get-purchase', [
            'methods' => 'POST',
            'callback' => [$this, 'get_purchases_of_user'],
            'permission_callback' => [$this, 'verify_purchases_nonce'],
        ]);
    }

    public function verify_purchases_nonce($request)
    {
        $nonce = $request->get_header('X-WP-Nonce');
        if (!wp_verify_nonce($nonce, 'wp_rest')) {
            return new WP_Error('rest_forbidden', __('Invalid nonce', 'devs-accounting'), ['status' => 403]);
        }
        return true;
    }

    /* =====================================================
     * GET PURCHASES
     * ===================================================== */
        public function get_purchases_of_user($request)
    {
        global $wpdb;

        $invoice_table = $wpdb->prefix . 'dac_invoices';
        $invoice_items_table = $wpdb->prefix . 'dac_invoice_items';
        $contacts_table = $wpdb->prefix . 'dac_contacts';

        $params = $request->get_json_params();
        $wp_user_id = intval($params['user_id'] ?? 0);

        if (!$wp_user_id) {
            return new WP_REST_Response(['error' => 'User ID required'], 400);
        }

        $wp_user = get_user_by('id', $wp_user_id);
        if (!$wp_user) {
            return new WP_REST_Response([], 200); // Return empty array
        }

        $contact_id = $wpdb->get_var(
            $wpdb->prepare(
                "SELECT id FROM {$contacts_table} WHERE email = %s AND deleted_at IS NULL LIMIT 1",
                $wp_user->user_email
            )
        );

        if (!$contact_id) {
            return new WP_REST_Response([], 200); // Return empty array
        }

        $invoices = $wpdb->get_results(
            $wpdb->prepare("
                SELECT inv.*, ii.invoice_items_data
                FROM {$invoice_table} inv
                LEFT JOIN {$invoice_items_table} ii ON ii.invoice_no = inv.invoice_no 
                WHERE inv.contact_id = %d
                AND inv.deleted_at IS NULL
                AND inv.status IN ('Pending','Paid')
                ORDER BY inv.issued_at DESC
            ", $contact_id),
            ARRAY_A
        );

        $all_purchases = [];

        foreach ($invoices as $invoice) {
            $row = [
                'id' => $invoice['id'],
                'invoice_no' => $invoice['invoice_no'],
                'total_amount' => $invoice['amount'],
                'status' => $invoice['status'],
                'issued_at' => $invoice['issued_at'],
                'due_date' => $invoice['due_at'],
                'items' => [],
            ];

            if (!empty($invoice['invoice_items_data'])) {
                $items = json_decode($invoice['invoice_items_data'], true) ?: [];

                foreach ($items as $item) {
                    $row['items'][] = [
                        'id' => $item['id'] ?? '',
                        'name' => $item['name'] ?? '',
                        'price' => $item['sale_price'] ?? 0,
                        'qty' => $item['quantity'] ?? 1,
                        'image' => $item['image'] ?? '',
                        'sku' => $item['sku'] ?? '',
                        'description' => $item['description'] ?? '',
                        'category_id' => $item['category_id'] ?? '',
                        'meta' => $item['meta'] ?? '',
                        'purchase_price' => $item['purchase_price'] ?? 0,
                        'exp_date' => $item['exp_date'] ?? '',
                        'type' => $item['type'] ?? '',
                        'post_id' => $item['post_id'] ?? null,
                    ];
                }
            }

            $all_purchases[] = $row;
        }

        return new WP_REST_Response($all_purchases, 200);
    }

    /* =====================================================
     * SAVE PURCHASE
     * ===================================================== */
    public function save_purchases_data($request)
    {
        global $wpdb;
        $params = $request->get_json_params();

        try {
            $email = $this->get_user_email($params);
            $user_id = $this->get_or_create_contact($params);
            $item_id = intval($params['item_id']);
            $is_guest = !empty($params['is_guest_checkout']);
            $quantity = intval($params['payment_data']['product']['quantity'] ?? 1);
            $payment_method = sanitize_text_field($params['payment_method'] ?? '');

            if (!$item_id) {
                throw new Exception('Item ID missing');
            }

            $item = $wpdb->get_row(
                $wpdb->prepare("SELECT * FROM {$wpdb->prefix}dac_items WHERE id = %d", $item_id)
            );

            if (!$item) {
                throw new Exception('Item not found');
            }


            if (!empty($params['billing_address'])) {
                $this->save_billing_address($params['billing_address'], $is_guest);
            }

            $status = ucfirst(strtolower($params['payment_data']['status'] ?? 'Pending'));
            $totalAmount = $params['totalAmount'];

            $invoice_id = $this->create_invoice($user_id, $item, $status, $totalAmount, $payment_method);
            $this->create_invoice_item($invoice_id, $item, $params, $quantity);

            // Only create transaction for paid orders (not for cash on delivery pending orders)
            if ($status === 'Paid' || $payment_method !== 'cash_on_delivery') {
                $this->create_transaction($invoice_id, $user_id, $item, $params, $totalAmount, $payment_method, $status);
            }

            return new WP_REST_Response([
                'success' => true,
                'invoice_id' => $invoice_id,
                'message' => 'Purchase completed successfully',
            ], 201);

        } catch (Exception $e) {
            error_log('Purchase Error: ' . $e->getMessage());
            return new WP_REST_Response([
                'success' => false,
                'error' => $e->getMessage(),
            ], 500);
        }
    }

    /* =====================================================
     * HELPERS
     * ===================================================== */
    private function get_user_email($params)
    {
        // Prioritize billing email, then payment data email
        if (!empty($params['billing_address']['email'])) {
            return sanitize_email($params['billing_address']['email']);
        }

        if (empty($params['payment_data']['user']['email'])) {
            throw new Exception('Email missing');
        }
        return sanitize_email($params['payment_data']['user']['email']);
    }

    private function get_or_create_contact($params)
    {
        global $wpdb;
        $table = $wpdb->prefix . 'dac_contacts';

        $email = sanitize_email($params['billing_address']['email'] ?? '');
        if (empty($email)) {
            $email = sanitize_email($params['payment_data']['user']['email'] ?? '');
        }

        if (empty($email)) {
            throw new Exception('Email address is required');
        }

        $id = $wpdb->get_var(
            $wpdb->prepare("SELECT id FROM {$table} WHERE email = %s", $email)
        );

        $name = sanitize_text_field($params['billing_address']['name'] ?? 'Guest Customer');

        $contact_data = [
            'name' => $name,
            'updated_at' => current_time('mysql'),
        ];

        if (!empty($params['billing_address']['phone'])) {
            $contact_data['phone'] = sanitize_text_field($params['billing_address']['phone']);
        }

        if (!empty($params['billing_address']['address'])) {
            $contact_data['address'] = sanitize_text_field($params['billing_address']['address']);
        }

        if (!empty($params['billing_address']['state'])) {
            $contact_data['states'] = sanitize_text_field($params['billing_address']['state']);
        }

        if (!empty($params['billing_address']['city'])) {
            if (empty($contact_data['address'])) {
                $contact_data['address'] = sanitize_text_field($params['billing_address']['city']);
            } else {
                $contact_data['address'] .= ', ' . sanitize_text_field($params['billing_address']['city']);
            }
        }

        if ($id) {
            $wpdb->update($table, $contact_data, ['id' => $id]);
            return $id;
        }

        $contact_data['email'] = $email;
        $contact_data['type'] = 'customer';
        $contact_data['created_at'] = current_time('mysql');

        $contact_data['country'] = !empty($params['billing_address']['country'])
            ? sanitize_text_field($params['billing_address']['country'])
            : 'BD';
        $contact_data['enabled'] = 1;

        $result = $wpdb->insert($table, $contact_data);

        if (!$result) {
            error_log('Contact creation failed: ' . $wpdb->last_error);
            throw new Exception('Contact creation failed');
        }

        return $wpdb->insert_id;
    }

    private function save_billing_address($billing, $is_guest = false)
    {
        // Always try to save to WordPress user meta if user is logged in
        // Check if this is a logged-in user (not guest)
        if (!$is_guest) {
            // Try to get user by email
            $email = sanitize_email($billing['email'] ?? '');
            if (!empty($email)) {
                $user = get_user_by('email', $email);

                if ($user) {
                    update_user_meta($user->ID, 'billing_address', maybe_serialize($billing));

                    update_user_meta($user->ID, 'billing_first_name', $billing['name'] ?? '');
                    update_user_meta($user->ID, 'billing_address_1', $billing['address'] ?? '');
                    update_user_meta($user->ID, 'billing_city', $billing['city'] ?? '');
                    update_user_meta($user->ID, 'billing_state', $billing['state'] ?? '');
                    update_user_meta($user->ID, 'billing_phone', $billing['phone'] ?? '');
                    update_user_meta($user->ID, 'billing_email', $email);

                }
            }
        }

        if (!class_exists('DevsAccounting_User')) {
            return;
        }

        try {
            $user_class = new DevsAccounting_User();
            $user_class->update_user_meta_data([
                'meta_key' => 'billing_address',
                'meta_value' => maybe_serialize($billing),
            ]);
        } catch (Exception $e) {
            error_log('Failed to save billing address via DevsAccounting_User: ' . $e->getMessage());
        }
    }

    private function create_invoice($contact_id, $item, $status, $total_amount, $payment_method = '')
    {
        global $wpdb;

        $last_invoice = $wpdb->get_var(
            "SELECT invoice_no FROM {$wpdb->prefix}dac_invoices 
         WHERE invoice_no LIKE 'INV-%' 
         ORDER BY id DESC LIMIT 1"
        );

        if ($last_invoice) {
            $last_number = intval(substr($last_invoice, 4));
            $new_number = $last_number + 1;
        } else {
            $new_number = 1001;
        }

        $invoice_no = 'INV-' . $new_number;

        $invoice_data = [
            'type' => 'invoice',
            'contact_id' => $contact_id,
            'invoice_no' => $invoice_no,
            'order_no' => 'ORD-' . wp_rand(100000, 999999),
            'issued_at' => current_time('mysql'),
            'due_at' => date('Y-m-d H:i:s', strtotime('+30 days')), // Set due date 30 days from now
            'amount' => $total_amount,
            'discount' => 0,
            'status' => $status,
            'created_at' => current_time('mysql'),
            'updated_at' => current_time('mysql'),
        ];

        // Add payment method if column exists
        $table_columns = $wpdb->get_col("DESCRIBE {$wpdb->prefix}dac_invoices", 0);
        if (in_array('payment_method', $table_columns) && !empty($payment_method)) {
            $invoice_data['payment_method'] = $payment_method;
        }

        $result = $wpdb->insert($wpdb->prefix . 'dac_invoices', $invoice_data);

        if (!$result) {
            error_log('Invoice creation failed: ' . $wpdb->last_error);
            throw new Exception('Invoice creation failed');
        }

        return $wpdb->insert_id;
    }

    private function create_invoice_item($invoice_id, $item, $params, $quantity = 1)
    {
        global $wpdb;

        // Get the actual invoice number from the invoices table
        $invoice_number = $wpdb->get_var(
            $wpdb->prepare(
                "SELECT invoice_no FROM {$wpdb->prefix}dac_invoices WHERE id = %d",
                $invoice_id
            )
        );

        if ( ! $invoice_number ) {
            throw new Exception(
                'Could not find invoice number for invoice ID: ' . esc_html( $invoice_id )
            );
        }


        $item_data = [
            'id' => $item->id,
            'type' => $item->type,
            'post_id' => $item->post_id,
            'name' => $item->name,
            'description' => $item->description,
            'sku' => $item->sku,
            'sale_price' => $item->sale_price,
            'purchase_price' => $item->purchase_price,
            'category_id' => $item->category_id,
            'stock_limit' => $item->stock_limit,
            'quantity' => $quantity,
            'comment' => $item->comment,
            'exp_date' => $item->exp_date,
            'enabled' => $item->enabled,
            'image' => $item->image,
            'meta' => $item->meta,
            'deleted_at' => $item->deleted_at,
            'created_at' => $item->created_at,
            'updated_at' => $item->updated_at,
            'total_price' => floatval($item->sale_price) * $quantity,
        ];

        $result = $wpdb->insert($wpdb->prefix . 'dac_invoice_items', [
            'invoice_no' => $invoice_number,  // FIXED: Store the invoice number, not ID
            'invoice_items_data' => json_encode([$item_data], JSON_UNESCAPED_UNICODE),
            'created_at' => current_time('mysql'),
            'updated_at' => current_time('mysql'),
        ]);

        if (!$result) {
            error_log('Invoice item creation failed: ' . $wpdb->last_error);
            throw new Exception('Invoice item creation failed');
        }

        return true;
    }

    private function create_transaction($invoice_id, $contact_id, $item, $params, $totalAmount, $payment_method = '', $status = '')
    {
        global $wpdb;

        $table_name = $wpdb->prefix . 'dac_transactions';

        // Get transaction ID from payment data
        $transaction_id = '';
        if (!empty($params['payment_data']['transaction_id'])) {
            $transaction_id = sanitize_text_field($params['payment_data']['transaction_id']);
        } elseif (!empty($params['payment_data']['details']['id'])) {
            $transaction_id = sanitize_text_field($params['payment_data']['details']['id']);
        } else {
            $transaction_id = 'TXN-' . wp_rand(100000, 999999);
        }

        // For cash on delivery with pending status, we might not want to create a transaction
        // Or create it with a special status
        if ($payment_method === 'cash_on_delivery' && $status === 'Pending') {
            // Either don't create transaction for COD pending orders
            // OR create it with a different type/status
            // return null; // Uncomment to skip transaction creation for COD pending

            // Alternative: Create transaction but mark it appropriately
            $data = [
                'paid_at' => null, // Not paid yet
                'amount' => $totalAmount,
                'type' => 'pending_income',
                'description' => 'COD Invoice #' . $invoice_id . ' - ' . $item->name . ' (Pending)',
                'contact_id' => $contact_id,
                'payment_method' => $payment_method,
                'document_id' => $invoice_id,
                'transaction_id' => $transaction_id,
                'status' => 'pending', // Add status if your table has it
                'created_at' => current_time('mysql'),
                'updated_at' => current_time('mysql'),
            ];
        } else {
            // For paid orders
            $data = [
                'paid_at' => current_time('mysql'),
                'amount' => $totalAmount,
                'type' => 'income',
                'description' => 'Invoice #' . $invoice_id . ' - ' . $item->name,
                'contact_id' => $contact_id,
                'payment_method' => $payment_method,
                'document_id' => $invoice_id,
                'transaction_id' => $transaction_id,
                'created_at' => current_time('mysql'),
                'updated_at' => current_time('mysql'),
            ];
        }


        $result = $wpdb->insert( $table_name, $data );

        if ( ! $result ) {
            error_log( 'Transaction creation failed: ' . $wpdb->last_error );

            throw new Exception(
                'Transaction creation failed: ' . esc_html( $wpdb->last_error )
            );
        }


        return $wpdb->insert_id;
    }
}

new DevsAccounting_Purchases();