# Copyright (c) 2025 Patrick Motsch
# All rights reserved.
"""
Sync trustee positions to accounting (Buha).
Input: featureInstanceId, documentList (reference to processDocuments result message).
Reads positionIds from the document and calls AccountingBridge.pushBatchToAccounting.
"""

import json
import logging
from typing import Dict, Any, List

from modules.datamodels.datamodelChat import ActionResult, ActionDocument
from modules.datamodels.datamodelDocref import DocumentReferenceList

logger = logging.getLogger(__name__)


def _resolveFirstDocument(documentListParam, services) -> Dict[str, Any] | None:
    """Resolve the first document from either Graph-Editor output (list of dicts) or Chat references.

    Returns the parsed JSON dict or None.
    """
    if isinstance(documentListParam, list) and documentListParam:
        first = documentListParam[0]
        if isinstance(first, dict) and ("documentData" in first or "documentName" in first):
            rawData = first.get("documentData")
            if rawData:
                try:
                    return json.loads(rawData) if isinstance(rawData, str) else rawData
                except (json.JSONDecodeError, TypeError):
                    pass

    chatService = getattr(services, "chat", None)
    if not chatService:
        return None

    try:
        docList = DocumentReferenceList.from_string_list(
            documentListParam if isinstance(documentListParam, list) else [documentListParam]
        )
        chatDocuments = chatService.getChatDocumentsFromDocumentList(docList)
        if not chatDocuments:
            return None
        doc = chatDocuments[0]
        rawBytes = chatService.getFileData(doc.fileId)
        if not rawBytes:
            return None
        content = rawBytes.decode("utf-8") if isinstance(rawBytes, bytes) else rawBytes
        return json.loads(content) if isinstance(content, str) else content
    except Exception as e:
        logger.debug("_resolveFirstDocument chat fallback failed: %s", e)
        return None


async def syncToAccounting(self, parameters: Dict[str, Any]) -> ActionResult:
    """
    Push trustee positions to the configured accounting system.
    documentList must reference the message from processDocuments (one document with JSON { positionIds, documentIds }).
    """
    featureInstanceId = parameters.get("featureInstanceId") or (self.services.featureInstanceId if hasattr(self.services, "featureInstanceId") else None)
    documentListParam = parameters.get("documentList")

    if not featureInstanceId:
        return ActionResult.isFailure(error="featureInstanceId is required")
    if not documentListParam:
        return ActionResult.isFailure(error="documentList is required (reference to processDocuments result)")

    try:
        data = _resolveFirstDocument(documentListParam, self.services)
        if data is None:
            return ActionResult.isFailure(error="No document found for documentList; ensure processDocuments ran before this action")

        positionIds = data.get("positionIds") or []
        if not positionIds:
            return ActionResult.isSuccess(documents=[
                ActionDocument(documentName="sync_result", documentData=json.dumps({"pushed": 0, "message": "No positionIds in document"}), mimeType="application/json")
            ])

        from modules.features.trustee.interfaceFeatureTrustee import getInterface as getTrusteeInterface
        from modules.features.trustee.accounting.accountingBridge import AccountingBridge

        trusteeInterface = getTrusteeInterface(
            self.services.user,
            mandateId=self.services.mandateId,
            featureInstanceId=featureInstanceId
        )
        bridge = AccountingBridge(trusteeInterface)
        results = await bridge.pushBatchToAccounting(featureInstanceId, positionIds)
        successCount = sum(1 for r in results if r.success)
        summary = {"pushed": successCount, "total": len(positionIds), "results": [{"positionId": pid, "success": r.success, "error": getattr(r, "errorMessage", None)} for pid, r in zip(positionIds, results)]}

        return ActionResult.isSuccess(documents=[
            ActionDocument(documentName="sync_result", documentData=json.dumps(summary), mimeType="application/json")
        ])
    except Exception as e:
        logger.exception("syncToAccounting failed")
        return ActionResult.isFailure(error=str(e))
