"""Converts prices into a tenant's reference currency so they can be compared.

Every price rule in the matching specification divides one price by another. Across
currencies that is meaningless and silent: an INR price against a USD one yields a
ratio dozens of times out, and the output looks like a ranking opinion rather than a
data fault. Conversion happens once, at ingestion, from an operator-seeded rate
table -- never guessed, since a guessed rate is indistinguishable from a real one in
the output while a missing one is visible as an incomplete product.
"""
import logging

from app.services.infra.database import get_master_db_connection

logger = logging.getLogger(__name__)


def ensure_fx_table() -> None:
    conn = get_master_db_connection()
    try:
        with conn.cursor() as cur:
            cur.execute("""
                CREATE TABLE IF NOT EXISTS fx_rates (
                    base_currency  TEXT NOT NULL,
                    quote_currency TEXT NOT NULL,
                    rate           REAL NOT NULL,
                    fetched_at     TIMESTAMPTZ NOT NULL DEFAULT now(),
                    PRIMARY KEY (base_currency, quote_currency)
                )
            """)
        conn.commit()
    except Exception:
        conn.rollback()
        logger.error("Could not ensure fx_rates table", exc_info=True)
        raise
    finally:
        conn.close()


def get_rate(base: str, quote: str) -> float | None:
    if not base or not quote:
        return None
    if base == quote:
        return 1.0

    ensure_fx_table()
    conn = get_master_db_connection()
    try:
        with conn.cursor() as cur:
            cur.execute(
                "SELECT rate FROM fx_rates WHERE base_currency = %s "
                "AND quote_currency = %s", (base, quote))
            row = cur.fetchone()
            return float(row[0]) if row else None
    finally:
        conn.close()


def to_reference_cents(
    price_cents: int | None, source_currency: str | None,
    reference_currency: str | None,
) -> tuple[int | None, float | None]:
    """Returns (converted_cents, rate_used), or (None, None) when no rate exists.

    Deliberately does not fall back to a default rate: a guessed conversion is
    indistinguishable from a real one in the output, whereas a null makes the
    product incomplete and therefore visible, matching the store-flag-exclude
    pattern used for every other required field.
    """
    if price_cents is None or not source_currency or not reference_currency:
        return None, None

    if source_currency == reference_currency:
        return int(price_cents), 1.0

    rate = get_rate(source_currency, reference_currency)
    if rate is None:
        logger.warning("No fx rate for %s -> %s; product will be incomplete",
                       source_currency, reference_currency)
        return None, None

    return int(round(price_cents * rate)), rate
