<?php

/******************************************************************************************
 * Copyright (C) Smackcoders. - All Rights Reserved under Smackcoders Proprietary License
 * Unauthorized copying of this file, via any medium is strictly prohibited
 * Proprietary and confidential
 * You can contact Smackcoders at email address info@smackcoders.com.
 *******************************************************************************************/

namespace Smackcoders\WCSV;

if (! defined('ABSPATH'))
    exit; // Exit if accessed directly

class JetBookingImport
{

    private static $instance = null, $media_instance;

    public static function getInstance()
    {
        if (JetBookingImport::$instance == null) {
            JetBookingImport::$instance = new JetBookingImport;
            JetBookingImport::$instance = new JetBookingImport;
            JetBookingImport::$media_instance = MediaHandling::getInstance();
        }
        return JetBookingImport::$instance;
    }
    function set_jet_booking_values($header_array, $value_array, $map, $post_id, $type, $mode, $hash_key, $line_number, $gmode, $templatekey)
    {
        $post_values = [];
        $helpers_instance = ImportHelpers::getInstance();
        $post_values = $helpers_instance->get_header_values($map, $header_array, $value_array);
        $this->jet_booking_fields_import_function($post_values, $type, $post_id, $mode, $hash_key, $line_number, $header_array, $value_array, $gmode, $templatekey);
    }

    public function jet_booking_fields_import_function($data_array, $type, $post_id, $mode, $hash_key, $line_number, $header_array, $value_array, $gmode, $templatekey)
    {
        global $wpdb;
        $helpers_instance = ImportHelpers::getInstance();
        $plugin = 'jetengine-booking';
        $media_instance = MediaHandling::getInstance();
        $darray = array();
        $listTaxonomy = get_taxonomies();
        if (in_array($type, $listTaxonomy)) {
            $get_import_type = 'term';
        } elseif ($type == 'Users' || $type == 'user') {
            $get_import_type = 'user';
        } elseif ($type == 'Comments') {
            $get_import_type = 'comment';
        } else {
            $get_import_type = 'post';
        }


        foreach ($data_array as $dkey => $dvalue) {

            $dvalue = trim($dvalue);
            if (!empty($dvalue) && ($dkey == 'jet_abaf_price' || $dkey == 'jet_abaf_custom_schedule' || $dkey == 'jet_abaf_configuration')) {
                // Unserialize the string, if possible
                $data = maybe_unserialize($dvalue);
                if (is_string($data)) {
                    $data = unserialize($dvalue);
                }
                // Update post meta with properly serialized data
                update_post_meta($post_id, $dkey, $data);
            }
        }

        if (!empty($data_array['unit_title'])) {
            $unit_titles = explode('|', $data_array['unit_title']);
            $numbers = explode('|', $data_array['unit_number']);

            // Ensure both arrays have the same length
            if (count($unit_titles) === count($numbers)) {
                foreach ($unit_titles as $index => $unit_title) {
                    $number = !empty($numbers[$index]) ? absint($numbers[$index]) : 1;
                    $apartment = $post_id;
                    $result = jet_abaf()->db->get_apartment_units($apartment);
                    $current_count = count($result);

                    for ($i = 1; $i <= $number; $i++) {
                        $unit_num = $current_count + $i;

                        // Insert each unit with its title and calculated unit number
                        jet_abaf()->db::wpdb()->insert(jet_abaf()->db->units->table(), [
                            'apartment_id' => $apartment,
                            'unit_title'   => $unit_title . ' ' . $unit_num,
                        ]);
                    }
                    $current_count += $number;
                }
            }
        }
    }

