<?php

namespace Rtc\PlantShopWC\Frontend\Controllers;

use Rtc\PlantShopWC\Admin\Models\GeneralSettingsModel;
use Rtc\PlantShopWC\Admin\Modules\BotanicalName;
use Rtc\PlantShopWC\Admin\Modules\Plot;
use Rtc\PlantShopWC\Frontend\Models\CartModel;
use Rtc\PlantShopWC\Frontend\Views\CartView;


class CartController {


    protected $model;
    protected $view;

    protected $botanical_name_checked;
    protected $frontend_bed_sorting_enabled;
    protected $frontend_bed_number_visible;

    public function __construct() {
        $this->model = new CartModel();
        $this->view  = new CartView();

        $opts                               = get_option( GeneralSettingsModel::get_option_key(), array() );
        $botanical_name_checked             = isset( $opts['botanical_name_replacement'] ) ? (string) $opts['botanical_name_replacement'] : '';
        $this->botanical_name_checked       = ( $botanical_name_checked === '1' );
        $sorting_toggle                     = isset( $opts['enable_frontend_bed_sorting'] ) ? (string) $opts['enable_frontend_bed_sorting'] : '1';
        $bed_number_toggle                  = isset( $opts['show_frontend_bed_number'] ) ? (string) $opts['show_frontend_bed_number'] : '1';
        $this->frontend_bed_sorting_enabled = ( $sorting_toggle === '1' );
        $this->frontend_bed_number_visible  = ( $bed_number_toggle === '1' );
    }

    public function register_hooks(): void {

        // Show bed number in cart item data (free + pro)
        if ( $this->frontend_bed_number_visible ) {
            add_filter( 'woocommerce_get_item_data', array( $this, 'add_bed_number_item_data' ), 10, 2 );
        }

        add_action( 'woocommerce_after_cart', array( $this, 'add_cart_neighbors' ) );

        // Change the Product Title to Botanical Name if enabled
        // Also runs on checkout
        if ( $this->botanical_name_checked ) {
            add_filter( 'woocommerce_cart_item_name', array( $this, 'plantshop_wc_title' ), 20, 2 );
        }

        // Sort cart by bed number
        if ( $this->frontend_bed_sorting_enabled ) {
            add_action( 'woocommerce_cart_loaded_from_session', array( $this, 'sort_cart_by_bed' ), 20 );
            // Also hook before totals as a fallback when cart changes after session load
            add_action( 'woocommerce_before_calculate_totals', array( $this, 'sort_cart_by_bed' ), 5 );
        }
    }

    /**
     * Append Bed number to cart item data display.
     *
     * @param array $item_data
     * @param array $cart_item
     * @return array
     */
    public function add_bed_number_item_data( array $item_data, array $cart_item ): array {
        if ( ! $this->frontend_bed_number_visible ) {
            return $item_data;
        }

        $product = $cart_item['data'] ?? null;
        if ( ! $product ) {
            return $item_data;
        }
        $product_id = (int) $product->get_id();
        if ( $product_id <= 0 ) {
            return $item_data;
        }

        $bed = $this->get_product_bed_number( $product_id );
        if ( $bed !== '' ) {
            $item_data[] = array(
                'name'    => __( 'Bed number', 'plantshop-wc' ),
                'value'   => esc_html( $bed ),
                'display' => esc_html( $bed ),
            );
        }

        return $item_data;
    }

    public function plantshop_wc_title( $name, $cart_item ) {

        if ( is_admin() ) {
            return $name;
        }
        $product = $cart_item['data'] ?? null;
        if ( ! $product || ! GeneralSettingsModel::is_product_included( $product ) ) {
            return $name;
        }

        $botanical_name = new BotanicalName();

        if ( preg_match( '#^(<a[^>]*>)(.*?)(</a>)$#i', $name, $m ) ) {
            $new_inner = $botanical_name->build( $product, wp_strip_all_tags( $m[2] ), true );
            return $m[1] . $new_inner . $m[3];
        }

        return $botanical_name->build( $product, wp_strip_all_tags( $name ), true );
    }

    public function add_cart_neighbors(): void {

        if ( ! function_exists( 'is_cart' ) || ! is_cart() ) {
            return;
        }

        $cart = WC()->cart;

        $contents = $cart->get_cart();
        if ( empty( $contents ) ) {
            return;
        }

        $neighbors = $this->model->get_neighbors( $contents, $this->botanical_name_checked );
        if ( empty( $neighbors ) ) {
            return;
        }

        $html = $this->view->render_neighbors( $neighbors );

        echo wp_kses_post( $html );
    }

    /**
     * If Pro, sort the cart contents by bed number ascending.
     */
    public function sort_cart_by_bed(): void {
        if ( ! $this->frontend_bed_sorting_enabled ) {
            return;
        }

        if ( ! function_exists( 'WC' ) || ! WC() || ! WC()->cart ) {
            return;
        }

        $cart = WC()->cart;
        // cart_contents is an associative array; we'll preserve keys while ordering
        $contents = $cart->get_cart();
        if ( empty( $contents ) ) {
            return;
        }

        // Build an array of [key, item, bed, original_index]
        $rows = array();
        $idx  = 0;
        foreach ( $contents as $key => $item ) {
            $product = $item['data'] ?? null;
            $pid     = $product ? (int) $product->get_id() : 0;
            $bed_raw = ( $pid > 0 ) ? $this->get_product_bed_number( $pid ) : '';
            $bed_num = is_numeric( $bed_raw ) ? (int) $bed_raw : PHP_INT_MAX; // Put non-set at bottom
            $rows[]  = array(
                'key'  => $key,
                'item' => $item,
                'bed'  => $bed_num,
                'i'    => $idx++,
            );
        }

        usort(
            $rows,
            function ( $a, $b ) {
                if ( $a['bed'] === $b['bed'] ) {
                    return $a['i'] <=> $b['i'];
                }
                    return $a['bed'] <=> $b['bed'];
            }
        );

        // Rebuild cart_contents preserving keys in new order
        $sorted = array();
        foreach ( $rows as $row ) {
            $sorted[ $row['key'] ] = $row['item'];
        }

        // Assign back only if order actually changed
        if ( array_keys( $sorted ) !== array_keys( $contents ) ) {
            $cart->cart_contents = $sorted; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
        }
    }

    private function get_product_bed_number( int $product_id ): string {
        // Try on given product
        $plot      = new Plot();
        $plot_data = $plot->get( $product_id );
        $bed       = isset( $plot_data['bed_number'] ) ? (string) $plot_data['bed_number'] : '';

        // If empty and product is a variation, try parent product
        if ( $bed === '' && function_exists( 'wc_get_product' ) ) {
            $prod = wc_get_product( $product_id );
            if ( $prod && $prod->is_type( 'variation' ) ) {
                $parent_id = (int) $prod->get_parent_id();
                if ( $parent_id > 0 ) {
                    $plot_data_parent = $plot->get( $parent_id );
                    $bed              = isset( $plot_data_parent['bed_number'] ) ? (string) $plot_data_parent['bed_number'] : '';
                }
            }
        }

        // Ensure numeric-only
        if ( $bed === '' || ! preg_match( '/^\d+$/', $bed ) ) {
            return '';
        }
        // Normalize to integer string (no leading zeros issues)
        $bed_int = (int) $bed;
        return $bed_int > 0 ? (string) $bed_int : '';
    }
}
