import logging

from odoo.http import request

_logger = logging.getLogger(__name__)


def _build_category_hierarchy(self, categories):
    if not categories:
        return []
    category_map = {}
    for cat in categories:
        category_map[cat.id] = {
            "id": cat.id,
            "name": cat.name,
            "sequence": cat.sequence,
            "parent_id": cat.parent_id.id if cat.parent_id else None,
            "children": [],
        }
    roots = []
    for _cat_id, cat_info in category_map.items():
        parent_id = cat_info["parent_id"]
        if parent_id is None or parent_id not in category_map:
            roots.append(cat_info)
        else:
            category_map[parent_id]["children"].append(cat_info)

    def sort_hierarchy(items):
        items.sort(key=lambda x: (x["sequence"], x["name"]))
        for item in items:
            if item["children"]:
                sort_hierarchy(item["children"])

    sort_hierarchy(roots)
    return roots


def _filter_published_tags(self, tags):
    return tags.filtered(lambda t: getattr(t, "visible_on_ecommerce", True))


def _filter_products(self, all_products, post, group_order):
    search_query = post.get("search", "").strip()
    category_filter = post.get("category", "0")
    filtered_products = all_products
    if search_query:
        filtered_products = filtered_products.filtered(
            lambda p: search_query.lower() in p.name.lower()
            or search_query.lower() in (p.description or "").lower()
        )
        _logger.info(
            'Filter: search "%s" - found %d of %d',
            search_query,
            len(filtered_products),
            len(all_products),
        )

    if category_filter != "0":
        try:
            category_id = int(category_filter)
            selected_category = (
                request.env["product.category"].sudo().browse(category_id)
            )
            if selected_category.exists():
                all_category_ids = [category_id]

                def get_all_children(category):
                    for child in category.child_id:
                        all_category_ids.append(child.id)
                        get_all_children(child)

                get_all_children(selected_category)

                products_in_categories = filtered_products.filtered(
                    lambda p: p.categ_id.id in all_category_ids
                )
                filtered_products = products_in_categories
                _logger.info(
                    "Filter: category %d - found %d of %d total",
                    category_id,
                    len(filtered_products),
                    len(all_products),
                )
        except (ValueError, TypeError) as e:
            _logger.warning("Filter: invalid category filter: %s", str(e))

    available_tags_dict = {}
    for product in filtered_products:
        for tag in product.product_tag_ids:
            is_visible = getattr(tag, "visible_on_ecommerce", True)
            if not is_visible:
                continue
            if tag.id not in available_tags_dict:
                tag_color = tag.color if tag.color else None
                available_tags_dict[tag.id] = {
                    "id": tag.id,
                    "name": tag.name,
                    "color": tag_color,
                    "count": 0,
                }
            available_tags_dict[tag.id]["count"] += 1

    available_tags = sorted(available_tags_dict.values(), key=lambda t: t["name"])
    _logger.info(
        "Filter: found %d available tags for %d filtered products",
        len(available_tags),
        len(filtered_products),
    )
    return filtered_products, available_tags, search_query, category_filter


def _collect_all_products_and_categories(self, group_order):
    all_products = group_order._get_products_for_group_order(group_order.id)
    product_categories = all_products.mapped("categ_id").filtered(lambda c: c.id > 0)
    all_categories_set = set()

    def collect_category_and_parents(category):
        if category and category.id > 0:
            all_categories_set.add(category.id)
            if category.parent_id:
                collect_category_and_parents(category.parent_id)

    for cat in product_categories:
        collect_category_and_parents(cat)

    available_categories = (
        request.env["product.category"].sudo().browse(list(all_categories_set))
    )
    available_categories = sorted(
        set(available_categories), key=lambda c: (c.sequence, c.name)
    )

    category_hierarchy = _build_category_hierarchy(self, available_categories)
    return all_products, available_categories, category_hierarchy


def _prepare_products_maps(self, products, pricelist):
    product_price_info = self._compute_price_info(products, pricelist)
    product_supplier_info = self._get_product_supplier_info(products)

    product_display_info = {}
    filtered_products_dict = {}
    for product in products:
        product_display_info[product.id] = self._prepare_product_display_info(
            product, product_price_info
        )
        filtered_products_dict[product.id] = {
            "product": product,
            "published_tags": self._filter_published_tags(product.product_tag_ids),
        }

    return (
        product_price_info,
        product_supplier_info,
        product_display_info,
        filtered_products_dict,
    )
