import json
import requests
import traceback
from django.conf import settings
from .ai_tools import (
    get_stock_report, get_financial_summary, draft_purchase_order,
    add_operating_expense, lookup_product_details, get_supplier_directory,
    get_customer_insights, add_customer, get_company_settings, update_company_settings
)
from .ai_knowledge import get_relevant_sections

AI_TOOLS = [
    {
        "type": "function",
        "function": {
            "name": "get_stock_report",
            "description": "Returns a JSON string of stock numbers: low stock, out of stock items, and top 5 items.",
            "parameters": {
                "type": "object",
                "properties": {},
                "required": []
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "get_financial_summary",
            "description": "Returns a financial summary (sales, revenue, profit, expenses) for a specific date range. Pass YYYY-MM-DD for both start and end dates. Leave dates empty to get today's summary.",
            "parameters": {
                "type": "object",
                "properties": {
                    "start_date": {"type": "string", "description": "Start date in YYYY-MM-DD format (e.g. 2025-03-01)"},
                    "end_date": {"type": "string", "description": "End date in YYYY-MM-DD format (e.g. 2025-03-31)"}
                },
                "required": []
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "draft_purchase_order",
            "description": "Drafts a purchase order in the database autonomously. Needs supplier name and list of items.",
            "parameters": {
                "type": "object",
                "properties": {
                    "supplier_name": {"type": "string", "description": "Name of supplier to search for"},
                    "items": {
                        "type": "array",
                        "description": "Array of item dicts",
                        "items": {
                            "type": "object",
                            "properties": {
                                "sku_or_name": {"type": "string"},
                                "quantity": {"type": "integer"}
                            },
                            "required": ["sku_or_name", "quantity"]
                        }
                    }
                },
                "required": ["supplier_name", "items"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "add_operating_expense",
            "description": "Log a new operating expense for the company.",
            "parameters": {
                "type": "object",
                "properties": {
                    "amount": {"type": "number", "description": "The cost or amount of the expense"},
                    "category_name": {"type": "string", "description": "The expense category (e.g. Rent, Transport, Utilities, Salaries, Marketing)"},
                    "reference": {"type": "string", "description": "Optional receipt or reference number/description"},
                    "notes": {"type": "string", "description": "Optional detailed notes"}
                },
                "required": ["amount", "category_name"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "lookup_product_details",
            "description": "Lookup detailed information for a specific product by name, SKU, or barcode (e.g. price, cost, margin, stock level, status).",
            "parameters": {
                "type": "object",
                "properties": {
                    "search_term": {"type": "string", "description": "Product name, SKU, or barcode to search for"}
                },
                "required": ["search_term"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "get_supplier_directory",
            "description": "Returns a list of all suppliers, including contact information and current balances.",
            "parameters": {
                "type": "object",
                "properties": {},
                "required": []
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "get_customer_insights",
            "description": "Returns analytics and insights on customers, including top 5 spending customers and top 5 debtors with outstanding balances.",
            "parameters": {
                "type": "object",
                "properties": {},
                "required": []
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "add_customer",
            "description": "Registers/adds a new customer directly into the database.",
            "parameters": {
                "type": "object",
                "properties": {
                    "name": {"type": "string", "description": "Full name of the customer"},
                    "phone": {"type": "string", "description": "Optional phone number"},
                    "email": {"type": "string", "description": "Optional email address"},
                    "address": {"type": "string", "description": "Optional physical address"},
                    "notes": {"type": "string", "description": "Optional description or customer notes"}
                },
                "required": ["name"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "get_company_settings",
            "description": "Retrieves the company operational settings, profiles, custom receipt headers/footers, thermal printer name, and WhatsApp receipt status.",
            "parameters": {
                "type": "object",
                "properties": {},
                "required": []
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "update_company_settings",
            "description": "Updates specific fields on the company's operational settings like business phone, email, receipt headers/footers, and QZ thermal printer name or width (58 or 80).",
            "parameters": {
                "type": "object",
                "properties": {
                    "business_phone": {"type": "string", "description": "Updated business phone number"},
                    "business_email": {"type": "string", "description": "Updated business email"},
                    "receipt_header": {"type": "string", "description": "Updated receipt header text"},
                    "receipt_footer": {"type": "string", "description": "Updated receipt footer text"},
                    "thermal_printer_name": {"type": "string", "description": "Updated thermal printer QZ name"},
                    "receipt_width_mm": {"type": "integer", "description": "Thermal receipt paper width (58 or 80)"}
                },
                "required": []
            }
        }
    }
]


def call_llm(user_prompt, company):
    """
    Calls the configured LLM API (e.g., OpenRouter) with the context and user prompt.
    Supports tool calling.

    System prompt is assembled from two parts:
      1. dynamic_context  — company name, plan, currency, current datetime (built here).
      2. SWIFTPOS_KNOWLEDGE — static platform feature guide (maintained in ai_knowledge.py).
    """
    base_url = getattr(settings, 'AI_API_URL', 'https://openrouter.ai/api/v1').rstrip('/')
    url = f"{base_url}/chat/completions"
    api_key = getattr(settings, 'AI_API_KEY', '')
    model = getattr(settings, 'AI_API_MODEL', 'minimax/minimax-m2.5:free')

    if not api_key:
        return "AI is not configured yet. Please configure the AI API Key in settings."

    currency = getattr(company.settings, 'currency_symbol', '₦') if hasattr(company, 'settings') else '₦'

    import datetime
    current_time = datetime.datetime.now()

    company_name = company.name if company else 'Global'
    plan_name = getattr(getattr(company, 'plan', None), 'name', 'Unknown') if company else 'Unknown'

    # ── Dynamic context (changes per request) ──────────────────────────────
    dynamic_context = (
        "You are SwiftPOS AI Assistant — an expert, helpful agent embedded inside SwiftPOS, "
        "a cloud-based multi-tenant Point of Sale (POS) and business management platform "
        "built for Nigerian SMEs and retail businesses.\n\n"
        "You serve TWO purposes:\n"
        "1. Answer questions about how SwiftPOS works, its features, pages, and how to use them.\n"
        "2. Execute real-time business queries via tools (stock, financials, purchase orders).\n\n"
        "IMPORTANT: Always format monetary values with the currency symbol. "
        "Never use $ unless it is the company's own currency.\n\n"
        f"CURRENT DATE AND TIME : {current_time.strftime('%A, %B %d, %Y %I:%M %p')}\n"
        f"COMPANY               : {company_name}\n"
        f"SUBSCRIPTION PLAN     : {plan_name}\n"
        f"CURRENCY              : {currency}\n\n"
        "STRICT BOUNDARIES — YOU MUST FOLLOW THESE AT ALL TIMES:\n"
        "- You ONLY assist the company currently logged in. Never discuss, reference, or reveal "
        "data, settings, or operations belonging to any other company.\n"
        "- You have NO knowledge of, and must NOT discuss, the superadmin panel, superadmin "
        "accounts, platform-level management (managing companies, creating plans, overriding "
        "subscriptions, etc.). If asked, politely say that is handled externally and outside "
        "your scope.\n"
        "- If a user asks about another company or tenant, respond: 'I can only assist with "
        f"{company_name}. I do not have access to other companies\\' data.'\n"
        "- Never reveal internal technical details (database IDs, server config, secret keys, "
        "or Django settings).\n"
    )

    # ── Relevant knowledge sections (keyword-matched to keep prompt small) ─────
    relevant_knowledge = get_relevant_sections(user_prompt)
    system_message = dynamic_context + relevant_knowledge

    headers = {
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json",
        "HTTP-Referer": "https://app.swiftpos.ng",
        "X-Title": "SwiftPOS"
    }

    messages = [
        {"role": "system", "content": system_message},
        {"role": "user", "content": user_prompt}
    ]

    def _call_api(msgs):
        payload = {
            "model": model,
            "messages": msgs,
            "tools": AI_TOOLS,
            "tool_choice": "auto"
        }
        res = requests.post(url, headers=headers, json=payload, timeout=30)
        res.raise_for_status()
        return res.json()

    try:
        data = _call_api(messages)
        message_obj = data["choices"][0]["message"]

        # Check if the LLM decided to call any tools
        if message_obj.get("tool_calls"):
            messages.append(message_obj)
            for tool_call in message_obj["tool_calls"]:
                func_name = tool_call["function"]["name"]
                args = json.loads(tool_call["function"]["arguments"])

                result = {"error": "Function not found"}
                try:
                    if func_name == "get_stock_report":
                        result = get_stock_report(company)
                    elif func_name == "get_financial_summary":
                        result = get_financial_summary(
                            company,
                            args.get("start_date"),
                            args.get("end_date")
                        )
                    elif func_name == "draft_purchase_order":
                        result = draft_purchase_order(
                            company,
                            args.get("supplier_name"),
                            args.get("items")
                        )
                    elif func_name == "add_operating_expense":
                        result = add_operating_expense(
                            company,
                            args.get("amount"),
                            args.get("category_name"),
                            args.get("reference"),
                            args.get("notes")
                        )
                    elif func_name == "lookup_product_details":
                        result = lookup_product_details(
                            company,
                            args.get("search_term")
                        )
                    elif func_name == "get_supplier_directory":
                        result = get_supplier_directory(company)
                    elif func_name == "get_customer_insights":
                        result = get_customer_insights(company)
                    elif func_name == "add_customer":
                        result = add_customer(
                            company,
                            args.get("name"),
                            args.get("phone"),
                            args.get("email"),
                            args.get("address"),
                            args.get("notes")
                        )
                    elif func_name == "get_company_settings":
                        result = get_company_settings(company)
                    elif func_name == "update_company_settings":
                        result = update_company_settings(
                            company,
                            args.get("business_phone"),
                            args.get("business_email"),
                            args.get("receipt_header"),
                            args.get("receipt_footer"),
                            args.get("thermal_printer_name"),
                            args.get("receipt_width_mm")
                        )
                except Exception as ex:
                    print("Tool error:", traceback.format_exc())
                    result = json.dumps({"error": str(ex)})

                messages.append({
                    "role": "tool",
                    "tool_call_id": tool_call["id"],
                    "name": func_name,
                    "content": str(result)
                })

            # Call API again with tool results
            data2 = _call_api(messages)
            content = data2["choices"][0]["message"].get("content") or ""
            return content.strip()

        else:
            content = message_obj.get("content") or ""
            return content.strip()

    except requests.exceptions.RequestException as e:
        return f"Sorry, I am currently unable to reach the AI server. (Error: {str(e)})"
    except Exception as e:
        print(traceback.format_exc())
        return f"An internal error occurred while processing the AI request. ({str(e)})"
