<?php
/**
 * Google Product Feed Generator
 *
 * Generates Google-compatible XML product feeds with location data.
 *
 * @package    Wcmlim
 * @subpackage Wcmlim/includes
 * @since      1.0.0
 */

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

/**
 * Class WCMLIM_Feed_Generator
 *
 * Handles generation of Google-compatible product feeds.
 */
class WCMLIM_Feed_Generator {

    /**
     * Feed namespace.
     *
     * @var string
     */
    const GOOGLE_NS = 'http://base.google.com/ns/1.0';

    /**
     * Atom namespace.
     *
     * @var string
     */
    const ATOM_NS = 'http://www.w3.org/2005/Atom';

    /**
     * CTX Feed Integration instance.
     *
     * @var WCMLIM_CTX_Feed_Integration
     */
    private $ctx_integration;

    /**
     * Whether feed generation is enabled.
     *
     * @var bool
     */
    private $is_enabled;

    /**
     * Constructor.
     */
    public function __construct() {
        $this->is_enabled = get_option('wcmlim_enable_ctx_feed') === 'on';
        
        if ($this->is_enabled) {
            $this->init_hooks();
        }
    }

    /**
     * Set CTX Integration instance.
     *
     * @param WCMLIM_CTX_Feed_Integration $integration Integration instance.
     */
    public function set_ctx_integration($integration) {
        $this->ctx_integration = $integration;
    }

    /**
     * Initialize hooks.
     */
    private function init_hooks() {
        add_action('init', array($this, 'register_feed_endpoint'));
        add_action('template_redirect', array($this, 'handle_feed_request'));
        add_action('wp_ajax_wcmlim_generate_feed', array($this, 'ajax_generate_feed'));
        add_action('wp_ajax_nopriv_wcmlim_generate_feed', array($this, 'ajax_generate_feed'));
    }

    /**
     * Register the feed endpoint.
     */
    public function register_feed_endpoint() {
        add_rewrite_rule(
            '^wcmlim-feed/?$',
            'index.php?wcmlim_feed=1',
            'top'
        );
        
        add_rewrite_rule(
            '^wcmlim-feed/([^/]+)/?$',
            'index.php?wcmlim_feed=1&wcmlim_feed_type=$matches[1]',
            'top'
        );

        add_rewrite_tag('%wcmlim_feed%', '([0-9]+)');
        add_rewrite_tag('%wcmlim_feed_type%', '([^&]+)');
    }

    /**
     * Handle feed request.
     */
    public function handle_feed_request() {
        global $wp_query;

        if (!isset($wp_query->query_vars['wcmlim_feed'])) {
            return;
        }

        if (!$this->is_enabled) {
            wp_die(
                esc_html__('Feed generation is disabled.', 'wcmlim'),
                esc_html__('Feed Disabled', 'wcmlim'),
                array('response' => 403)
            );
        }

        $feed_type = isset($wp_query->query_vars['wcmlim_feed_type']) 
            ? sanitize_text_field($wp_query->query_vars['wcmlim_feed_type']) 
            : 'google';

        $this->output_feed($feed_type);
        exit;
    }

    /**
     * AJAX handler for feed generation.
     */
    public function ajax_generate_feed() {
        if (!$this->is_enabled) {
            wp_send_json_error(array('message' => 'Feed generation is disabled.'));
        }

        $feed_type = isset($_GET['type']) ? sanitize_text_field($_GET['type']) : 'google';
        
        $this->output_feed($feed_type);
        exit;
    }

    /**
     * Output the feed.
     *
     * @param string $type Feed type (google, local_inventory).
     */
    public function output_feed($type = 'google') {
        // Set headers
        header('Content-Type: application/xml; charset=utf-8');
        header('Cache-Control: no-cache, no-store, must-revalidate');
        header('Pragma: no-cache');
        header('Expires: 0');

        switch ($type) {
            case 'local_inventory':
                echo $this->generate_local_inventory_feed();
                break;
            case 'google':
            default:
                echo $this->generate_google_feed();
                break;
        }
    }

