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

"""
Folder Management helper for Outlook operations.
Handles folder ID resolution and folder name lookups.
"""

import logging
import requests
from typing import Dict, Any, Optional, Tuple

logger = logging.getLogger(__name__)

# Microsoft Graph well-known folder path segments (always English in the URL; works for any mailbox UI language).
# See https://learn.microsoft.com/en-us/graph/api/resources/mailfolder
_graphWellKnownSegments = frozenset(
    {
        "inbox",
        "drafts",
        "sentitems",
        "deleteditems",
        "junkemail",
        "outbox",
        "archive",
        "clutter",
        "conflicts",
        "conversationhistory",
        "msgfolderroot",
        "recoverableitemsdeletions",
        "scheduled",
        "searchfolders",
        "syncissues",
    }
)

# Map common user/tool labels (any language) -> Graph well-known segment
_wellKnownAliases: Tuple[Tuple[str, str], ...] = (
    ("inbox", "inbox"),
    ("posteingang", "inbox"),
    ("postfach", "inbox"),
    ("boîte de réception", "inbox"),
    ("boite de reception", "inbox"),
    ("drafts", "drafts"),
    ("draft", "drafts"),
    ("entwürfe", "drafts"),
    ("entwurfe", "drafts"),
    ("brouillons", "drafts"),
    ("brouillon", "drafts"),
    ("sent items", "sentitems"),
    ("sentitems", "sentitems"),
    ("gesendete elemente", "sentitems"),
    ("éléments envoyés", "sentitems"),
    ("elements envoyes", "sentitems"),
    ("deleted items", "deleteditems"),
    ("deleteditems", "deleteditems"),
    ("gelöschte elemente", "deleteditems"),
    ("geloschte elemente", "deleteditems"),
    ("éléments supprimés", "deleteditems"),
    ("junk email", "junkemail"),
    ("junkemail", "junkemail"),
    ("junk-e-mail", "junkemail"),
    ("junk e-mail", "junkemail"),
    ("courrier indésirable", "junkemail"),
    ("outbox", "outbox"),
    ("postausgang", "outbox"),
    ("out box", "outbox"),
    ("archive", "archive"),
    ("archiv", "archive"),
)


def _wellKnownSegmentForName(folderName: str) -> Optional[str]:
    """Return Graph mailFolder segment if folderName is a known default folder alias."""
    if not folderName or not str(folderName).strip():
        return None
    key = str(folderName).strip().lower()
    if key in _graphWellKnownSegments:
        return key
    for alias, segment in _wellKnownAliases:
        if key == alias:
            return segment
    return None


class FolderManagementHelper:
    """Helper for folder management operations"""
    
    def __init__(self, methodInstance):
        """
        Initialize folder management helper.
        
        Args:
            methodInstance: Instance of MethodOutlook (for access to services)
        """
        self.method = methodInstance
        self.services = methodInstance.services
    
    def getFolderId(self, folder_name: str, connection: Dict[str, Any]) -> Optional[str]:
        """
        Get the folder ID for a given folder name or ID.
        Returns the input as-is if it already looks like a Microsoft Graph folder ID.
        """
        if not folder_name or not str(folder_name).strip():
            return None
        # Graph folder IDs are base64-like strings (e.g. AQMk...); return as-is
        s = str(folder_name).strip()
        if s.startswith("AQMk") and len(s) > 20 and " " not in s:
            return s
        try:
            graph_url = "https://graph.microsoft.com/v1.0"
            headers = {
                "Authorization": f"Bearer {connection['accessToken']}",
                "Content-Type": "application/json"
            }

            # Resolve default folders by Graph well-known name (locale-independent; avoids missing "Inbox" on paginated /mailFolders lists)
            wk = _wellKnownSegmentForName(folder_name)
            if wk:
                wk_url = f"{graph_url}/me/mailFolders/{wk}"
                wk_resp = requests.get(wk_url, headers=headers)
                if wk_resp.status_code == 200:
                    wid = wk_resp.json().get("id")
                    if wid:
                        return wid
                logger.debug(
                    f"Well-known folder '{wk}' lookup failed ({wk_resp.status_code}); falling back to folder list"
                )
            
            # Get mail folders (first page only; subfolders / pagination may omit Inbox)
            api_url = f"{graph_url}/me/mailFolders"
            response = requests.get(api_url, headers=headers)
            
            if response.status_code == 200:
                folders_data = response.json()
                all_folders = folders_data.get("value", [])
                

                
                # Try exact match first
                for folder in all_folders:
                    if folder.get("displayName", "").lower() == folder_name.lower():

                        return folder.get("id")
                
                # Try common variations for Drafts folder
                if folder_name.lower() == "drafts":
                    draft_variations = ["drafts", "draft", "entwürfe", "entwurf", "brouillons", "brouillon"]
                    for folder in all_folders:
                        folder_display_name = folder.get("displayName", "").lower()
                        if any(variation in folder_display_name for variation in draft_variations):

                            return folder.get("id")
                
                # Try common variations for other folders
                if folder_name.lower() == "sent items":
                    sent_variations = ["sent items", "sent", "gesendete elemente", "éléments envoyés"]
                    for folder in all_folders:
                        folder_display_name = folder.get("displayName", "").lower()
                        if any(variation in folder_display_name for variation in sent_variations):

                            return folder.get("id")
                
                logger.warning(f"Folder '{folder_name}' not found. Available folders: {[f.get('displayName', 'Unknown') for f in all_folders]}")
                return None
            else:
                logger.warning(f"Could not retrieve folders: {response.status_code}")
                return None
                
        except Exception as e:
            logger.warning(f"Error getting folder ID for '{folder_name}': {str(e)}")
            return None
    
    def getFolderNameById(self, folder_id: str, connection: Dict[str, Any]) -> str:
        """
        Get the folder display name for a given folder ID
        """
        try:
            graph_url = "https://graph.microsoft.com/v1.0"
            headers = {
                "Authorization": f"Bearer {connection['accessToken']}",
                "Content-Type": "application/json"
            }
            
            # Get folder by ID
            api_url = f"{graph_url}/me/mailFolders/{folder_id}"
            response = requests.get(api_url, headers=headers)
            
            if response.status_code == 200:
                folder_data = response.json()
                return folder_data.get("displayName", folder_id)
            else:
                logger.warning(f"Could not retrieve folder name for ID {folder_id}: {response.status_code}")
                return folder_id
                
        except Exception as e:
            logger.warning(f"Error getting folder name for ID '{folder_id}': {str(e)}")
            return folder_id

