"""Card-related constants, demo data, and validation helpers."""

from __future__ import annotations

from typing import Any

from utils import clean_text


CATEGORIES = [
    "Shopping",
    "Dining",
    "Fuel",
    "Groceries",
    "Travel",
    "Entertainment",
    "Utilities",
    "Online Shopping",
    "Other",
]

CARD_TYPES = ["Credit Card", "Debit Card", "Prepaid Card", "Virtual Card"]
REWARD_TYPES = ["Cashback", "Reward Points", "Miles", "Discount"]

CATEGORY_RATE_COLUMNS = {
    "Shopping": "shopping_rate",
    "Dining": "dining_rate",
    "Fuel": "fuel_rate",
    "Groceries": "grocery_rate",
    "Travel": "travel_rate",
    "Entertainment": "entertainment_rate",
    "Utilities": "utility_rate",
    "Online Shopping": "online_shopping_rate",
    "Other": "other_rate",
}


DEMO_CARDS = [
    {
        "card_name": "Demo Rewards Plus",
        "bank_name": "Demo Bank",
        "card_type": "Credit Card",
        "annual_fee": 999,
        "reward_type": "Cashback",
        "shopping_rate": 4.0,
        "dining_rate": 2.5,
        "fuel_rate": 1.0,
        "grocery_rate": 2.0,
        "travel_rate": 1.5,
        "entertainment_rate": 2.0,
        "utility_rate": 1.0,
        "online_shopping_rate": 5.0,
        "other_rate": 1.0,
    },
    {
        "card_name": "Demo Cashback Pro",
        "bank_name": "Sample Finance",
        "card_type": "Credit Card",
        "annual_fee": 499,
        "reward_type": "Cashback",
        "shopping_rate": 3.0,
        "dining_rate": 3.0,
        "fuel_rate": 1.0,
        "grocery_rate": 4.0,
        "travel_rate": 1.0,
        "entertainment_rate": 1.5,
        "utility_rate": 2.0,
        "online_shopping_rate": 4.0,
        "other_rate": 1.0,
    },
    {
        "card_name": "Demo Travel Card",
        "bank_name": "Journey Bank",
        "card_type": "Credit Card",
        "annual_fee": 1499,
        "reward_type": "Miles",
        "shopping_rate": 1.0,
        "dining_rate": 2.0,
        "fuel_rate": 0.5,
        "grocery_rate": 1.0,
        "travel_rate": 6.0,
        "entertainment_rate": 2.0,
        "utility_rate": 0.5,
        "online_shopping_rate": 2.0,
        "other_rate": 1.0,
    },
    {
        "card_name": "Demo Fuel Saver",
        "bank_name": "Highway Bank",
        "card_type": "Credit Card",
        "annual_fee": 299,
        "reward_type": "Discount",
        "shopping_rate": 1.0,
        "dining_rate": 1.0,
        "fuel_rate": 5.0,
        "grocery_rate": 1.0,
        "travel_rate": 1.0,
        "entertainment_rate": 1.0,
        "utility_rate": 1.0,
        "online_shopping_rate": 1.0,
        "other_rate": 0.5,
    },
    {
        "card_name": "Demo Lifestyle Card",
        "bank_name": "Urban Credit",
        "card_type": "Credit Card",
        "annual_fee": 799,
        "reward_type": "Reward Points",
        "shopping_rate": 2.0,
        "dining_rate": 5.0,
        "fuel_rate": 0.5,
        "grocery_rate": 2.0,
        "travel_rate": 2.0,
        "entertainment_rate": 5.0,
        "utility_rate": 1.0,
        "online_shopping_rate": 3.0,
        "other_rate": 1.0,
    },
]


def get_rate_column(category: str) -> str:
    """Return the database column that stores a category's reward rate."""
    return CATEGORY_RATE_COLUMNS.get(category, "other_rate")


def validate_card_data(card_data: dict[str, Any]) -> list[str]:
    """Return a list of human-readable validation errors for a card form."""
    errors = []

    if not clean_text(card_data.get("card_name")):
        errors.append("Card name is required.")

    if not clean_text(card_data.get("bank_name")):
        errors.append("Bank name is required.")

    annual_fee = card_data.get("annual_fee", 0)
    try:
        if float(annual_fee) < 0:
            errors.append("Annual fee cannot be negative.")
    except (TypeError, ValueError):
        errors.append("Annual fee must be a valid number.")

    for category, column_name in CATEGORY_RATE_COLUMNS.items():
        reward_rate = card_data.get(column_name, 0)
        try:
            numeric_rate = float(reward_rate)
        except (TypeError, ValueError):
            errors.append(f"{category} reward rate must be a valid number.")
            continue

        if numeric_rate < 0:
            errors.append(f"{category} reward rate cannot be negative.")
        elif numeric_rate > 100:
            errors.append(f"{category} reward rate cannot be more than 100%.")

    return errors


def normalize_card_data(card_data: dict[str, Any]) -> dict[str, Any]:
    """Convert user input into clean values ready for SQLite."""
    normalized = {
        "card_name": clean_text(card_data.get("card_name")),
        "bank_name": clean_text(card_data.get("bank_name")),
        "card_type": clean_text(card_data.get("card_type")) or CARD_TYPES[0],
        "annual_fee": float(card_data.get("annual_fee") or 0),
        "reward_type": clean_text(card_data.get("reward_type")) or REWARD_TYPES[0],
    }

    for column_name in CATEGORY_RATE_COLUMNS.values():
        normalized[column_name] = float(card_data.get(column_name) or 0)

    return normalized

