"""Commerce-Tools — Kaufabsichten, Angebotsvergleich, Tracking, Händlerprüfung."""

from mcp.server.fastmcp import FastMCP

from src.db import (
    create_purchase, get_purchase, update_purchase,
    list_purchases as db_list_purchases,
    add_offer, get_offers,
    get_merchant, upsert_merchant, now_iso,
)


def register_commerce_tools(mcp: FastMCP):
    """Commerce-bezogene MCP-Tools registrieren."""

    @mcp.tool()
    async def create_purchase_intent(
        item: str,
        quantity: int = 1,
        budget_max: float = 0,
        budget_currency: str = "USD",
        delivery_address: str = "",
        delivery_notes: str = "",
    ) -> dict:
        """Strukturierte Kaufabsicht erstellen.

        Erstellt einen neuen Kaufvorgang, der dann mit Angeboten
        verglichen und weiterverfolgt werden kann.

        Args:
            item: Beschreibung des gewünschten Artikels
            quantity: Gewünschte Menge (Standard: 1)
            budget_max: Maximales Budget (0 = kein Limit)
            budget_currency: Währung (Standard: "USD")
            delivery_address: Lieferadresse
            delivery_notes: Besondere Lieferhinweise
        """
        result = create_purchase(
            item=item,
            quantity=quantity,
            budget_max=budget_max if budget_max > 0 else None,
            budget_currency=budget_currency,
            delivery_address=delivery_address,
            delivery_notes=delivery_notes,
        )
        return {
            "purchase_id": result["id"],
            "status": "intent",
            "item": item,
            "quantity": quantity,
            "budget": f"{budget_max} {budget_currency}" if budget_max > 0
                      else "kein Limit",
            "message": "Kaufabsicht erstellt. Jetzt Angebote mit "
                       "compare_offers vergleichen.",
        }

    @mcp.tool()
    async def compare_offers(
        purchase_id: str,
        offers: list[dict],
    ) -> dict:
        """Angebote für eine Kaufabsicht vergleichen.

        Nimmt eine Liste von Angeboten entgegen, speichert sie
        und gibt eine Vergleichsübersicht zurück.

        Args:
            purchase_id: ID der Kaufabsicht
            offers: Liste von Angeboten, jedes mit:
                    merchant_name (str), price (float),
                    optional: currency, shipping_cost, delivery_days,
                    condition, url, notes
        """
        purchase = get_purchase(purchase_id)
        if purchase is None:
            return {"error": f"Kaufvorgang '{purchase_id}' nicht gefunden."}

        # Angebote speichern
        saved_offers = []
        for o in offers:
            if "merchant_name" not in o or "price" not in o:
                continue
            result = add_offer(
                purchase_id=purchase_id,
                merchant_name=o["merchant_name"],
                price=float(o["price"]),
                currency=o.get("currency", "USD"),
                shipping_cost=float(o.get("shipping_cost", 0)),
                delivery_days=o.get("delivery_days"),
                condition=o.get("condition", ""),
                url=o.get("url", ""),
                notes=o.get("notes", ""),
            )
            saved_offers.append(result)

        # Alle Angebote laden und vergleichen
        all_offers = get_offers(purchase_id)

        # Gesamtkosten berechnen (Preis + Versand)
        for o in all_offers:
            o["total_cost"] = o["price"] + (o["shipping_cost"] or 0)

        # Nach Gesamtkosten sortieren
        all_offers.sort(key=lambda x: x["total_cost"])

        # Bestes Angebot ermitteln
        best = all_offers[0] if all_offers else None

        # Budgetprüfung
        budget_max = purchase.get("budget_max")
        within_budget = []
        over_budget = []
        if budget_max:
            for o in all_offers:
                if o["total_cost"] <= budget_max:
                    within_budget.append(o["merchant_name"])
                else:
                    over_budget.append(o["merchant_name"])

        # Status aktualisieren
        update_purchase(purchase_id, status="comparing")

        return {
            "purchase_id": purchase_id,
            "item": purchase["item"],
            "total_offers": len(all_offers),
            "new_offers_added": len(saved_offers),
            "best_offer": {
                "merchant": best["merchant_name"],
                "price": best["price"],
                "shipping": best["shipping_cost"],
                "total": best["total_cost"],
                "delivery_days": best.get("delivery_days"),
            } if best else None,
            "all_offers": [
                {
                    "merchant": o["merchant_name"],
                    "price": o["price"],
                    "shipping": o["shipping_cost"],
                    "total": o["total_cost"],
                    "delivery_days": o.get("delivery_days"),
                    "condition": o.get("condition", ""),
                }
                for o in all_offers
            ],
            "budget_check": {
                "budget_max": budget_max,
                "within_budget": within_budget,
                "over_budget": over_budget,
            } if budget_max else None,
        }

    @mcp.tool()
    async def track_purchase(purchase_id: str,
                             new_status: str = "") -> dict:
        """Status eines Kaufvorgangs abrufen oder aktualisieren.

        Mögliche Status: intent, comparing, ordered, shipped,
        delivered, cancelled.

        Args:
            purchase_id: ID des Kaufvorgangs
            new_status: Optional — neuer Status setzen
        """
        purchase = get_purchase(purchase_id)
        if purchase is None:
            return {"error": f"Kaufvorgang '{purchase_id}' nicht gefunden."}

        valid_statuses = {
            "intent", "comparing", "ordered",
            "shipped", "delivered", "cancelled",
        }

        if new_status:
            if new_status not in valid_statuses:
                return {
                    "error": f"Ungültiger Status: '{new_status}'",
                    "valid_statuses": sorted(valid_statuses),
                }
            update_purchase(purchase_id, status=new_status)
            purchase["status"] = new_status

        # Angebote laden
        offers = get_offers(purchase_id)

        return {
            "purchase_id": purchase_id,
            "status": purchase["status"],
            "item": purchase["item"],
            "quantity": purchase["quantity"],
            "budget_max": purchase.get("budget_max"),
            "merchant": purchase.get("merchant_name", ""),
            "total_price": purchase.get("total_price"),
            "offers_count": len(offers),
            "created_at": purchase["created_at"],
            "updated_at": purchase["updated_at"],
        }

    @mcp.tool()
    async def list_purchases(status: str = "",
                             limit: int = 20) -> dict:
        """Kaufhistorie auflisten.

        Args:
            status: Optional — Filter nach Status
                    (intent, comparing, ordered, shipped, delivered, cancelled)
            limit: Maximale Anzahl (Standard: 20)
        """
        limit = min(max(1, limit), 100)
        purchases = db_list_purchases(
            status=status if status else None,
            limit=limit,
        )

        return {
            "total": len(purchases),
            "filter": status if status else "alle",
            "purchases": [
                {
                    "id": p["id"],
                    "status": p["status"],
                    "item": p["item"],
                    "quantity": p["quantity"],
                    "budget_max": p.get("budget_max"),
                    "merchant": p.get("merchant_name", ""),
                    "total_price": p.get("total_price"),
                    "created_at": p["created_at"],
                }
                for p in purchases
            ],
        }

    @mcp.tool()
    async def verify_merchant(merchant_name: str,
                              successful_order: bool | None = None) -> dict:
        """Händler-Zuverlässigkeit prüfen oder Erfahrung melden.

        Ohne successful_order: Zeigt aktuellen Score.
        Mit successful_order: Aktualisiert den Score basierend
        auf einer neuen Erfahrung.

        Args:
            merchant_name: Name des Händlers
            successful_order: Optional — True wenn Bestellung erfolgreich,
                              False wenn problematisch
        """
        merchant = get_merchant(merchant_name)

        # Neue Erfahrung melden
        if successful_order is not None:
            total = (merchant["total_orders"] if merchant else 0) + 1
            successful = (merchant["successful_orders"] if merchant else 0)
            if successful_order:
                successful += 1

            score = successful / total if total > 0 else 0.5

            upsert_merchant(
                name=merchant_name,
                reliability_score=round(score, 3),
                total_orders=total,
                successful_orders=successful,
                last_order_at=now_iso(),
            )
            merchant = get_merchant(merchant_name)

        if merchant is None:
            return {
                "merchant_name": merchant_name,
                "known": False,
                "reliability_score": None,
                "message": "Händler noch nicht bekannt. Keine Erfahrungsdaten.",
            }

        # Bewertung interpretieren
        score = merchant["reliability_score"]
        if score >= 0.9:
            rating = "Exzellent"
        elif score >= 0.7:
            rating = "Gut"
        elif score >= 0.5:
            rating = "Durchschnittlich"
        else:
            rating = "Problematisch"

        return {
            "merchant_name": merchant_name,
            "known": True,
            "reliability_score": score,
            "rating": rating,
            "total_orders": merchant["total_orders"],
            "successful_orders": merchant["successful_orders"],
            "last_order_at": merchant.get("last_order_at", ""),
        }