    /**
     * Generate Google Shopping feed XML.
     *
     * @return string XML feed content.
     */
    public function generate_google_feed() {
        if (!$this->ctx_integration) {
            $this->ctx_integration = new WCMLIM_CTX_Feed_Integration();
        }

        $products = $this->ctx_integration->get_products_for_feed();
        $site_name = get_bloginfo('name');
        $site_url = home_url();
        $currency = get_woocommerce_currency();

        $xml = new DOMDocument('1.0', 'UTF-8');
        $xml->formatOutput = true;

        // Create RSS root element
        $rss = $xml->createElement('rss');
        $rss->setAttribute('version', '2.0');
        $rss->setAttribute('xmlns:g', self::GOOGLE_NS);
        $xml->appendChild($rss);

        // Create channel
        $channel = $xml->createElement('channel');
        $rss->appendChild($channel);

        // Add channel info
        $channel->appendChild($xml->createElement('title', $this->escape_xml($site_name)));
        $channel->appendChild($xml->createElement('link', esc_url($site_url)));
        $channel->appendChild($xml->createElement('description', $this->escape_xml(get_bloginfo('description'))));

        // Add products
        foreach ($products as $product_data) {
            $item = $xml->createElement('item');
            
            // Basic product info
            $item->appendChild($this->create_element($xml, 'g:id', $product_data['id'] . '_' . $product_data['location_id']));
            $item->appendChild($this->create_element($xml, 'g:title', $product_data['title']));
            $item->appendChild($this->create_element($xml, 'g:description', $product_data['description']));
            $item->appendChild($this->create_element($xml, 'g:link', $product_data['link']));
            
            // Image
            if (!empty($product_data['image_link'])) {
                $item->appendChild($this->create_element($xml, 'g:image_link', $product_data['image_link']));
            }
            
            // Price
            if (!empty($product_data['price'])) {
                $price_formatted = number_format((float) $product_data['price'], 2, '.', '') . ' ' . $currency;
                $item->appendChild($this->create_element($xml, 'g:price', $price_formatted));
            }
            
            // Availability
            $item->appendChild($this->create_element($xml, 'g:availability', $product_data['availability']));
            
            // Store code
            if (!empty($product_data['store_code'])) {
                $item->appendChild($this->create_element($xml, 'g:store_code', $product_data['store_code']));
            }
            
            // Quantity
            $item->appendChild($this->create_element($xml, 'g:quantity', (string) $product_data['quantity']));
            
            // Identifiers
            if (!empty($product_data['gtin'])) {
                $item->appendChild($this->create_element($xml, 'g:gtin', $product_data['gtin']));
            }
            
            if (!empty($product_data['mpn'])) {
                $item->appendChild($this->create_element($xml, 'g:mpn', $product_data['mpn']));
            }
            
            if (!empty($product_data['brand'])) {
                $item->appendChild($this->create_element($xml, 'g:brand', $product_data['brand']));
            }
            
            // Condition
            $item->appendChild($this->create_element($xml, 'g:condition', $product_data['condition']));
            
            $channel->appendChild($item);
        }

        return $xml->saveXML();
    }

    /**
     * Generate Local Inventory feed for Google.
     *
     * @return string XML feed content.
     */
    public function generate_local_inventory_feed() {
        if (!$this->ctx_integration) {
            $this->ctx_integration = new WCMLIM_CTX_Feed_Integration();
        }

        $products = $this->ctx_integration->get_products_for_feed();
        $currency = get_woocommerce_currency();

        $xml = new DOMDocument('1.0', 'UTF-8');
        $xml->formatOutput = true;

        // Create feed root element
        $feed = $xml->createElementNS(self::ATOM_NS, 'feed');
        $feed->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:g', self::GOOGLE_NS);
        $xml->appendChild($feed);

        // Add feed title
        $title = $xml->createElement('title', $this->escape_xml(get_bloginfo('name') . ' Local Product Inventory'));
        $feed->appendChild($title);

        // Add updated timestamp
        $updated = $xml->createElement('updated', gmdate('Y-m-d\TH:i:s\Z'));
        $feed->appendChild($updated);

        // Add entries
        foreach ($products as $product_data) {
            $entry = $xml->createElement('entry');
            
            // Required fields
            $entry->appendChild($this->create_element($xml, 'g:itemid', (string) $product_data['id']));
            $entry->appendChild($this->create_element($xml, 'g:store_code', $product_data['store_code']));
            $entry->appendChild($this->create_element($xml, 'g:quantity', (string) $product_data['quantity']));
            $entry->appendChild($this->create_element($xml, 'g:availability', $product_data['availability']));
            
            // Optional price override
            if (!empty($product_data['price'])) {
                $price_formatted = number_format((float) $product_data['price'], 2, '.', '') . ' ' . $currency;
                $entry->appendChild($this->create_element($xml, 'g:price', $price_formatted));
            }
            
            $feed->appendChild($entry);
        }

        return $xml->saveXML();
    }

    /**
     * Create XML element with CDATA for text content.
     *
     * @param DOMDocument $xml   XML document.
     * @param string      $name  Element name.
     * @param string      $value Element value.
     * @return DOMElement
     */
    private function create_element($xml, $name, $value) {
        $element = $xml->createElement($name);
        
        // Use CDATA for text that might contain special characters
        if (preg_match('/[<>&\'"]/', $value)) {
            $cdata = $xml->createCDATASection($value);
            $element->appendChild($cdata);
        } else {
            $element->nodeValue = $this->escape_xml($value);
        }
        
        return $element;
    }

    /**
     * Escape XML special characters.
     *
     * @param string $string String to escape.
     * @return string Escaped string.
     */
    private function escape_xml($string) {
        return htmlspecialchars(strip_tags($string), ENT_XML1, 'UTF-8');
    }

    /**
     * Get feed URL.
     *
     * @param string $type Feed type.
     * @return string Feed URL.
     */
    public static function get_feed_url($type = 'google') {
        $base_url = home_url('/wcmlim-feed/');
        
        if ($type !== 'google') {
            $base_url .= $type . '/';
        }
        
        return $base_url;
    }

    /**
     * Flush rewrite rules.
     * Should be called on plugin activation.
     */
    public static function flush_rewrite_rules() {
        $instance = new self();
        $instance->register_feed_endpoint();
        flush_rewrite_rules();
    }
}
