<?php
/**
 * Address Management Handler for WooCommerce Multi Locations Inventory Management
 *
 * @link       http://www.techspawn.com
 * @since      1.0.0
 *
 * @package    Wcmlim
 * @subpackage Wcmlim/includes
 */

/**
 * Address Management Handler
 *
 * Handles user address CRUD operations and nearest location assignment
 *
 * @package    Wcmlim
 * @subpackage Wcmlim/includes
 * @author     techspawn1 <contact@techspawn.com>
 */
class WCMLIM_Address_Manager {
    
    /**
     * Constructor
     */
    public function __construct() {
        // Register AJAX actions for logged-in users only
        add_action('wp_ajax_wcmlim_get_user_addresses', array($this, 'get_user_addresses'));
        add_action('wp_ajax_wcmlim_add_user_address', array($this, 'add_user_address'));
        add_action('wp_ajax_wcmlim_update_user_address', array($this, 'update_user_address'));
        add_action('wp_ajax_wcmlim_delete_user_address', array($this, 'delete_user_address'));
        add_action('wp_ajax_wcmlim_set_default_address', array($this, 'set_default_address'));
        add_action('wp_ajax_wcmlim_select_address', array($this, 'select_address'));
        add_action('wp_ajax_wcmlim_get_selected_address', array($this, 'get_selected_address'));
    }

    /**
     * Get all addresses for current user
     */
    public function get_user_addresses() {
        check_ajax_referer('wcmlim_address_nonce', 'security');
        
        if (!is_user_logged_in()) {
            wp_send_json_error(array('message' => 'User not logged in'));
            return;
        }

        $user_id = get_current_user_id();
        $addresses = get_user_meta($user_id, 'wcmlim_user_addresses', true);
        
        if (empty($addresses) || !is_array($addresses)) {
            $addresses = array();
        }

        // Get currently selected address from cookie
        $selected_address_id = isset($_COOKIE['wcmlim_selected_address_id']) ? sanitize_text_field($_COOKIE['wcmlim_selected_address_id']) : '';

        wp_send_json_success(array(
            'addresses' => $addresses,
            'selected_address_id' => $selected_address_id
        ));
    }

    /**
     * Add new address for current user
     */
    public function add_user_address() {
        check_ajax_referer('wcmlim_address_nonce', 'security');
        
        if (!is_user_logged_in()) {
            wp_send_json_error(array('message' => 'User not logged in'));
            return;
        }

        $user_id = get_current_user_id();
        $addresses = get_user_meta($user_id, 'wcmlim_user_addresses', true);
        
        if (empty($addresses) || !is_array($addresses)) {
            $addresses = array();
        }

        // Generate unique ID for this address
        $address_id = uniqid('addr_', true);

        // Sanitize and prepare address data
        $new_address = array(
            'id' => $address_id,
            'label' => sanitize_text_field($_POST['label']),
            'address_line1' => sanitize_text_field($_POST['address_line1']),
            'address_line2' => sanitize_text_field($_POST['address_line2']),
            'city' => sanitize_text_field($_POST['city']),
            'state' => sanitize_text_field($_POST['state']),
            'country' => sanitize_text_field($_POST['country']),
            'postcode' => sanitize_text_field($_POST['postcode']),
            'latitude' => floatval($_POST['latitude']),
            'longitude' => floatval($_POST['longitude']),
            'is_default' => empty($addresses) ? true : (isset($_POST['is_default']) && $_POST['is_default'] === 'true'),
            'created_at' => current_time('mysql')
        );

        // If this is set as default, remove default from other addresses
        if ($new_address['is_default']) {
            foreach ($addresses as $key => $address) {
                $addresses[$key]['is_default'] = false;
            }
        }

        // Add new address to array
        $addresses[$address_id] = $new_address;

        // Save to user meta
        update_user_meta($user_id, 'wcmlim_user_addresses', $addresses);

        // Find nearest location and set cookie
        $nearest_location = $this->find_nearest_location($new_address['latitude'], $new_address['longitude']);

        if ($nearest_location) {
            $this->set_location_cookie($nearest_location, $address_id);
        }

        wp_send_json_success(array(
            'message' => 'Address added successfully',
            'address' => $new_address,
            'nearest_location' => $nearest_location
        ));
    }

