# /home/Autopartes/pos/blueprints/chat_bp.py
"""Chat blueprint: AI-powered parts lookup via natural language.

Endpoints (all under /pos/api/chat):
  POST /  — send a message, get AI response + catalog search results
"""

from flask import Blueprint, request, jsonify, g
from middleware import require_auth
from tenant_db import get_master_conn, get_tenant_conn
from services import catalog_service, ai_chat

chat_bp = Blueprint("chat", __name__, url_prefix="/pos/api/chat")


@chat_bp.route("", methods=["POST"])
@require_auth("catalog.view")
def chat():
    body = request.get_json(force=True)
    user_message = (body.get("message") or "").strip()
    if not user_message:
        return jsonify({"error": "message required"}), 400

    history = body.get("history") or []

    # Fetch inventory context so the AI knows what this tenant has in stock
    inventory_context = None
    tenant_for_context = None
    try:
        tenant_for_context = get_tenant_conn(g.tenant_id)
        inventory_context = ai_chat.get_inventory_context(tenant_for_context, g.branch_id)
    except Exception:
        pass
    finally:
        if tenant_for_context:
            try:
                tenant_for_context.close()
            except Exception:
                pass

    # Check for image (base64) — use vision model if present
    image_base64 = (body.get("image") or "").strip()

    if image_base64:
        ai_response = ai_chat.chat_with_image(user_message, image_base64, history, inventory_context=inventory_context)
    else:
        ai_response = ai_chat.chat(user_message, history, inventory_context=inventory_context)

    search_results = []
    vehicle_match = None

    master = None
    tenant = None
    try:
        # If AI suggests a search query, run it against the catalog
        search_query = ai_response.get("search_query")
        vehicle = ai_response.get("vehicle")

        if search_query or vehicle:
            master = get_master_conn()
            tenant = get_tenant_conn(g.tenant_id)
            branch_id = g.branch_id

        # Try to resolve vehicle to MYE
        if vehicle and master:
            vehicle_match = _resolve_vehicle(master, vehicle)

        # Run catalog search if we have a search query
        # Also search if AI identified a vehicle but didn't give a search_query
        effective_query = search_query
        if not effective_query and vehicle:
            # Extract likely part keywords from the user's message
            import re
            # Remove brand/model/year from message to get the part description
            part_words = user_message.lower()
            for remove in [vehicle.get('brand',''), vehicle.get('model',''), str(vehicle.get('year',''))]:
                part_words = part_words.replace(remove.lower(), '')
            part_words = re.sub(r'necesito|quiero|busco|para|un|una|el|la|de|del|los|las|mi|\d{4}', '', part_words).strip()
            if len(part_words) >= 3:
                effective_query = part_words

        if effective_query and tenant:
            # Support multiple search queries separated by | (for quotes/cotizaciones)
            query_terms = [q.strip() for q in effective_query.split('|') if q.strip()]
            seen_part_numbers = set()

            for qt in query_terms:
                # First: search local inventory
                try:
                    local_results = _search_local_inventory(tenant, qt, qt, branch_id)
                    if local_results:
                        for lr in local_results:
                            pn = lr.get('part_number', '')
                            if pn not in seen_part_numbers:
                                seen_part_numbers.add(pn)
                                search_results.append(lr)
                except Exception:
                    pass

                # Then: search TecDoc catalog
                if master:
                    try:
                        per_query_limit = max(3, 10 // len(query_terms))
                        catalog_results = catalog_service.smart_search(
                            master, qt, tenant, branch_id, limit=per_query_limit
                        )
                        if catalog_results:
                            for cr in catalog_results:
                                pn = cr.get('oem_part_number', '')
                                if pn not in seen_part_numbers:
                                    seen_part_numbers.add(pn)
                                    cr['source'] = 'catalog'
                                    search_results.append(cr)
                    except Exception:
                        pass  # search failure is non-fatal

    except Exception:
        pass  # DB failure is non-fatal for chat
    finally:
        if master:
            try:
                master.close()
            except Exception:
                pass
        if tenant:
            try:
                tenant.close()
            except Exception:
                pass

    return jsonify(
        {
            "response": ai_response.get("message", ""),
            "search_results": search_results,
            "vehicle": vehicle_match or ai_response.get("vehicle"),
        }
    )


def _resolve_vehicle(master_conn, vehicle):
    """Try to resolve AI-extracted vehicle info to brand_id/model_id in DB."""
    brand_name = (vehicle.get("brand") or "").upper().strip()
    model_name = (vehicle.get("model") or "").strip()
    year = vehicle.get("year")

    if not brand_name:
        return vehicle

    cur = master_conn.cursor()
    result = dict(vehicle)

    try:
        # Find brand
        cur.execute(
            "SELECT id_brand, name_brand FROM brands WHERE UPPER(name_brand) = %s",
            (brand_name,),
        )
        brand_row = cur.fetchone()
        if brand_row:
            result["brand_id"] = brand_row[0]
            result["brand"] = brand_row[1]

            # Find model
            if model_name:
                cur.execute(
                    """SELECT m.id_model, m.name_model
                       FROM models m
                       WHERE m.brand_id = %s
                         AND UPPER(m.name_model) LIKE %s
                       ORDER BY m.name_model
                       LIMIT 5""",
                    (brand_row[0], f"%{model_name.upper()}%"),
                )
                model_row = cur.fetchone()
                if model_row:
                    result["model_id"] = model_row[0]
                    result["model"] = model_row[1]

                    # Find year -> MYE
                    if year:
                        cur.execute(
                            """SELECT mye.id_mye, y.year_car, e.name_engine, mye.trim_level
                               FROM model_year_engine mye
                               JOIN years y ON y.id_year = mye.year_id
                               JOIN engines e ON e.id_engine = mye.engine_id
                               WHERE mye.model_id = %s AND y.year_car = %s
                               ORDER BY e.name_engine
                               LIMIT 10""",
                            (model_row[0], int(year)),
                        )
                        mye_rows = cur.fetchall()
                        if mye_rows:
                            result["mye_options"] = [
                                {
                                    "mye_id": r[0],
                                    "year": r[1],
                                    "engine": r[2],
                                    "trim": r[3],
                                }
                                for r in mye_rows
                            ]
    except Exception:
        pass
    finally:
        cur.close()

    return result


def _search_local_inventory(tenant_conn, query_en, query_es, branch_id):
    """Search tenant's local inventory by part name/number in both English and Spanish."""
    cur = tenant_conn.cursor()
    results = []
    try:
        # Search by part_number, name, or brand — try both English and Spanish terms
        terms = set()
        terms.add(query_en)
        if query_es:
            terms.add(query_es)

        where_parts = []
        params = []
        for term in terms:
            if not term:
                continue
            where_parts.append("(i.part_number ILIKE %s OR i.name ILIKE %s OR i.brand ILIKE %s)")
            params.extend([f'%{term}%', f'%{term}%', f'%{term}%'])

        if not where_parts:
            return []

        where = " OR ".join(where_parts)
        if branch_id:
            where = f"({where}) AND i.branch_id = %s"
            params.append(branch_id)

        cur.execute(f"""
            SELECT i.id, i.part_number, i.name, i.brand, i.price_1, i.price_2, i.price_3, i.cost,
                   COALESCE((SELECT SUM(quantity) FROM inventory_operations WHERE inventory_id = i.id), 0) as stock
            FROM inventory i
            WHERE i.is_active = true AND ({where})
            ORDER BY i.name
            LIMIT 10
        """, params)

        for r in cur.fetchall():
            results.append({
                'source': 'local',
                'inventory_id': r[0],
                'part_number': r[1],
                'oem_part_number': r[1],
                'name_part': r[2],
                'brand': r[3],
                'price_1': float(r[4]) if r[4] else 0,
                'price_2': float(r[5]) if r[5] else 0,
                'price_3': float(r[6]) if r[6] else 0,
                'cost': float(r[7]) if r[7] else 0,
                'local_stock': r[8],
            })
    except Exception:
        pass
    finally:
        cur.close()

    return results
