"""Card query skills — search and compare credit cards."""

from __future__ import annotations

from sqlalchemy import or_

from luca_assistant.db.engine import get_session
from luca_assistant.db.models import BankRule, Card, CardOffer


def query_card_details(card_name: str, bank: str | None = None) -> dict:
    """Look up a card by name, optionally filtering by bank."""
    session = get_session()
    try:
        query = session.query(Card).filter(
            or_(
                Card.name.ilike(f"%{card_name}%"),
                Card.full_name.ilike(f"%{card_name}%"),
            )
        )
        if bank:
            query = query.filter(Card.bank.ilike(f"%{bank}%"))

        cards = query.all()
        if not cards:
            return {"error": f"No card found matching '{card_name}'"}

        results = []
        for card in cards:
            offers = [
                {
                    "bonus": o.bonus_amount,
                    "value_usd": o.bonus_value_usd,
                    "spend_requirement": o.spend_requirement,
                    "spend_months": o.spend_timeframe_months,
                    "is_current": o.is_current,
                    "is_highest_known": o.is_highest_known,
                }
                for o in card.offers
                if o.is_current
            ]
            benefits = [
                {
                    "category": b.category,
                    "multiplier": b.multiplier,
                    "points_type": b.points_type,
                    "annual_credit": b.annual_credit,
                    "credit_category": b.credit_category,
                    "notes": b.notes,
                }
                for b in card.benefits
            ]
            entry = {
                "bank": card.bank,
                "name": card.name,
                "full_name": card.full_name,
                "network": card.network,
                "annual_fee": card.annual_fee,
                "annual_fee_waived_first_year": card.annual_fee_waived_first_year,
                "product_family": card.product_family,
                "is_business": card.is_business,
                "is_secured": card.is_secured,
                "purchase_apr_min": card.purchase_apr_min,
                "purchase_apr_max": card.purchase_apr_max,
                "foreign_transaction_fee_pct": card.foreign_transaction_fee_pct,
                "late_fee": card.late_fee,
                "grace_period_days": card.grace_period_days,
                "current_offers": offers,
                "benefits": benefits,
            }

            # Hint for agent to enrich multipliers via web search
            has_multipliers = any(b["multiplier"] > 1.0 for b in benefits)
            if not has_multipliers:
                entry["multiplier_hint"] = (
                    f"Category multipliers not populated for {card.full_name}. "
                    f"To find current earning rates, search: "
                    f"'{card.full_name} category multipliers"
                    f" site:doctorofcredit.com OR site:thepointsguy.com' "
                    f"then call luca_update_card_benefit to persist each category."
                )

            results.append(entry)

        return {"cards": results} if len(results) > 1 else results[0]
    finally:
        session.close()


def find_highest_offers(
    bank: str | None = None,
    min_bonus_usd: int | None = None,
    is_business: bool | None = None,
    limit: int = 10,
) -> dict:
    """Find highest current SUB offers."""
    session = get_session()
    try:
        query = (
            session.query(Card, CardOffer)
            .join(CardOffer)
            .filter(CardOffer.is_current.is_(True))
            .order_by(CardOffer.bonus_value_usd.desc())
        )

        if bank:
            query = query.filter(Card.bank.ilike(f"%{bank}%"))
        if min_bonus_usd is not None:
            query = query.filter(CardOffer.bonus_value_usd >= min_bonus_usd)
        if is_business is not None:
            query = query.filter(Card.is_business.is_(is_business))

        results = []
        for card, offer in query.limit(limit).all():
            results.append(
                {
                    "bank": card.bank,
                    "name": card.name,
                    "annual_fee": card.annual_fee,
                    "is_business": card.is_business,
                    "bonus": offer.bonus_amount,
                    "bonus_value_usd": offer.bonus_value_usd,
                    "spend_requirement": offer.spend_requirement,
                    "spend_months": offer.spend_timeframe_months,
                    "is_highest_known": offer.is_highest_known,
                }
            )

        return {"offers": results, "count": len(results)}
    finally:
        session.close()


def compare_card_benefits(card_names: list[str]) -> dict:
    """Compare multiple cards side by side."""
    session = get_session()
    try:
        comparisons = []
        for name in card_names:
            card = (
                session.query(Card)
                .filter(
                    or_(
                        Card.name.ilike(f"%{name}%"),
                        Card.full_name.ilike(f"%{name}%"),
                    )
                )
                .first()
            )

            if not card:
                comparisons.append({"name": name, "error": "Card not found"})
                continue

            current_offer = next((o for o in card.offers if o.is_current), None)
            comparisons.append(
                {
                    "bank": card.bank,
                    "name": card.name,
                    "annual_fee": card.annual_fee,
                    "network": card.network,
                    "is_business": card.is_business,
                    "current_offer": {
                        "bonus": current_offer.bonus_amount,
                        "value_usd": current_offer.bonus_value_usd,
                        "spend_requirement": current_offer.spend_requirement,
                        "spend_months": current_offer.spend_timeframe_months,
                    }
                    if current_offer
                    else None,
                    "benefits": [
                        {
                            "category": b.category,
                            "multiplier": b.multiplier,
                            "points_type": b.points_type,
                            "annual_credit": b.annual_credit,
                            "notes": b.notes,
                        }
                        for b in card.benefits
                    ],
                }
            )

        return {"comparison": comparisons}
    finally:
        session.close()


def get_bank_rules(bank: str) -> dict:
    """Get all rules for a specific bank."""
    session = get_session()
    try:
        rules = session.query(BankRule).filter(BankRule.bank.ilike(f"%{bank}%")).all()
        if not rules:
            return {"error": f"No rules found for bank '{bank}'"}

        return {
            "bank": bank,
            "rules": [
                {
                    "name": r.rule_name,
                    "description": r.description,
                    "type": r.rule_type,
                    "parameters": r.parameters,
                }
                for r in rules
            ],
        }
    finally:
        session.close()
