import logging

from flask import Blueprint, request
from flask_jwt_extended import jwt_required
from median.models import Product, Ucd, Cip

suggestions_blueprint = Blueprint("suggestions", __name__)

logger = logging.getLogger("median")


@suggestions_blueprint.route("", methods=["GET"])
@jwt_required()
def get_all():
    args = request.args
    search_query = args["q"].strip()

    try:
        # Split search query into individual terms for AND search
        search_terms = [term for term in search_query.split() if term.strip()]

        if not search_terms:
            return []

        # Get all matching products in one efficient query using UNION

        if len(search_terms) == 1:
            # Single term: search across all fields
            term = search_terms[0]
            combined_condition = (
                Product.reference.contains(term)
                | Product.designation.contains(term)
                | Product.ucd.contains(term)
                | Product.cip.contains(term)
            )
        else:
            # Multiple terms: search only in designation field with AND logic
            designation_conditions = [Product.designation.contains(term) for term in search_terms]
            combined_condition = designation_conditions[0]
            for condition in designation_conditions[1:]:
                combined_condition &= condition

        product_query = Product.select(
            Product.pk, Product.reference, Product.designation, Product.ucd, Product.cip
        ).where(combined_condition)

        # For UCD and CIP searches, only include them for single term searches
        if len(search_terms) == 1:
            term = search_terms[0]
            ucd_query = (
                Product.select(Product.pk, Product.reference, Product.designation, Product.ucd, Product.cip)
                .join(Ucd, on=(Product.reference == Ucd.reference))
                .where(Ucd.ucd.contains(term))
            )

            cip_query = (
                Product.select(Product.pk, Product.reference, Product.designation, Product.ucd, Product.cip)
                .join(Ucd, on=(Product.reference == Ucd.reference))
                .join(Cip, on=(Ucd.ucd == Cip.ucd))
                .where(Cip.cip.contains(term))
            )

            combined_query = product_query.union(ucd_query).union(cip_query)
        else:
            # Multiple terms: only search products directly
            combined_query = product_query

        results = []
        seen_pks = set()

        for p in combined_query:
            # Skip duplicates
            if p.pk in seen_pks:
                continue
            seen_pks.add(p.pk)

            # Determine the best UCD value (prefer Product.ucd, fallback to Ucd table)
            ucd_value = p.ucd
            if not ucd_value:
                ucd_data = Ucd.get_or_none(Ucd.reference == p.reference)
                if ucd_data:
                    ucd_value = ucd_data.ucd

            # Build display text with available codes
            codes = []
            if p.reference:
                codes.append(p.reference)
            # if p.cip:
            #     codes.append(p.cip)
            if ucd_value:
                codes.append(ucd_value)

            code_text = " / ".join(codes) if codes else "No codes"

            results.append(
                {
                    "cdu": ucd_value,
                    "value": p.pk,
                    "text": f"[{code_text}] {p.designation or 'No designation'}",
                    "designation": p.designation,
                }
            )

        logger.info(f"Found {len(results)} unique product suggestions")
        return results

    except Exception as error:
        logger.error(f"Error in suggestions: {error}")
        return {"message": str(error)}, 400
