#pragma once

#include <string>
#include <vector>
#include <memory>
#include <map>
#include <unordered_set>
#include <utility>
#include "gumbo.h"

namespace cutysoup {

class FastNode;

/**
 * FastTree - A minimal, high-performance HTML tree implementation
 * Focused on actual speed over theoretical optimizations
 */
class FastTree : public std::enable_shared_from_this<FastTree> {
    friend class FastNode;
public:
    explicit FastTree(const std::string& html);
    ~FastTree();
    
    // Core tree access
    std::shared_ptr<FastNode> get_root() const;
    const GumboOutput* get_gumbo_output() const { return output_; }
    
    // Fast element creation for manipulation
    std::shared_ptr<FastNode> create_element(const std::string& tag_name, 
                                           const std::map<std::string, std::string>& attributes = {});
    
    // Performance-focused methods
    std::vector<std::shared_ptr<FastNode>> find_all_by_tag(const std::string& tag_name) const;
    std::vector<std::shared_ptr<FastNode>> find_all_by_class(const std::string& class_name) const;
    std::vector<std::shared_ptr<FastNode>> find_all_by_id(const std::string& id) const;
    
    // MaxCpp Phase 35: C++ bulk find operations
    std::vector<std::shared_ptr<FastNode>> bulk_find_all(const std::string& name = "", 
                                                        const std::map<std::string, std::string>& attrs = {},
                                                        bool recursive = true) const;
    std::shared_ptr<FastNode> bulk_find(const std::string& name = "",
                                       const std::map<std::string, std::string>& attrs = {},
                                       bool recursive = true) const;
    std::vector<std::shared_ptr<FastNode>> bulk_find_all_strings() const;
    std::vector<std::shared_ptr<FastNode>> bulk_find_parents(const std::shared_ptr<FastNode>& node,
                                                           const std::string& name = "",
                                                           const std::map<std::string, std::string>& attrs = {}) const;
    
    // CSS selector support (single-threaded, optimized) - MaxCpp Phase 34
    std::vector<std::shared_ptr<FastNode>> select(const std::string& css_selector) const;
    std::shared_ptr<FastNode> select_one(const std::string& css_selector) const;
    
    // Advanced CSS selector methods
    std::vector<std::shared_ptr<FastNode>> select_by_complex_selector(const std::string& css_selector) const;
    bool matches_css_selector(const std::shared_ptr<FastNode>& node, const std::string& selector) const;
    
    // Bulk text extraction (zero Python overhead)
    std::vector<std::string> extract_all_text_by_tag(const std::string& tag_name) const;
    std::vector<std::string> extract_all_hrefs() const;
    std::vector<std::string> extract_all_src() const;
    
    // Advanced indexing methods for large documents
    std::vector<std::shared_ptr<FastNode>> find_by_attribute(const std::string& attr_name, const std::string& value) const;
    std::vector<std::shared_ptr<FastNode>> find_by_text_content(const std::string& text) const;
    std::shared_ptr<FastNode> get_nth_element(size_t index) const;
    
    // Statistics and performance metrics
    size_t get_node_count() const { return node_count_; }
    size_t get_indexed_node_count() const { return indexed_node_count_; }
    double get_index_build_time() const { return index_build_time_; }
    bool are_indexes_built() const { return indexes_built_; }
    
private:
    GumboOutput* output_;
    mutable std::shared_ptr<FastNode> root_node_;
    size_t node_count_;
    
    // Pre-built indexes for common queries (built on demand)
    mutable std::map<std::string, std::vector<GumboNode*>> tag_index_;
    mutable std::map<std::string, std::vector<GumboNode*>> class_index_;
    mutable std::map<std::string, GumboNode*> id_index_;
    
    // Advanced indexing features for large documents
    mutable std::map<std::string, std::vector<GumboNode*>> attribute_index_;  // attr=value pairs
    mutable std::map<std::string, std::vector<GumboNode*>> text_index_;       // text content
    mutable std::vector<GumboNode*> all_elements_;                            // All elements for nth operations
    
    mutable bool indexes_built_ = false;
    mutable size_t indexed_node_count_ = 0;
    mutable double index_build_time_ = 0.0;
    
    void build_indexes() const;
    void build_indexes_recursive(GumboNode* node) const;
    
    // Helper methods
    std::shared_ptr<FastNode> create_node_wrapper(GumboNode* node) const;
    bool node_matches_selector(GumboNode* node, const std::string& selector) const;
    void count_nodes_recursive(GumboNode* node);
    std::vector<std::shared_ptr<FastNode>> select_complex(const std::string& css_selector) const;
    
