from logging_config import get_logger
from models.bank_mapping import BankMapping
from models.outward_log_model import OutwardLogModel

logger = get_logger(__name__)

class Processor:

    def __init__(self, config, repo, api):
        self.config = config
        self.repo = repo
        self.api = api
        self.mapping = BankMapping(config.BANK_CODE_MAPPING)

    def process(self):
        total_inserted = 0

        logger.info("Starting processing...")

        for bank_code in self.config.bank_codes:

            try:
                logger.info("Processing bank %s", bank_code)

                dccb = self.mapping.get_dccb(bank_code)

                if not dccb:
                    logger.error("No mapping for bank %s", bank_code)
                    continue

                records = self.repo.get_records(dccb)

                if not records:
                    logger.info("No records found for bank %s", bank_code)
                    continue

                payload = {
                    "bankCode": bank_code,
                    "rrn": "090686552",
                    "branchCode": str(records[0]["BR_CODE"]).zfill(3),
                    "itemType": 1,
                    "queueType": "02",
                    "reterieveTop": "20"
                }

                response = self.api.fetch(payload)

                # ✅ Business-level failure logging
                if response.get("status") != "SUCCESS":
                    logger.warning(
                        "API business failure | bank=%s | status=%s | message=%s | response=%s",
                        bank_code,
                        response.get("status"),
                        response.get("message"),
                        response.get("response")
                    )
                    continue

                items = response.get("response", {}).get("VwQueueItems", [])

                if not items:
                    logger.info("No VwQueueItems found for bank %s", bank_code)
                    continue

                # build lookup map
                api_map = {
                    (int(x["queueItemId"]), float(x["txnAmt"])): x
                    for x in items
                    if x.get("queueItemId") and x.get("txnAmt") is not None
                }

                for r in records:

                    try:
                        key = (int(r["CBS_QUEUE_NO2"]), float(r["TXN_AMT"]))
                    except Exception:
                        logger.error("Invalid record data %s", r, exc_info=True)
                        continue

                    item = api_map.get(key)

                    if not item:
                        continue

                    if item.get("status") != "Processed":
                        logger.info(
                            "Skipping non-processed item id=%s status=%s",
                            item.get("queueItemId"),
                            item.get("status")
                        )
                        continue

                    ref = item.get("remarks")

                    if not ref:
                        logger.warning("Missing remarks for item %s", item)
                        continue

                    # duplicate check
                    try:
                        if self.repo.exists_by_ref(ref):
                            logger.info("Duplicate ref %s", ref)
                            continue
                    except Exception:
                        logger.exception("Duplicate check failed for ref %s", ref)
                        continue

                    # build model
                    try:
                        model = OutwardLogModel(bank_code, r, item)
                        data = model.to_dict()
                    except Exception:
                        logger.exception("Model building failed for record %s", r)
                        continue

                    # insert
                    try:
                        self.repo.insert_outward_log(data)
                        total_inserted += 1

                        logger.info(
                            "Inserted record ref=%s journalId=%s",
                            ref,
                            item.get("journalId")
                        )
                    except Exception:
                        logger.exception("Insert failed for ref %s", ref)

            except Exception:
                logger.exception("Error processing bank %s", bank_code)

        logger.info("Processing completed total inserted %s", total_inserted)

        return total_inserted
