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

"""
Site Discovery helper for SharePoint operations.
Handles SharePoint site discovery, filtering, and resolution.
"""

import logging
import urllib.parse
from typing import Dict, Any, List, Optional

logger = logging.getLogger(__name__)

class SiteDiscoveryHelper:
    """Helper for SharePoint site discovery and resolution"""
    
    def __init__(self, methodInstance):
        """
        Initialize site discovery helper.
        
        Args:
            methodInstance: Instance of MethodSharepoint (for access to services)
        """
        self.method = methodInstance
        self.services = methodInstance.services
    
    async def discoverSharePointSites(self, limit: Optional[int] = None) -> List[Dict[str, Any]]:
        """
        Discover SharePoint sites accessible to the user via Microsoft Graph API.
        
        Args:
            limit: Optional limit on number of sites to return
            
        Returns:
            List of site information dictionaries
        """
        try:
            # Query Microsoft Graph to get sites the user has access to
            endpoint = "sites?search=*"
            if limit:
                endpoint += f"&$top={limit}"
            
            result = await self.method.apiClient.makeGraphApiCall(endpoint)
            
            if "error" in result:
                logger.error(f"Error discovering SharePoint sites: {result['error']}")
                return []
            
            sites = result.get("value", [])
            if limit:
                sites = sites[:limit]
            
            logger.info(f"Discovered {len(sites)} SharePoint sites" + (f" (limited to {limit})" if limit else ""))
            
            # Process and return site information
            processedSites = []
            for site in sites:
                siteInfo = {
                    "id": site.get("id"),
                    "displayName": site.get("displayName"),
                    "name": site.get("name"),
                    "webUrl": site.get("webUrl"),
                    "description": site.get("description"),
                    "createdDateTime": site.get("createdDateTime"),
                    "lastModifiedDateTime": site.get("lastModifiedDateTime")
                }
                processedSites.append(siteInfo)
                logger.debug(f"Site: {siteInfo['displayName']} - {siteInfo['webUrl']}")
            
            return processedSites
            
        except Exception as e:
            logger.error(f"Error discovering SharePoint sites: {str(e)}")
            return []
    
    def extractHostnameFromWebUrl(self, webUrl: str) -> Optional[str]:
        """Extract hostname from SharePoint webUrl (e.g., https://pcuster.sharepoint.com)"""
        try:
            if not webUrl:
                return None
            parsed = urllib.parse.urlparse(webUrl)
            return parsed.hostname
        except Exception as e:
            logger.error(f"Error extracting hostname from webUrl '{webUrl}': {str(e)}")
            return None
    
    def extractSiteFromStandardPath(self, pathQuery: str) -> Optional[Dict[str, str]]:
        """
        Extract site name from Microsoft-standard server-relative path.
        Delegates to SharePoint service.
        """
        return self.services.sharepoint.extractSiteFromStandardPath(pathQuery)
    
    async def getSiteByStandardPath(self, sitePath: str) -> Optional[Dict[str, Any]]:
        """
        Get SharePoint site directly by Microsoft-standard path.
        Delegates to SharePoint service.
        """
        return await self.services.sharepoint.getSiteByStandardPath(sitePath)
    
    def filterSitesByHint(self, sites: List[Dict[str, Any]], siteHint: str) -> List[Dict[str, Any]]:
        """
        Filter discovered sites by a human-entered site hint.
        Delegates to SharePoint service.
        """
        return self.services.sharepoint.filterSitesByHint(sites, siteHint)
    
    async def getSiteId(self, hostname: str, sitePath: str) -> str:
        """
        Get SharePoint site ID from hostname and site path.
        
        Args:
            hostname: SharePoint hostname
            sitePath: Site path
            
        Returns:
            Site ID string
        """
        try:
            endpoint = f"sites/{hostname}:/{sitePath}"
            result = await self.method.apiClient.makeGraphApiCall(endpoint)
            
            if "error" in result:
                logger.error(f"Error getting site ID: {result['error']}")
                return ""
            
            return result.get("id", "")
        except Exception as e:
            logger.error(f"Error getting site ID: {str(e)}")
            return ""
    
    async def resolveSitesFromPathQuery(self, pathQuery: str) -> tuple[List[Dict[str, Any]], Optional[str]]:
        """
        Resolve sites from pathQuery using SharePoint service helper methods.
        
        Args:
            pathQuery: Path query string
            
        Returns:
            Tuple of (sites list, error message)
        """
        try:
            # Validate pathQuery format
            isValid, errorMsg = self.services.sharepoint.validatePathQuery(pathQuery)
            if not isValid:
                return [], errorMsg
            
            # Resolve sites using service helper
            sites = await self.services.sharepoint.resolveSitesFromPathQuery(pathQuery)
            if not sites:
                return [], "No SharePoint sites found or accessible"
            
            return sites, None
        except Exception as e:
            logger.error(f"Error resolving sites from pathQuery '{pathQuery}': {str(e)}")
            return [], f"Error resolving sites from pathQuery: {str(e)}"
    
    def parseSiteUrl(self, siteUrl: str) -> Dict[str, str]:
        """Parse SharePoint site URL to extract hostname and site path"""
        try:
            parsed = urllib.parse.urlparse(siteUrl)
            hostname = parsed.hostname
            path = parsed.path.strip('/')
            
            return {
                "hostname": hostname,
                "sitePath": path
            }
        except Exception as e:
            logger.error(f"Error parsing site URL {siteUrl}: {str(e)}")
            return {"hostname": "", "sitePath": ""}