    // MaxCpp Phase 34: Advanced CSS selector helpers
    struct SelectorPart {
        std::string tag;
        std::string id;
        std::vector<std::string> classes;
        std::map<std::string, std::pair<std::string, std::string>> attrs;  // attr_name -> (operator, value)
        std::string pseudo;
        std::string combinator = "descendant";
    };
    
    std::vector<SelectorPart> parse_css_selector(const std::string& selector) const;
    SelectorPart parse_simple_selector(const std::string& selector) const;
    bool matches_selector_part(const std::shared_ptr<FastNode>& node, const SelectorPart& part) const;
    bool matches_attribute(const std::shared_ptr<FastNode>& node, const std::string& attr_name, 
                          const std::string& op, const std::string& value) const;
    bool matches_pseudo(const std::shared_ptr<FastNode>& node, const std::string& pseudo) const;
    bool matches_complex_selector(const std::shared_ptr<FastNode>& node, const std::vector<SelectorPart>& parts) const;
};

/**
 * FastNode - Minimal node wrapper focused on performance
 */
class FastNode {
public:
    explicit FastNode(GumboNode* node, std::weak_ptr<FastTree> tree);
    
    // Core properties
    std::string get_name() const;
    std::string get_text() const;
    std::map<std::string, std::string> get_attributes() const;
    std::string get_attribute(const std::string& name) const;
    bool has_attribute(const std::string& name) const;
    
    // Advanced C++ text processing methods (MaxCpp Phase 32)
    std::string get_text_with_separator(const std::string& separator) const;
    std::string get_text_stripped() const;
    std::string get_text_with_separator_stripped(const std::string& separator) const;
    std::vector<std::string> get_strings() const;
    std::vector<std::string> get_stripped_strings() const;
    std::string get_direct_text() const;
    
    // Navigation
    std::shared_ptr<FastNode> get_parent() const;
    std::vector<std::shared_ptr<FastNode>> get_children() const;
    std::shared_ptr<FastNode> get_next_sibling() const;
    std::shared_ptr<FastNode> get_previous_sibling() const;
    
    // Type checking
    bool is_text() const;
    bool is_element() const;
    
    // Fast searches from this node
    std::vector<std::shared_ptr<FastNode>> find_descendants_by_tag(const std::string& tag_name) const;
    std::vector<std::shared_ptr<FastNode>> select(const std::string& css_selector) const;
    std::shared_ptr<FastNode> select_one(const std::string& css_selector) const;
    
    // MaxCpp Phase 35: Node-scoped C++ bulk find operations
    std::vector<std::shared_ptr<FastNode>> node_find_all(const std::string& name = "",
                                                        const std::map<std::string, std::string>& attrs = {},
                                                        bool recursive = true) const;
    std::shared_ptr<FastNode> node_find(const std::string& name = "",
                                       const std::map<std::string, std::string>& attrs = {},
                                       bool recursive = true) const;
    
    // MaxCpp Phase 33: C++ Tree Navigation Bulk Operations
    std::vector<std::shared_ptr<FastNode>> get_all_descendants() const;
    std::vector<std::shared_ptr<FastNode>> get_all_descendants_with_text() const;
    std::vector<std::shared_ptr<FastNode>> get_all_parents() const;
    std::vector<std::shared_ptr<FastNode>> get_all_next_siblings() const;
    std::vector<std::shared_ptr<FastNode>> get_all_previous_siblings() const;
    std::vector<std::shared_ptr<FastNode>> get_all_next_siblings_including_text() const;
    std::vector<std::shared_ptr<FastNode>> get_all_previous_siblings_including_text() const;
    
    // Direct access to underlying node (for advanced usage)
    GumboNode* get_gumbo_node() const { return node_; }
    
private:
    GumboNode* node_;
    std::weak_ptr<FastTree> tree_;
    
    void collect_descendants_by_tag(GumboNode* node, const std::string& tag_name, 
                                   std::vector<std::shared_ptr<FastNode>>& results) const;
    void extract_text_recursive(GumboNode* node, std::string& result) const;
    
    // MaxCpp Phase 32: Text processing helpers
    void collect_text_parts(GumboNode* node, std::vector<std::string>& parts) const;
    void collect_strings_recursive(GumboNode* node, std::vector<std::string>& strings) const;
    
    // MaxCpp Phase 33: Navigation helpers
    void collect_all_descendants(GumboNode* node, std::vector<std::shared_ptr<FastNode>>& descendants) const;
    void collect_all_descendants_with_text(GumboNode* node, std::vector<std::shared_ptr<FastNode>>& descendants) const;
};

} // namespace cutysoup
