"""
recon_report_py — CloudI Python report generation service.

Receives the matched/unmatched result from recon_engine_py (forwarded by
MwRecon.Orchestrator) plus display config, builds an openpyxl XLSX report,
and returns the file as a base64-encoded string for storage in recon_sessions.report_data.

Service path: /+/recon/report/

cloudi.conf entry:
  [{prefix,        "/+/recon/report/"},
   {file_path,     "/usr/bin/python3"},
   {args,          "/app/services/recon_report_py/main.py"},
   {count_process, 2},
   {max_r,         5},
   {max_t,         120},
   {env, [
     {"PYTHONPATH", "/usr/local/lib/cloudi-2.0.7/api/python:/app/services/recon_report_py"}
   ]}
  ]

Expected request payload (JSON):
  {
    "result": {
      "matched_rows":      [...],
      "unmatched_rows":    [...],
      "matched_count":     N,
      "unmatched_count":   N,
      "total_count":       N,
      "matched_amount":    0.0,
      "unmatched_amount":  0.0,
      "total_amount":      0.0,
      "location_summary":  [...],
      "sheet_matched":     "BankCard-MP-Matched",
      "sheet_unmatched":   "BankCard-MP-Unmatched"
    },
    "config": {
      "hospital_name": "Sahyadri Hospital",
      "recon_type":    "bank_card_vs_momentspay",
      "recon_date":    "2025-06-09"
    }
  }

Response (JSON):
  {
    "status": "ok",
    "data": {
      "report_b64":   "<base64 XLSX>",
      "filename":     "recon_bank_card_vs_momentspay_2025-06-09.xlsx"
    }
  }
"""

import sys
import json
import logging

sys.path.insert(0, "/usr/local/lib/cloudi-2.0.7/api/python/")
sys.path.insert(0, "/app/services/recon_report_py/")

from cloudi import API, terminate_exception
from report_v2 import build_report_v2

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] [CloudI:recon_report_py] %(message)s",
)
logger = logging.getLogger("recon_report_py")


class ReconReportService:
    def __init__(self):
        self.__api = API(0)

    def run(self):
        try:
            self.__api.subscribe("+/recon/report/", self.__handle_request)
            logger.info("recon_report_py started, subscribing to +/recon/report/")
            self.__api.poll()
        except terminate_exception:
            logger.info("recon_report_py terminated cleanly")
        except Exception as e:
            logger.error(f"Service error: {e}", exc_info=True)

    def __handle_request(self, request_type, name, pattern,
                         request_info, request,
                         timeout, priority, trans_id, pid):
        try:
            payload   = json.loads(request)
            info      = json.loads(request_info) if request_info else {}
            trace_id  = info.get("trace_id", "unknown")
            tenant_id = info.get("tenant_id", "unknown")

            if "report_v2" in payload:
                # V2: rendered from persisted recon_matches rows (phase R3)
                report = payload["report_v2"]
                logger.info(
                    f"Building V2 report trace_id={trace_id} tenant_id={tenant_id} "
                    f"rule_set={report.get('name')} stages={len(report.get('stages', []))}"
                )
                report_b64 = build_report_v2(report)
                filename = _make_filename_v2(report)
                logger.info(f"V2 report built trace_id={trace_id} filename={filename}")
                return json.dumps({
                    "status": "ok",
                    "data": {"report_b64": report_b64, "filename": filename},
                })

            # Legacy result/config payloads were removed at R6 cutover.
            return json.dumps({
                "status": "error",
                "reason": "Unsupported payload: expected 'report_v2' "
                          "(legacy result payloads were removed)",
            })

        except Exception as e:
            logger.error(f"Report generation error: {e}", exc_info=True)
            return json.dumps({"status": "error", "reason": str(e)})


def _make_filename_v2(report: dict) -> str:
    name = str(report.get("name", "recon")).replace("_", "-")
    recon_date = report.get("recon_date") or ""
    return f"recon_{name}_{recon_date}.xlsx" if recon_date else f"recon_{name}.xlsx"


if __name__ == "__main__":
    assert API.thread_count() == 1, "Single-threaded service required"
    ReconReportService().run()