    /**
     * Update existing address
     */
    public function update_user_address() {
        check_ajax_referer('wcmlim_address_nonce', 'security');
        
        if (!is_user_logged_in()) {
            wp_send_json_error(array('message' => 'User not logged in'));
            return;
        }

        $user_id = get_current_user_id();
        $address_id = sanitize_text_field($_POST['address_id']);
        $addresses = get_user_meta($user_id, 'wcmlim_user_addresses', true);

        if (empty($addresses) || !isset($addresses[$address_id])) {
            wp_send_json_error(array('message' => 'Address not found'));
            return;
        }

        // Update address data
        $addresses[$address_id]['label'] = sanitize_text_field($_POST['label']);
        $addresses[$address_id]['address_line1'] = sanitize_text_field($_POST['address_line1']);
        $addresses[$address_id]['address_line2'] = sanitize_text_field($_POST['address_line2']);
        $addresses[$address_id]['city'] = sanitize_text_field($_POST['city']);
        $addresses[$address_id]['state'] = sanitize_text_field($_POST['state']);
        $addresses[$address_id]['country'] = sanitize_text_field($_POST['country']);
        $addresses[$address_id]['postcode'] = sanitize_text_field($_POST['postcode']);
        $addresses[$address_id]['latitude'] = floatval($_POST['latitude']);
        $addresses[$address_id]['longitude'] = floatval($_POST['longitude']);
        $addresses[$address_id]['updated_at'] = current_time('mysql');

        // If this is set as default, remove default from other addresses
        if (isset($_POST['is_default']) && $_POST['is_default'] === 'true') {
            foreach ($addresses as $key => $address) {
                $addresses[$key]['is_default'] = ($key === $address_id);
            }
        }

        // Save to user meta
        update_user_meta($user_id, 'wcmlim_user_addresses', $addresses);

        wp_send_json_success(array(
            'message' => 'Address updated successfully',
            'address' => $addresses[$address_id]
        ));
    }

    /**
     * Delete address
     */
    public function delete_user_address() {
        check_ajax_referer('wcmlim_address_nonce', 'security');
        
        if (!is_user_logged_in()) {
            wp_send_json_error(array('message' => 'User not logged in'));
            return;
        }

        $user_id = get_current_user_id();
        $address_id = sanitize_text_field($_POST['address_id']);
        $addresses = get_user_meta($user_id, 'wcmlim_user_addresses', true);

        if (empty($addresses) || !isset($addresses[$address_id])) {
            wp_send_json_error(array('message' => 'Address not found'));
            return;
        }

        // Remove address
        unset($addresses[$address_id]);

        // If there are remaining addresses and none is default, set first as default
        if (!empty($addresses)) {
            $has_default = false;
            foreach ($addresses as $address) {
                if ($address['is_default']) {
                    $has_default = true;
                    break;
                }
            }
            if (!$has_default) {
                $first_key = array_key_first($addresses);
                $addresses[$first_key]['is_default'] = true;
            }
        }

        // Save to user meta
        update_user_meta($user_id, 'wcmlim_user_addresses', $addresses);

        wp_send_json_success(array('message' => 'Address deleted successfully'));
    }

    /**
     * Set default address
     */
    public function set_default_address() {
        check_ajax_referer('wcmlim_address_nonce', 'security');
        
        if (!is_user_logged_in()) {
            wp_send_json_error(array('message' => 'User not logged in'));
            return;
        }

        $user_id = get_current_user_id();
        $address_id = sanitize_text_field($_POST['address_id']);
        $addresses = get_user_meta($user_id, 'wcmlim_user_addresses', true);

        if (empty($addresses) || !isset($addresses[$address_id])) {
            wp_send_json_error(array('message' => 'Address not found'));
            return;
        }

        // Set all addresses as non-default
        foreach ($addresses as $key => $address) {
            $addresses[$key]['is_default'] = ($key === $address_id);
        }

        // Save to user meta
        update_user_meta($user_id, 'wcmlim_user_addresses', $addresses);

        wp_send_json_success(array('message' => 'Default address updated'));
    }

    /**
     * Select an address and set nearest location cookie
     */
    public function select_address() {
        check_ajax_referer('wcmlim_address_nonce', 'security');
        
        if (!is_user_logged_in()) {
            wp_send_json_error(array('message' => 'User not logged in'));
            return;
        }

        $user_id = get_current_user_id();
        $address_id = sanitize_text_field($_POST['address_id']);
        $addresses = get_user_meta($user_id, 'wcmlim_user_addresses', true);

        if (empty($addresses) || !isset($addresses[$address_id])) {
            wp_send_json_error(array('message' => 'Address not found'));
            return;
        }

        $selected_address = $addresses[$address_id];

        // Check if coordinates exist
        if (empty($selected_address['latitude']) || empty($selected_address['longitude'])) {
            wp_send_json_error(array('message' => 'Address is missing location coordinates'));
            return;
        }

        // Find nearest location
        $nearest_location = $this->find_nearest_location($selected_address['latitude'], $selected_address['longitude']);

        if ($nearest_location) {
            $this->set_location_cookie($nearest_location, $address_id);
            
            // Get the location index for the response
            $all_locations = get_terms(array(
                'taxonomy' => 'locations',
                'hide_empty' => false,
                'parent' => 0
            ));
            
            $location_index = null;
            foreach ($all_locations as $key => $term) {
                if ($term->term_id == $nearest_location['term_id']) {
                    $location_index = $key;
                    break;
                }
            }
            
            wp_send_json_success(array(
                'message' => 'Address selected successfully. Nearest location: ' . $nearest_location['location_name'],
                'address' => $selected_address,
                'location' => array(
                    'name' => $nearest_location['location_name'],
                    'key' => $nearest_location['location_key'],
                    'term_id' => $nearest_location['term_id'],
                    'index' => $location_index,
                    'distance' => $nearest_location['distance']
                )
            ));
        } else {
            wp_send_json_error(array('message' => 'No location found nearby'));
        }
    }

