# Copyright (c) 2025 Patrick Motsch
# All rights reserved.

import logging
import json
from typing import Dict, Any, List
from modules.datamodels.datamodelChat import ActionResult, ActionDocument

logger = logging.getLogger(__name__)

async def mergeTicketData(self, parameters: Dict[str, Any]) -> ActionResult:
    try:
        jiraDataParam = parameters.get("jiraData")
        if not jiraDataParam:
            return ActionResult.isFailure(error="jiraData parameter is required")
        
        existingDataParam = parameters.get("existingData")
        if not existingDataParam:
            return ActionResult.isFailure(error="existingData parameter is required")
        
        taskSyncDefinitionParam = parameters.get("taskSyncDefinition")
        if not taskSyncDefinitionParam:
            return ActionResult.isFailure(error="taskSyncDefinition parameter is required")
        
        idField = parameters.get("idField", "ID")
        
        # Parse taskSyncDefinition
        if isinstance(taskSyncDefinitionParam, str):
            try:
                taskSyncDefinition = json.loads(taskSyncDefinitionParam)
            except json.JSONDecodeError as e:
                return ActionResult.isFailure(error=f"taskSyncDefinition is not valid JSON: {str(e)}")
        elif isinstance(taskSyncDefinitionParam, dict):
            taskSyncDefinition = taskSyncDefinitionParam
        else:
            return ActionResult.isFailure(error=f"taskSyncDefinition must be a dict or JSON string, got {type(taskSyncDefinitionParam)}")
        
        # Get data from documents
        jiraDataJson = self.documentParsing.parseJsonFromDocument(jiraDataParam)
        if jiraDataJson is None or not isinstance(jiraDataJson, list):
            return ActionResult.isFailure(error="Could not parse jiraData as JSON array")
        
        existingDataJson = self.documentParsing.parseJsonFromDocument(existingDataParam)
        if existingDataJson is None or not isinstance(existingDataJson, list):
            # Empty existing data is OK
            existingDataJson = []
        
        # Perform merge
        existingLookup = {row.get(idField): row for row in existingDataJson if row.get(idField)}
        mergedData: List[dict] = []
        changes: List[str] = []
        updatedCount = addedCount = unchangedCount = 0
        
        for jiraRow in jiraDataJson:
            jiraId = jiraRow.get(idField)
            if jiraId and jiraId in existingLookup:
                existingRow = existingLookup[jiraId].copy()
                rowChanges: List[str] = []
                
                for fieldName, fieldConfig in taskSyncDefinition.items():
                    if fieldConfig[0] == 'get':
                        oldValue = "" if existingRow.get(fieldName) is None else str(existingRow.get(fieldName))
                        newValue = "" if jiraRow.get(fieldName) is None else str(jiraRow.get(fieldName))
                        
                        # Convert ADF data to readable text for logging
                        if isinstance(newValue, dict) and newValue.get("type") == "doc":
                            newValueReadable = self.adfConverter.convertAdfToText(newValue)
                            if oldValue != newValueReadable:
                                rowChanges.append(f"{fieldName}: '{oldValue[:100]}...' -> '{newValueReadable[:100]}...'")
                        elif oldValue != newValue:
                            # Truncate long values for logging
                            oldTruncated = oldValue[:100] + "..." if len(oldValue) > 100 else oldValue
                            newTruncated = newValue[:100] + "..." if len(newValue) > 100 else newValue
                            rowChanges.append(f"{fieldName}: '{oldTruncated}' -> '{newTruncated}'")
                        
                        existingRow[fieldName] = jiraRow.get(fieldName)
                
                mergedData.append(existingRow)
                if rowChanges:
                    updatedCount += 1
                    changes.append(f"Row ID {jiraId} updated: {', '.join(rowChanges)}")
                else:
                    unchangedCount += 1
                del existingLookup[jiraId]
            else:
                mergedData.append(jiraRow)
                addedCount += 1
                changes.append(f"Row ID {jiraId} added as new record")
        
        # Add remaining existing rows
        for remaining in existingLookup.values():
            mergedData.append(remaining)
            unchangedCount += 1
        
        mergeDetails = {
            "updated": updatedCount,
            "added": addedCount,
            "unchanged": unchangedCount,
            "changes": changes
        }
        
        logger.info(f"Merged ticket data: {updatedCount} updated, {addedCount} added, {unchangedCount} unchanged")
        
        # Generate filename
        workflowContext = self.services.chat.getWorkflowContext() if hasattr(self.services, 'chat') else None
        filename = self._generateMeaningfulFileName(
            "merged_ticket_data",
            "json",
            workflowContext,
            "mergeTicketData"
        )
        
        result = {
            "data": mergedData,
            "mergeDetails": mergeDetails
        }
        
        validationMetadata = self._createValidationMetadata(
            "mergeTicketData",
            updated=updatedCount,
            added=addedCount,
            unchanged=unchangedCount
        )
        
        document = ActionDocument(
            documentName=filename,
            documentData=json.dumps(result, indent=2, ensure_ascii=False),
            mimeType="application/json",
            validationMetadata=validationMetadata
        )
        
        return ActionResult.isSuccess(documents=[document])
        
    except Exception as e:
        errorMsg = f"Error merging ticket data: {str(e)}"
        logger.error(errorMsg)
        return ActionResult.isFailure(error=errorMsg)