    function jet_booking_import($item, $type, $mode, $unikey, $unikey_name, $line_number, $update_based_on, $check, $hash_key,$order_meta = null)
    {
        global $wpdb;
        $helpers_instance = ImportHelpers::getInstance();
        $core_instance = CoreFieldsImport::getInstance();
        global $core_instance;
        $log_table_name = $wpdb->prefix . "import_detail_log";
        $jet_booking_type = trim(jet_abaf()->settings->get( 'apartment_post_type' ));
        $updated_row_counts = $helpers_instance->update_count($unikey, $unikey_name);
        $created_count = $updated_row_counts['created'];
        $updated_count = $updated_row_counts['updated'];
        $skipped_count = $updated_row_counts['skipped'];
        $item['status'] = strtolower($item['status']);
        if ($item['status'] == 'on hold' || $item['status'] == 'onhold') {
            $item['status'] = 'on-hold';
        }
        if (!empty($item['attributes']) && isset($item['attributes'])) {
            $attributes = $item['attributes'];
            $item['attributes'] = $this->parseAttributes($attributes);
            }
        if ($mode == 'Insert' && !empty($item)) {
            $result = $this->insert_booking($item, $wpdb, $core_instance, $helpers_instance, $created_count, $updated_count, $skipped_count, $log_table_name, $type, $mode, $unikey, $unikey_name, $line_number, $update_based_on, $check, $hash_key,$jet_booking_type,$order_meta);
        } else if ($mode == 'Update' && !empty($item)) {
            $result = $this->update_booking($item, $wpdb, $core_instance, $helpers_instance, $created_count, $updated_count, $skipped_count, $log_table_name, $type, $mode, $unikey, $unikey_name, $line_number, $update_based_on, $check, $hash_key,$jet_booking_type,$order_meta);
        }
        return $result;
    }

