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

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

logger = logging.getLogger(__name__)

async def uploadFile(self, parameters: Dict[str, Any]) -> ActionResult:
    try:
        connectionReference = parameters.get("connectionReference")
        if not connectionReference:
            return ActionResult.isFailure(error="connectionReference parameter is required")
        
        # Set SharePoint access token first – required before siteDiscovery/sharepoint calls
        connection = self.connection.getMicrosoftConnection(connectionReference)
        if not connection:
            return ActionResult.isFailure(error="No valid Microsoft connection found for the provided connection reference")
        
        contentParam = parameters.get("content")
        if not contentParam:
            return ActionResult.isFailure(error="content parameter is required")
        
        # Resolve siteId and folderPath: pathQuery (path) or explicit siteId+folderPath
        pathQuery = (parameters.get("pathQuery") or parameters.get("path") or "").strip()
        siteIdParam = parameters.get("siteId")
        folderPath = parameters.get("folderPath")
        siteId = None
        
        if pathQuery and pathQuery != "*":
            # Option 1: pathQuery (e.g. /sites/host,siteId,webId/15. Persoenliche Ordner/Ida Dittrich/)
            sites, errorMsg = await self.siteDiscovery.resolveSitesFromPathQuery(pathQuery)
            if errorMsg:
                return ActionResult.isFailure(error=errorMsg)
            if not sites:
                return ActionResult.isFailure(error="Could not resolve site from path")
            parsedPath = self.services.sharepoint.extractSiteFromStandardPath(pathQuery)
            if not parsedPath:
                return ActionResult.isFailure(error="path must be a standard SharePoint path (e.g. /sites/SiteName/Shared Documents/Folder)")
            innerPath = (parsedPath.get("innerPath") or "").strip().rstrip("/")
            siteId = sites[0].get("id")
            folderPath = innerPath
        elif siteIdParam and folderPath:
            # Option 2: explicit siteId + folderPath
            if isinstance(siteIdParam, str):
                from modules.datamodels.datamodelDocref import DocumentReferenceList
                try:
                    docList = DocumentReferenceList.from_string_list([siteIdParam])
                    chatDocuments = self.services.chat.getChatDocumentsFromDocumentList(docList)
                    if chatDocuments and len(chatDocuments) > 0:
                        siteInfoJson = json.loads(chatDocuments[0].documentData)
                        siteId = siteInfoJson.get("id")
                except Exception:
                    pass
                if not siteId:
                    siteId = siteIdParam
            else:
                siteId = siteIdParam
        else:
            return ActionResult.isFailure(error="Either path (e.g. /sites/.../Folder) or both siteId and folderPath are required")
        
        if not siteId:
            return ActionResult.isFailure(error="Could not resolve siteId")
        
        # fileName: from param or from content document
        fileName = parameters.get("fileName")
        if not fileName and contentParam:
            content = contentParam[0] if isinstance(contentParam, (list, tuple)) and contentParam else contentParam
            if isinstance(content, dict):
                fileName = content.get("documentName") or content.get("fileName")
            elif hasattr(content, "documentName"):
                fileName = getattr(content, "documentName", None) or getattr(content, "fileName", None)
            if not fileName:
                fileName = "file"
        
        # Get file content: support inline ActionDocument (from automation2 e.g. sharepoint.downloadFile)
        # or docItem references (chat workflow)
        content = contentParam[0] if isinstance(contentParam, (list, tuple)) and contentParam else contentParam
        fileContentBase64 = None
        if isinstance(content, dict) and content.get("documentData"):
            fileContentBase64 = content.get("documentData")
        elif hasattr(content, "documentData") and content.documentData:
            fileContentBase64 = content.documentData
        elif isinstance(content, dict) and (content.get("validationMetadata") or {}).get("fileId"):
            file_id = content["validationMetadata"]["fileId"]
            try:
                raw = self.services.chat.getFileData(file_id)
                fileContentBase64 = base64.b64encode(raw if isinstance(raw, bytes) else str(raw).encode("utf-8")).decode("utf-8")
            except Exception as e:
                return ActionResult.isFailure(error=f"Could not load file content from fileId {file_id}: {e}")
        if not fileContentBase64:
            from modules.datamodels.datamodelDocref import DocumentReferenceList
            docList = DocumentReferenceList.from_string_list([content] if isinstance(content, str) else content)
            chatDocuments = self.services.chat.getChatDocumentsFromDocumentList(docList)
            if not chatDocuments or len(chatDocuments) == 0:
                return ActionResult.isFailure(error="Could not get file content from document reference")
            fileContentBase64 = chatDocuments[0].documentData
        
        # Decode base64
        try:
            fileContent = base64.b64decode(fileContentBase64)
        except Exception as e:
            return ActionResult.isFailure(error=f"Could not decode base64 file content: {str(e)}")
        
        # Upload file (connection/token already set above)
        uploadResult = await self.services.sharepoint.uploadFile(
            siteId=siteId,
            folderPath=folderPath,
            fileName=fileName,
            content=fileContent
        )
        
        if "error" in uploadResult:
            return ActionResult.isFailure(error=f"Upload failed: {uploadResult['error']}")
        
        logger.info(f"Uploaded file to SharePoint: {folderPath}/{fileName} ({len(fileContent)} bytes)")
        
        # Generate filename
        workflowContext = self.services.chat.getWorkflowContext() if hasattr(self.services, 'chat') else None
        filename = self._generateMeaningfulFileName(
            "file_upload_result",
            "json",
            workflowContext,
            "uploadFile"
        )
        
        result = {
            "success": True,
            "siteId": siteId,
            "filePath": f"{folderPath}/{fileName}",
            "fileSize": len(fileContent),
            "uploadResult": uploadResult
        }
        
        validationMetadata = self._createValidationMetadata(
            "uploadFile",
            siteId=siteId,
            filePath=f"{folderPath}/{fileName}",
            fileSize=len(fileContent)
        )
        
        document = ActionDocument(
            documentName=filename,
            documentData=json.dumps(result, indent=2),
            mimeType="application/json",
            validationMetadata=validationMetadata
        )
        
        return ActionResult.isSuccess(documents=[document])
        
    except Exception as e:
        errorMsg = f"Error uploading file to SharePoint: {str(e)}"
        logger.error(errorMsg)
        return ActionResult.isFailure(error=errorMsg)

