<?php

namespace KirilKirkov\WpInvoices;

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

class Woo
{
    /**
     * Check has active woocommerce
     */
    public function hasActiveWoocommerce()
    {
        return class_exists('WooCommerce');
    }

    /**
     * Check if is valid order id
     * 
     * @param int $order_id - id of the order
     */
    public function is_valid_order_id($order_id)
    {
        if($this->hasActiveWoocommerce() && is_numeric($order_id) && $order_id > 0) {
            // check if order exists
            $order = wc_get_order($order_id);
            if($order) {
                return true;
            }
        }

        return false;
    }

    public function is_cpt_orders_page()
    {
        // No nonce verification needed here – just checking the post_type
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
        if (is_admin() && isset($_GET['post_type']) && $_GET['post_type'] === 'shop_order') {
            return true;
        }
        return false;
    }

    public function get_order_object_by_id($order_id)
    {
        if($this->is_valid_order_id($order_id)) {
            return wc_get_order($order_id);
        }

        return false;
    }
    
    /**
     * Handle has new order
     * 
     * @param int $order_id - id of the order
     * @return void
     */
    public function new_order_created($order_id)
    {
        $order = wc_get_order( $order_id );
        $this->create_invoice($order);
    }

    /**
     * Handle has order status changed
     * 
     * @param int $order_id - id of the order
     * @return void
     */
    public function order_status_changed($order_id, $new_status, $old_status)
    {
        if($new_status !== $old_status) {
            $order = wc_get_order( $order_id );
            $this->create_invoice($order);
        }
    }

    /**
     * Create invoice for order
     * Called when has new order or change order status and 
     * create invoice from specified rules
     * 
     * @param object $order - Object of the order
     */
    public function create_invoice($order)
    {
        if(!$this->hasEnabledAutoCreateInvoices()) {
            return;
        }

        // if there is invoice for this order. .. do not create another
        global $wpdb;
        $i = new Invoices();

        // We need a fresh result directly from the database (not cached). Using $wpdb->get_var() with prepare() – the standard and safe approach for this operation.
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		$count = $wpdb->get_var($wpdb->prepare("SELECT COUNT(id) FROM ".esc_sql($i->table_name)." WHERE wc_id = %d", $order->get_id()));
        if($count > 0) {
            return;
        }

        if ('completed' === trim(strtolower((string)$order->get_status()))) {
            $this->generate_invoice_for_order($order);
        }
    }

    /**
     * Generate invoice from order
     * Object params - https://woocommerce.github.io/code-reference/classes/WC-Order.html
     * 
     * @param object $order - Object of the order
     * @param bool $return_as_array - Return as array or not
     */
    public function generate_invoice_for_order($order, $return_as_array = false)
    {
        $next_inv_number = Invoices::get_next_inv_number('invoice');

        $post = [
            'id' => 0,
            'wc_id' => $order->get_id(),
            Config::INPUTS_PREFIX.'to_invoice_number' => 0,
            Config::INPUTS_PREFIX.'from_date' => 0,

            Config::INPUTS_PREFIX.'invoice_type' => 'invoice',
            Config::INPUTS_PREFIX.'invoice_number' => $next_inv_number,
            Config::INPUTS_PREFIX.'invoice_date' => gmdate(Config::get_dates_format_type()),
            Config::INPUTS_PREFIX.'date_tax_event' => gmdate(Config::get_dates_format_type()),
            Config::INPUTS_PREFIX.'due_date' => '',
            Config::INPUTS_PREFIX.'has_maturity' => 0,
            Config::INPUTS_PREFIX.'maturity_date' => '',
            Config::INPUTS_PREFIX.'cash_accounting' => 0,

            Config::INPUTS_PREFIX.'currency' => $order->get_currency(),
            Config::INPUTS_PREFIX.'items_total' => $order->get_total(),
            Config::INPUTS_PREFIX.'discount' => $order->get_discount_total(),
            Config::INPUTS_PREFIX.'discount_type' => $order->get_currency(),

            Config::INPUTS_PREFIX.'vat_percent' => '',
            Config::INPUTS_PREFIX.'vat_sum' => '',
            Config::INPUTS_PREFIX.'no_vat' => 0,
            Config::INPUTS_PREFIX.'final_total' => $order->get_total(),
            Config::INPUTS_PREFIX.'remarks' => '',
            Config::INPUTS_PREFIX.'payment_method' => $order->get_payment_method_title(),
            Config::INPUTS_PREFIX.'tax_base' => '',
            Config::INPUTS_PREFIX.'no_vat_reason' => '',
            Config::INPUTS_PREFIX.'compiled' => '',
            Config::INPUTS_PREFIX.'schiffer' => '',
            Config::INPUTS_PREFIX.'customer_user_id' => $order->get_user_id(),

            // client
            Config::INPUTS_PREFIX.'client_from_list' => 0,
            Config::INPUTS_PREFIX.'client' => [
                'client' => trim($order->get_billing_first_name()) . ' ' . trim($order->get_billing_last_name()),
                'is_individual' => 0,
                'has_vat_registration' => 0,
                'vat_number' => '',
                'accountable_person' => trim($order->get_billing_first_name()) . ' ' . trim($order->get_billing_last_name()),
                'identification_number' => '',
                'city' => $order->get_billing_city(),
                'address' => $order->get_billing_address_1() . ' / ' . $order->get_billing_address_2(),
                'country' => $order->get_billing_country(),
                'beneficiary' => trim($order->get_billing_first_name()) . ' ' . trim($order->get_billing_last_name()),
            ],
        ];

       foreach($order->get_items() as $item_id => $item) {
            $post[Config::INPUTS_PREFIX.'items']['item_from_list'][] = 0;
            $post[Config::INPUTS_PREFIX.'items']['items_names'][] = $item->get_name();
            $post[Config::INPUTS_PREFIX.'items']['items_quantities'][] = $item->get_quantity();
            $post[Config::INPUTS_PREFIX.'items']['items_quantity_types'][] = '';
            $post[Config::INPUTS_PREFIX.'items']['items_prices'][] = $item->get_subtotal();
            $post[Config::INPUTS_PREFIX.'items']['items_totals'][] = $item->get_total();
       }

       if($return_as_array) {
           return $post;
       }

       $created_invoice = CreateInvoice::create_invoice($post);
       if($created_invoice !== false) {
            return true;
       } else { // if wants to debug..
            // $errors = CreateInvoice::get_validation_errors();
            // var_dump($r, $errors);
            // exit;
       }
    }

