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

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

logger = logging.getLogger(__name__)

async def downloadFileByPath(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")
        
        pathQuery = (parameters.get("pathQuery") or parameters.get("path") or "").strip()
        siteIdParam = parameters.get("siteId")
        filePath = parameters.get("filePath")
        # If filePath looks like full SharePoint path, use as pathQuery fallback
        if not pathQuery and filePath and isinstance(filePath, str) and filePath.strip().startswith("/sites/"):
            pathQuery = filePath.strip()
        
        siteId = None
        innerPath = None
        
        # Option 1: pathQuery provided (e.g. /sites/SiteName/Shared Documents/file.pdf) – resolve site and inner path
        if pathQuery and pathQuery != "*":
            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 pathQuery")
            parsedPath = self.services.sharepoint.extractSiteFromStandardPath(pathQuery)
            if not parsedPath:
                return ActionResult.isFailure(error="pathQuery must be a standard SharePoint path (e.g. /sites/SiteName/Shared Documents/file.pdf)")
            innerPath = (parsedPath.get("innerPath") or "").strip()
            if not innerPath:
                return ActionResult.isFailure(error="pathQuery must include a file path (e.g. /sites/SiteName/Shared Documents/file.pdf)")
            siteId = sites[0].get("id")
            filePath = innerPath
        elif siteIdParam and filePath:
            # Option 2: siteId + filePath provided directly
            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 pathQuery (e.g. /sites/SiteName/Shared Documents/file.pdf) or both siteId and filePath are required")
        
        if not siteId or not filePath:
            return ActionResult.isFailure(error="Could not resolve siteId and file path from parameters")
        
        # Download file (connection/token already set above)
        fileContent = await self.services.sharepoint.downloadFileByPath(
            siteId=siteId,
            filePath=filePath
        )
        
        if fileContent is None:
            return ActionResult.isFailure(error=f"File not found or could not be downloaded: {filePath}")
        
        logger.info(f"Downloaded file from SharePoint: {filePath} ({len(fileContent)} bytes)")
        
        # Generate filename from filePath
        fileName = os.path.basename(filePath) or "downloaded_file"
        workflowContext = self.services.chat.getWorkflowContext() if hasattr(self.services, 'chat') else None
        filename = self._generateMeaningfulFileName(
            fileName.split('.')[0] if '.' in fileName else fileName,
            fileName.split('.')[-1] if '.' in fileName else "bin",
            workflowContext,
            "downloadFileByPath"
        )
        
        # Save to user's Files (FileItem + FileData) via interfaceDbComponent – appears in Files UI
        fileItem = None
        db = getattr(self.services, "interfaceDbComponent", None)
        if db:
            try:
                mimeType = db.getMimeType(filename) if hasattr(db, "getMimeType") else "application/octet-stream"
                fileItem = db.createFile(name=filename, mimeType=mimeType, content=fileContent)
                db.createFileData(fileItem.id, fileContent)
                logger.info(f"Saved SharePoint file to user Files: {filename} (id={fileItem.id})")
            except Exception as e:
                logger.warning(f"Could not save to user Files: {e}")
        
        # Encode as base64 for workflow context (AI, data nodes)
        fileBase64 = base64.b64encode(fileContent).decode('utf-8')
        
        validationMetadata = self._createValidationMetadata(
            "downloadFileByPath",
            siteId=siteId,
            filePath=filePath,
            fileSize=len(fileContent)
        )
        if fileItem:
            validationMetadata["fileId"] = fileItem.id
        
        document = ActionDocument(
            documentName=filename,
            documentData=fileBase64,
            mimeType="application/octet-stream",
            validationMetadata=validationMetadata
        )
        
        return ActionResult.isSuccess(documents=[document])
        
    except Exception as e:
        errorMsg = f"Error downloading file from SharePoint: {str(e)}"
        logger.error(errorMsg)
        return ActionResult.isFailure(error=errorMsg)