    /**
     * Get currently selected address
     */
    public function get_selected_address() {
        check_ajax_referer('wcmlim_address_nonce', 'security');
        
        if (!is_user_logged_in()) {
            wp_send_json_error(array('message' => 'User not logged in'));
            return;
        }

        $user_id = get_current_user_id();
        $addresses = get_user_meta($user_id, 'wcmlim_user_addresses', true);
        
        if (empty($addresses)) {
            wp_send_json_success(array('address' => null));
            return;
        }

        $selected_address_id = isset($_COOKIE['wcmlim_selected_address_id']) ? sanitize_text_field($_COOKIE['wcmlim_selected_address_id']) : '';

        if ($selected_address_id && isset($addresses[$selected_address_id])) {
            wp_send_json_success(array('address' => $addresses[$selected_address_id]));
        } else {
            // Return default address if available
            foreach ($addresses as $address) {
                if ($address['is_default']) {
                    wp_send_json_success(array('address' => $address));
                    return;
                }
            }
            // Return first address if no default
            wp_send_json_success(array('address' => reset($addresses)));
        }
    }

    /**
     * Find nearest location based on coordinates using Haversine formula
     *
     * @param float $lat User latitude
     * @param float $lng User longitude
     * @return array|null Location data with term_id and location_key
     */
    private function find_nearest_location($lat, $lng) {
        // Get all location terms
        $terms = get_terms(array(
            'taxonomy' => 'locations',
            'hide_empty' => false,
        ));

        if (empty($terms) || is_wp_error($terms)) {
            return null;
        }

        $nearest_location = null;
        $min_distance = PHP_FLOAT_MAX;

        foreach ($terms as $term) {
            // Get location coordinates from term meta (separate keys: wcmlim_lat and wcmlim_lng)
            $loc_lat = get_term_meta($term->term_id, 'wcmlim_lat', true);
            $loc_lng = get_term_meta($term->term_id, 'wcmlim_lng', true);
            
            // Skip if coordinates are not set or are zero
            if (empty($loc_lat) || empty($loc_lng) || $loc_lat == 0 || $loc_lng == 0) {
                continue;
            }
            
            $loc_lat = floatval($loc_lat);
            $loc_lng = floatval($loc_lng);
            
            // Calculate distance using Haversine formula
            $distance = $this->calculate_distance($lat, $lng, $loc_lat, $loc_lng);
            
            if ($distance < $min_distance) {
                $min_distance = $distance;
                $nearest_location = array(
                    'term_id' => $term->term_id,
                    'location_key' => $term->slug,
                    'location_name' => $term->name,
                    'distance' => round($distance, 2)
                );
            }
        }

        return $nearest_location;
    }    /**
     * Calculate distance between two points using Haversine formula
     *
     * @param float $lat1 Latitude of point 1
     * @param float $lng1 Longitude of point 1
     * @param float $lat2 Latitude of point 2
     * @param float $lng2 Longitude of point 2
     * @return float Distance in kilometers
     */
    private function calculate_distance($lat1, $lng1, $lat2, $lng2) {
        $earth_radius = 6371; // Earth radius in kilometers

        $dLat = deg2rad($lat2 - $lat1);
        $dLng = deg2rad($lng2 - $lng1);

        $a = sin($dLat / 2) * sin($dLat / 2) +
             cos(deg2rad($lat1)) * cos(deg2rad($lat2)) *
             sin($dLng / 2) * sin($dLng / 2);

        $c = 2 * atan2(sqrt($a), sqrt(1 - $a));
        $distance = $earth_radius * $c;

        return $distance;
    }

    /**
     * Set location cookies
     *
     * @param array $location Location data
     * @param string $address_id Address ID
     */
    private function set_location_cookie($location, $address_id) {
        $expire_days = get_option('wcmlim_set_location_cookie_time', 30);
        $expire = time() + (intval($expire_days) * 24 * 60 * 60);

        // Get all locations to find the array index key
        $all_locations = get_terms(array(
            'taxonomy' => 'locations',
            'hide_empty' => false,
            'parent' => 0
        ));

        $location_index = null;
        foreach ($all_locations as $key => $term) {
            if ($term->term_id == $location['term_id']) {
                $location_index = $key;
                break;
            }
        }

        if ($location_index === null) {
            return;
        }

        // Use the helper function if available, otherwise set directly
        if (function_exists('setLocation')) {
            setLocation("wcmlim_selected_location", $location_index, $expire);
            setLocation("wcmlim_selected_location_termid", $location['term_id'], $expire);
        } else {
            setcookie('wcmlim_selected_location', $location_index, $expire, '/');
            setcookie('wcmlim_selected_location_termid', $location['term_id'], $expire, '/');
        }

        // Set address ID cookie
        setcookie('wcmlim_selected_address_id', $address_id, $expire, '/');
    }
}

// Initialize the address manager
new WCMLIM_Address_Manager();
