from __future__ import annotations

import logging
from typing import Any

import mysql.connector
from mysql.connector import Error as MySQLError

from config.db_config import get_db_config
from utils.json_helper import as_date, as_int, as_number

logger = logging.getLogger(__name__)

LOAN_SQL = """
SELECT
  IDENTIDAD,
  FECHA_OTORGAMIENTO,
  fVencimiento,
  Ultimo_Pago,
  Cuotas_Mora,
  MTO_APROBADO,
  Cuotas_Pendientes,
  DESTINO
FROM mora
WHERE IDENTIDAD = %s
"""


def get_connection():
    return mysql.connector.connect(**get_db_config())


def _col(row: dict[str, Any], *names: str) -> Any:
    mapped = {str(key).lower(): value for key, value in row.items()}
    for name in names:
        if name.lower() in mapped:
            return mapped[name.lower()]
    return None


def is_refi(destino: Any, overdue: int, pending: int) -> bool:
    text = str(destino or "").strip().upper()
    if any(token in text for token in ("REFINANC", "REFINANCIAMIENTO")):
        return True
    return overdue > 0 or pending > 0


def map_loan(row: dict[str, Any]) -> dict[str, Any]:
    overdue = as_int(_col(row, "Cuotas_Mora"))
    pending = as_int(_col(row, "Cuotas_Pendientes"))
    destino = _col(row, "DESTINO")

    return {
        "fecha_otorgamiento": as_date(_col(row, "FECHA_OTORGAMIENTO")),
        "fecha_vencimiento": as_date(_col(row, "fVencimiento")),
        "fecha_ultimo_realizado": as_date(_col(row, "Ultimo_Pago")),
        "cuotas_mora": overdue,
        "monto_aprobado": as_number(_col(row, "MTO_APROBADO"), 0),
        "cuotas_pendientes": pending,
        "refinanciamiento": is_refi(destino, overdue, pending),
    }


def get_loans(identidad: str, conexion=None) -> list[dict[str, Any]]:
    """Consulta mora y mapea las filas a prestamos."""
    identidad = str(identidad or "").strip()
    own = conexion is None
    if own:
        conexion = get_connection()

    try:
        cursor = conexion.cursor(dictionary=True)
        cursor.execute(LOAN_SQL, (identidad,))
        rows = cursor.fetchall() or []
        cursor.close()
        return [map_loan(row) for row in rows]
    except MySQLError:
        logger.exception("Error consultando mora para identidad %s", identidad)
        raise
    finally:
        if own and conexion is not None and conexion.is_connected():
            conexion.close()
