"""Shared helper for writing receipts to Oracle via PACK_CONTAFIN."""
import logging
from datetime import datetime

import oracledb

logger = logging.getLogger(__name__)

_CUI_TO_CONT = {
    "11201891": "6022",   # MOL
    "1590082": "6022",    # OMV Petrom
    "14991381": "6022",   # MOL Romania
    "10562600": "6021",   # Dedeman
}


def _get_cont_cheltuiala(cui: str) -> str:
    cui_clean = cui.upper().replace("RO", "").strip()
    return _CUI_TO_CONT.get(cui_clean, "6028")


def _build_conn_params(oracle_cfg) -> dict:
    if isinstance(oracle_cfg, dict):
        return oracle_cfg
    return {
        "user": oracle_cfg.user,
        "password": oracle_cfg.password,
        "dsn": oracle_cfg.get_dsn(),
    }


def write_receipt(receipt_dict: dict, oracle_cfg, *, commit: bool = True) -> tuple[int, str]:
    """Write a receipt to Oracle ACT_TEMP via PACK_CONTAFIN.

    Args:
        receipt_dict: Keys: partner_name, cui, receipt_date, receipt_number, amount, tva_total
        oracle_cfg: Dict with user/password/dsn, OracleServerConfig instance, or
                    oracledb.Connection (pre-acquired from pool — caller manages lifecycle)
        commit: If False, rolls back after FINALIZEAZA (dry-run mode)

    Returns:
        (cod, mesaj) — Oracle document code and result message from PACK_CONTAFIN
    """
    if isinstance(oracle_cfg, oracledb.Connection):
        conn = oracle_cfg
        own_conn = False
    else:
        conn_params = _build_conn_params(oracle_cfg)
        conn = oracledb.connect(**conn_params)
        own_conn = True
    cursor = conn.cursor()

    try:
        receipt_date = receipt_dict.get("receipt_date")
        _now = datetime.now()
        an = receipt_date.year if receipt_date else _now.year
        luna = receipt_date.month if receipt_date else _now.month
        act_date = receipt_date or _now.date()

        id_util = 0
        id_sucursala = 0

        cursor.callproc("PACK_CONTAFIN.INITIALIZEAZA_SCRIERE_ACT_RUL", [
            id_util,
            datetime.now(),
            an,
            luna,
            0,  # suprascriere_cod
            0,  # suprascriere_anluna
            0,  # scrie_sterge (0=scrie)
            id_sucursala,
        ])

        # Globally unique document COD from sequence (NOT MAX+1 per period —
        # that races and reuses CODs across (AN, LUNA) tuples).
        cursor.execute("SELECT seq_cod.nextval FROM DUAL")
        cod = cursor.fetchone()[0]

        cui = receipt_dict.get("cui") or ""
        cui_clean = cui.upper().replace("RO", "").strip()
        cursor.execute(
            "SELECT ID_PART FROM NOM_PARTENERI WHERE COD_FISCAL = :cui OR COD_FISCAL = :cui2",
            cui=cui_clean, cui2="RO" + cui_clean,
        )
        row = cursor.fetchone()
        id_part = row[0] if row else 0

        total = float(receipt_dict.get("amount") or 0)
        tva = float(receipt_dict.get("tva_total") or 0)
        fara_tva = total - tva
        receipt_number = str(receipt_dict.get("receipt_number") or "")
        nract = int(receipt_number) if receipt_number.isdigit() else 0
        cont = _get_cont_cheltuiala(cui)
        partner_name = receipt_dict.get("partner_name") or "N/A"
        expl = f"OCR: {partner_name}"

        lines = [
            (cont, "401", fara_tva, expl, id_part, 0),
            ("401", "5311", total, f"Plata {expl}", 0, id_part),
        ]
        if tva > 0:
            lines.insert(1, ("4426", "401", tva, f"TVA {expl}", id_part, 0))

        for scd, scc, suma, e, id_partc, id_partd in lines:
            cursor.execute("""
                INSERT INTO ACT_TEMP (
                    LUNA, AN, COD, DATAIREG, DATAACT, NRACT,
                    EXPLICATIA, SCD, SCC, SUMA,
                    ID_PARTC, ID_PARTD, ID_UTIL, DATAORA
                ) VALUES (
                    :luna, :an, :cod, TRUNC(SYSDATE), :dataact, :nract,
                    :expl, :scd, :scc, :suma,
                    :id_partc, :id_partd, :id_util, SYSDATE
                )
            """, luna=luna, an=an, cod=cod, dataact=act_date, nract=nract,
                expl=e, scd=scd, scc=scc, suma=suma,
                id_partc=id_partc, id_partd=id_partd, id_util=id_util)

        mesaj_var = cursor.var(oracledb.STRING, 4000)
        cursor.callproc("PACK_CONTAFIN.FINALIZEAZA_SCRIERE_ACT_RUL", [
            id_util,
            cod,
            0,  # scrie_sterge
            0,  # modificare_nota
            0,  # scrie_cump_vanz
            mesaj_var,
        ])
        mesaj = mesaj_var.getvalue() or ""

        if commit:
            conn.commit()
            logger.info("write_receipt: saved COD=%s mesaj=%r", cod, mesaj)
        else:
            conn.rollback()
            logger.info("write_receipt: dry-run rollback COD would be %s", cod)

        return cod, mesaj

    except Exception:
        conn.rollback()
        raise
    finally:
        cursor.close()
        if own_conn:
            conn.close()