    public function update_booking($item, $wpdb, $core_instance, $helpers_instance, $created_count, $updated_count, $skipped_count, $log_table_name, $type, $mode, $unikey, $unikey_name, $line_number, $update_based_on, $check, $hash_key,$jet_booking_type,$order_meta =null)
    {
        $item_id = $item['booking_id'];
        if(isset($jet_booking_type) && $jet_booking_type == 'product'){
            $item['calculateTotals'] =  1;
            if ( ! empty( $item['calculateTotals'] ) ) {
                wp_cache_set( 'calculate_booking_totals_' . $item_id, $item['calculateTotals'] );
            }
            if (! empty($item['attributes'])) {
                wp_cache_set('booking_attributes_' . $item_id, $item['attributes']);
            }
            if (! empty($item['guests'])) {
                wp_cache_set('booking_guests_' . $item_id, $item['guests']);
            }
        }
		$not_allowed = ['booking_id','order_id','user_id','check_in_date_timestamp','check_out_date_timestamp','attributes','guests','firstName','lastName','email','phone' ,'calculateTotals'];

        if (empty($item) || empty($item['check_in_date']) || empty($item['check_out_date'])) {
            $core_instance->detailed_log[$line_number]['Message'] = "No data to update. Incorrect item data in Jet-Booking.";
            $core_instance->detailed_log[$line_number]['state'] = 'Skipped';
            $wpdb->get_results("UPDATE $log_table_name SET skipped = $skipped_count WHERE $unikey_name = '$unikey'");
            return array('MODE' => $mode, 'ERROR_MSG' => 'No data to update');
        }
        foreach ($not_allowed as $key) {
            if (isset($item[$key])) {
                unset($item[$key]);
            }
        }

        $item['check_in_date']  = strtotime($item['check_in_date']);
        $item['check_out_date'] = strtotime($item['check_out_date']);
        $apartment_units = jet_abaf()->db->get_apartment_units($item['apartment_id']);

        if (! empty($apartment_units)) {
            $apartment_unit = jet_abaf()->db->get_apartment_unit($item['apartment_id'], $item['apartment_unit']);

            if (empty($apartment_unit)) {
                $item['apartment_unit'] = jet_abaf()->db->get_available_unit($item);
            }
        }

        $is_available       = jet_abaf()->db->booking_availability($item, $item_id);
        $is_dates_available = jet_abaf()->db->is_booking_dates_available($item, $item_id);
        $is_days_available  = jet_abaf()->tools->is_booking_period_available($item);

        if (! $is_available && ! $is_dates_available || ! $is_days_available) {
            $error_message = "Unable to add this record ";
            if (! $is_available) {
                $error_message .= "Booking unit is not open or available.";
            } elseif (! $is_dates_available) {
                $error_message .= "Requested booking dates are unavailable.";
            } elseif (! $is_days_available) {
                $error_message .= "Requested booking days are unavailable.";
            } else {
                $error_message .= "Something went wrong";
            }
            // Log the message and update the detailed log
            $core_instance->detailed_log[$line_number]['Message'] = $error_message;
            $core_instance->detailed_log[$line_number]['state'] = 'Skipped';
            $wpdb->get_results("UPDATE $log_table_name SET skipped = $skipped_count WHERE $unikey_name = '$unikey'");

            return array('MODE' => $mode, 'ERROR_MSG' => $error_message);
        }
        // Booking updated
        jet_abaf()->db->update_booking($item_id, $item); 
        // Update booking order details
        $booking = jet_abaf_get_booking( $item_id ); 
        if($booking->get_order_id()){
            $order_id = $booking->get_order_id();
        } 
        if(!empty($order_id) && isset($order_id) && !empty($order_meta) && isset($order_meta)){
            $order = wc_get_order($order_id);
            $first_name = isset($order_meta['firstName']) ? $order_meta['firstName'] : '';
            $last_name = isset($order_meta['lastName']) ? $order_meta['lastName'] : '';
            $email = isset($order_meta['email']) ? $order_meta['email'] : '';
            $phone = isset($order_meta['phone']) ? $order_meta['phone'] : '';
            if ($order) {
                $billing_address = array(
                    'first_name' => $first_name,
                    'last_name'  => $last_name,
                    'email'      => $email,
                    'phone'      => $phone
                );
                $order->set_address($billing_address, 'billing');
                $order_id = $order->save();
            }
        }
        $mode_of_affect = 'Updated';
        $core_instance->detailed_log[$line_number]['state'] = 'Updated';
        $wpdb->get_results("UPDATE $log_table_name SET updated = $updated_count WHERE $unikey_name = '$unikey'");
        $returnArr['ID'] = $item_id;
        $returnArr['MODE'] = $mode_of_affect;
        return $returnArr;
    }
    public function insert_booking($item, $wpdb, $core_instance, $helpers_instance, $created_count, $updated_count, $skipped_count, $log_table_name, $type, $mode, $unikey, $unikey_name, $line_number, $update_based_on, $check, $hash_key,$jet_booking_type,$order_meta = null)
    {
        $order_status = $item['orderStatus'] ?? '';
        $import_id = $item['import_id'] ?? '';
        $user_id = $item['user_id'] ?? '';
       // unset($item['orderStatus']);

    
       $not_allowed = ['order_id','orderStatus','firstName','lastName','email','phone'];
        foreach ( $not_allowed as $key ) {
            if ( isset( $item[ $key ] ) ) {
                unset( $item[ $key ] );
            }
        }
        if (empty($item['check_in_date']) || empty($item['check_out_date'])) {
            $core_instance->detailed_log[$line_number]['Message'] = "Booking date is empty";
            $core_instance->detailed_log[$line_number]['state'] = 'Skipped';
            $wpdb->get_results("UPDATE $log_table_name SET skipped = $skipped_count WHERE $unikey_name = '$unikey'");
            return array('MODE' => $mode, 'ERROR_MSG' => 'Invalid');
        }

        $item['check_in_date']  = strtotime($item['check_in_date']);
        $item['check_out_date'] = strtotime($item['check_out_date']);

        if ($item['check_in_date'] >= $item['check_out_date']) {
            $item['check_out_date'] = $item['check_in_date'] + 12 * HOUR_IN_SECONDS;
        }

        if (empty($item['apartment_unit'])) {
            $item['apartment_unit'] = jet_abaf()->db->get_available_unit($item);
        }
        $is_available       = jet_abaf()->db->booking_availability($item);
        $is_dates_available = jet_abaf()->db->is_booking_dates_available($item);
        $is_days_available  = jet_abaf()->tools->is_booking_period_available($item);
        $bookings_cpt = jet_abaf()->settings->get('apartment_post_type');
        $posts = jet_abaf()->tools->get_booking_posts();
        $post_ids = wp_list_pluck($posts, 'ID');
        $apartment_id = !empty($item['apartment_id']) ? $item['apartment_id'] : false;
        $apartment_id_check = in_array($apartment_id, $post_ids) ? true  : false;

        if (! $apartment_id || ! $apartment_id_check || ! $is_available && ! $is_dates_available || ! $is_days_available) {
            $error_message = "Unable to add this record ";
            if (! $apartment_id) {
                $error_message .= "Apartment ID is missing.";
            } else if (! $apartment_id_check) {
                $error_message .= "Apartment ID is not available in your " . $bookings_cpt;
            } else if (! $is_available) {
                $error_message .= "Booking unit is not open or available.";
            } elseif (! $is_dates_available) {
                $error_message .= "Requested booking dates are unavailable.";
            } elseif (! $is_days_available) {
                $error_message .= "Requested booking days are unavailable.";
            } else {
                $error_message .= "Something went wrong.";
            }
            // Log the message and update the detailed log
            $core_instance->detailed_log[$line_number]['Message'] = $error_message;
            $core_instance->detailed_log[$line_number]['state'] = 'Skipped';
            $wpdb->get_results("UPDATE $log_table_name SET skipped = $skipped_count WHERE $unikey_name = '$unikey'");

            return array('MODE' => $mode, 'ERROR_MSG' => $error_message);
        }
        $booking_id = jet_abaf()->db->insert_booking($item);
        if ($booking_id !== '0' && (! empty($order_status) || $jet_booking_type == 'product')) {
            $this->set_related_order_data($order_status, $booking_id, $item,$order_meta);
        }
        $mode_of_affect = 'Inserted';
        $core_instance->detailed_log[$line_number]['state'] = 'Inserted';
        $wpdb->get_results("UPDATE $log_table_name SET created = $created_count WHERE $unikey_name = '$unikey'");
        $returnArr['ID'] = $booking_id;
        $returnArr['MODE'] = $mode_of_affect;
        return $returnArr;
    }