    /**
     * Check settings if has auto create inv
     */
    public function hasEnabledAutoCreateInvoices()
    {
        $auto_create_inv = (int)get_option(Config::INPUTS_PREFIX.'auto_create_inv');
        return $auto_create_inv === 1;
    }

    /**
     * Add invoices box to WC edit page
     */
    public function add_invoice_box() 
    {
        add_meta_box('kk-wp-invoices-wc-metabox', esc_html( 'WP Invoice', 'kirilkirkov-pdf-invoice-manager' ), array($this,'create_metabox_content'), 'shop_order', 'side', 'default');
    }

    public function create_metabox_content($post)
    {
        global $wpdb;
        $i = new Invoices();

        // We need a fresh result directly from the database (not cached). Using $wpdb->get_var() with prepare() – the standard and safe approach for this operation.
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		$inv_id = $wpdb->get_var($wpdb->prepare("SELECT id FROM ".esc_sql($i->table_name)." WHERE wc_id = %d", $post->ID));

        // We need a fresh result directly from the database (not cached). Using $wpdb->get_var() with prepare() – the standard and safe approach for this operation.
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $invoice_number = $wpdb->get_var($wpdb->prepare("SELECT invoice_number FROM ".esc_sql($i->table_name)." WHERE wc_id = %d", $post->ID));

        if((int)$inv_id < 1) {
            echo esc_html( 'There is no invoice generated', 'kirilkirkov-pdf-invoice-manager' );
        } else {
            $url = esc_url(admin_url( 'admin.php?page=' . Config::SUB_MENU_PREVIEW_INVOICE_PAGE_SLUG . '&view=' . $inv_id ));
            echo '<a class="button wf-packing-list-link" href="'.esc_url($url).'">'.esc_html($invoice_number).'</a>';
        }
    }

    /**
     * Add wp invoice column to orders table
     */
    public function add_invoice_column($columns)
    {
        $columns['kk-wp-invoice-id'] = esc_html( 'WP Invoice', 'kirilkirkov-pdf-invoice-manager' );
        return $columns;
    }

    // legacy – for CPT-based orders
    public function add_invoice_column_value_cpt( $column, $post_id )
    {
        if($column === 'kk-wp-invoice-id') {
            $this->get_value_for_table_column($post_id);
        }
    }

    // for HPOS-based orders
    public function add_invoice_column_value_hpos( $column, $post_id )
    {
        if($column === 'kk-wp-invoice-id') {
            if(is_object($post_id)) {
                if(method_exists($post_id, 'get_id') && is_callable([$post_id, 'get_id'])) {
                    $post_id = $post_id->get_id();
                } else {
                    $post_id = $post_id->ID;
                }
            } else {
                $post_id = (int)$post_id;
            }

            $this->get_value_for_table_column($post_id);
        }
    }

    private function get_value_for_table_column($post_id)
    {
        global $wpdb;
        $i = new Invoices();

        // We need a fresh result directly from the database (not cached). Using $wpdb->get_var() with prepare() – the standard and safe approach for this operation.
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $inv_id = $wpdb->get_var($wpdb->prepare("SELECT id FROM ".esc_sql($i->table_name)." WHERE wc_id = %d", $post_id));

        // We need a fresh result directly from the database (not cached). Using $wpdb->get_var() with prepare() – the standard and safe approach for this operation.
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $invoice_number = $wpdb->get_var($wpdb->prepare("SELECT invoice_number FROM ".esc_sql($i->table_name)." WHERE wc_id = %d", $post_id));
        
        if((int)$inv_id < 1) {
            echo esc_html( 'No invoice generated', 'kirilkirkov-pdf-invoice-manager' );
        } else {
            $url = esc_url(admin_url( 'admin.php?page=' . Config::SUB_MENU_PREVIEW_INVOICE_PAGE_SLUG . '&view=' . $inv_id ));
            echo '<a class="button" href="'.esc_url($url).'">'.esc_html($invoice_number).'</a>';
        }
    }
}