"""MCP server exposing Luca skills to any MCP-compatible agent."""

from __future__ import annotations

import json

from mcp.server.fastmcp import FastMCP

from luca_assistant.db import init_db
from luca_assistant.db.engine import get_session
from luca_assistant.db.seed import seed_all
from luca_assistant.skills.card_query import (
    compare_card_benefits,
    find_highest_offers,
    get_bank_rules,
    query_card_details,
)
from luca_assistant.skills.card_update import update_card_benefit
from luca_assistant.skills.portfolio import (
    add_user_card,
    check_chase_524_status,
    close_user_card,
    get_user_portfolio,
)

mcp = FastMCP("luca-assistant")


def _ensure_db() -> None:
    init_db()
    session = get_session()
    try:
        seed_all(session)
    finally:
        session.close()


def _json(data: dict) -> str:
    return json.dumps(data, default=str, ensure_ascii=False)


def _safe(func, *args, **kwargs) -> str:
    """Call a skill function with DB init and error handling."""
    _ensure_db()
    try:
        return _json(func(*args, **kwargs))
    except Exception as e:
        return _json({"error": str(e)})


# --- Database management tools ---


@mcp.tool()
def luca_import_cards(source: str = "offer-optimist", force: bool = False) -> str:
    """Import or refresh card data. source: 'offer-optimist' or 'cfpb'."""
    _ensure_db()
    try:
        session = get_session()
        try:
            if source == "offer-optimist":
                from luca_assistant.db.importers import OfferOptimistImporter

                importer = OfferOptimistImporter()
                path = importer.download(force=force)
                data = importer.parse(path)
                result = importer.import_cards(session, data)
                session.commit()
                return _json({
                    "status": "ok",
                    "source": "offer-optimist",
                    "cards_created": result.cards_created,
                    "cards_updated": result.cards_updated,
                    "offers_created": result.offers_created,
                    "benefits_created": result.benefits_created,
                    "skipped_discontinued": result.skipped_discontinued,
                    "errors": result.errors[:5] if result.errors else [],
                })
            elif source == "cfpb":
                from luca_assistant.db.importers import CFPBImporter

                importer = CFPBImporter()
                path = importer.download(force=force)
                data = importer.parse(path)
                result = importer.import_cards(session, data)
                session.commit()
                return _json({
                    "status": "ok",
                    "source": "cfpb",
                    "total_rows": result.total_rows,
                    "cards_enriched": result.cards_enriched,
                    "cards_not_matched": result.cards_not_matched,
                    "errors": result.errors[:5] if result.errors else [],
                })
            else:
                return _json({
                    "error": f"Unknown source: '{source}'. Available: offer-optimist, cfpb",
                })
        finally:
            session.close()
    except Exception as e:
        return _json({"error": str(e)})


# --- Card query tools ---


@mcp.tool()
def luca_query_card_details(card_name: str, bank: str | None = None) -> str:
    """Query a credit card's details including benefits, current offers, and annual fee."""
    return _safe(query_card_details, card_name, bank)


@mcp.tool()
def luca_find_highest_offers(
    bank: str | None = None,
    min_bonus_usd: int | None = None,
    is_business: bool | None = None,
    limit: int = 10,
) -> str:
    """Find credit cards with the best current sign-up bonuses."""
    return _safe(find_highest_offers, bank, min_bonus_usd, is_business, limit)


@mcp.tool()
def luca_compare_card_benefits(card_names: list[str]) -> str:
    """Compare benefits and offers of multiple credit cards side by side."""
    return _safe(compare_card_benefits, card_names)


@mcp.tool()
def luca_get_bank_rules(bank: str) -> str:
    """Get issuer-specific application rules for a bank."""
    return _safe(get_bank_rules, bank)


# --- Card update tools ---


@mcp.tool()
def luca_update_card_benefit(
    card_name: str,
    category: str,
    multiplier: float,
    points_type: str,
    notes: str | None = None,
    bank: str | None = None,
    annual_credit: int | None = None,
    credit_category: str | None = None,
) -> str:
    """Add or update a category benefit (multiplier or credit) for a card."""
    return _safe(
        update_card_benefit,
        card_name, category, multiplier, points_type, notes, bank, annual_credit, credit_category,
    )


# --- Portfolio tools ---


@mcp.tool()
def luca_get_user_portfolio() -> str:
    """Get the user's current credit card portfolio."""
    return _safe(get_user_portfolio)


@mcp.tool()
def luca_check_chase_524_status() -> str:
    """Calculate the user's Chase 5/24 status."""
    return _safe(check_chase_524_status)


@mcp.tool()
def luca_add_user_card(
    card_name: str,
    opened_date: str,
    bank: str | None = None,
    credit_limit: int | None = None,
    bonus_earned: bool = False,
    bonus_met_date: str | None = None,
    notes: str | None = None,
) -> str:
    """Add a credit card to the user's portfolio."""
    return _safe(
        add_user_card, card_name, opened_date, bank, credit_limit, bonus_earned, bonus_met_date,
        notes,
    )


@mcp.tool()
def luca_close_user_card(card_name: str, closed_date: str, bank: str | None = None) -> str:
    """Mark a card in the user's portfolio as closed."""
    return _safe(close_user_card, card_name, closed_date, bank)


def main() -> None:
    """Entry point for the luca-mcp command."""
    _ensure_db()
    mcp.run()


if __name__ == "__main__":
    main()