    public function parseAttributes($attributesString) {
        $parsedAttributes = [];
        $attributeGroups = explode(',', $attributesString); // Split attributes by comma
    
        foreach ($attributeGroups as $group) {
            [$key, $values] = explode('->', $group); // Split key-value by '->'
            $taxonomy = 'pa_' . $key; // Prefix the key with 'pa_'
            $valuesArray = explode('|', $values); // Split values by pipe for multiple entries
            $parsedAttributes[$taxonomy] = $valuesArray;
        }
    
        return $parsedAttributes;
    }
    
    public function set_related_order_data($order_status, $booking_id, $booking,$order_meta = null)
    {
        if ('plain' === jet_abaf()->settings->get('booking_mode') && ! jet_abaf()->settings->get('wc_integration')) {
            $post_type        = jet_abaf()->settings->get('related_post_type');
            $post_type_object = get_post_type_object($post_type);

            $args = [
                'post_type'   => $post_type,
                'post_status' => ! empty($order_status) ? $order_status : 'draft',
            ];

            if (post_type_supports($post_type, 'excerpt')) {
                $args['post_excerpt'] = sprintf(__('This is %s post.', 'jet-booking'), $post_type_object->labels->singular_name);
            }

            $post_id = wp_insert_post($args);

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

            wp_update_post([
                'ID'         => $post_id,
                'post_title' => $post_type_object->labels->singular_name . ' #' . $post_id,
                'post_name'  => $post_type_object->labels->singular_name . '-' . $post_id,
            ]);
            jet_abaf()->db->update_booking($booking_id, ['order_id' => $post_id]);
        }else{
            do_action('jet-booking/rest-api/add-booking/set-related-order-data', $order_meta, $booking_id, $booking);
        }
    }
}
