"""
Enhanced Confluence Operations Module
Comprehensive read, write, and append operations for Confluence content
"""

import logging
import re
from typing import Dict, List, Any, Optional
from .confluence_connector import ConfluenceConnector


class ConfluenceOperations:
    """
    Enhanced operations for Confluence content management.
    Provides comprehensive read, write, append, and advanced functionalities.
    """

    def __init__(self, connector: ConfluenceConnector):
        """
        Initialize operations with a connector instance

        Args:
            connector: ConfluenceConnector instance
        """
        self.connector = connector
        self.logger = logging.getLogger(__name__)

    # ==================== READ OPERATIONS ====================

    def read_page(self, page_id: str, format_type: str = "storage") -> Dict[str, Any]:
        """
        Read page content and metadata

        Args:
            page_id: Page ID
            format_type: Content format (storage, view, export_view)

        Returns:
            Dictionary with page content and metadata
        """
        try:
            # Get page with full metadata
            page = self.connector.get_page_by_id(
                page_id, expand=["body.storage", "body.view", "version", "space", "history", "ancestors"]
            )
            
            # Extract content in requested format
            if format_type == "storage":
                content = page.get("body", {}).get("storage", {}).get("value", "")
            elif format_type == "view":
                content = page.get("body", {}).get("view", {}).get("value", "")
            elif format_type == "export_view":
                content = page.get("body", {}).get("export_view", {}).get("value", "")
            else:
                content = page.get("body", {}).get("storage", {}).get("value", "")

            # Extract comprehensive metadata
            metadata = {
                "id": page.get("id"),
                "title": page.get("title"),
                "type": page.get("type"),
                "space": page.get("space", {}),
                "version": page.get("version", {}),
                "history": page.get("history", {}),
                "ancestors": page.get("ancestors", []),
                "url": f"{self.connector.confluence_url}/pages/viewpage.action?pageId={page_id}",
                "content_format": format_type,
                "created_date": page.get("history", {}).get("createdDate"),
                "modified_date": page.get("version", {}).get("when"),
                "author": page.get("history", {}).get("createdBy", {}),
                "modifier": page.get("version", {}).get("by", {})
            }

            return {
                "content": content,
                "metadata": metadata,
                "success": True
            }

        except Exception as e:
            self.logger.error(f"Failed to read page {page_id}: {e}")
            return {
                "content": "",
                "metadata": {},
                "success": False,
                "error": str(e)
            }

    def read_pages_in_space(self, space_key: str, limit: int = 50, start: int = 0) -> List[Dict[str, Any]]:
        """Read all pages in a space with pagination"""
        try:
            pages = self.connector.get_space_pages(space_key, limit, start)
            results = []

            for page in pages:
                page_data = self.read_page(page.get("id"))
                if page_data["success"]:
                    results.append(page_data)

            return results

        except Exception as e:
            self.logger.error(f"Failed to read pages in space {space_key}: {e}")
            return []

    def read_page_tree(self, page_id: str, max_depth: int = 5) -> Dict[str, Any]:
        """Read page with all children in tree structure"""
        try:
            root_page = self.read_page(page_id)
            if not root_page["success"]:
                return root_page

            tree = {"page": root_page, "children": []}
            self._build_page_tree(page_id, tree["children"], max_depth, 0)
            return tree

        except Exception as e:
            self.logger.error(f"Failed to read page tree for {page_id}: {e}")
            return {"page": {}, "children": [], "error": str(e)}

    def _build_page_tree(self, page_id: str, children_list: List, max_depth: int, current_depth: int):
        """Recursively build page tree"""
        if current_depth >= max_depth:
            return

        try:
            child_pages = self.connector.get_page_children(page_id)
            for child in child_pages:
                child_data = self.read_page(child.get("id"))
                if child_data["success"]:
                    child_node = {"page": child_data, "children": []}
                    children_list.append(child_node)
                    self._build_page_tree(child.get("id"), child_node["children"], max_depth, current_depth + 1)
        except Exception as e:
            self.logger.warning(f"Failed to build tree for {page_id}: {e}")

    def read_attachments(self, page_id: str) -> List[Dict[str, Any]]:
        """Read all attachments for a page with enhanced metadata"""
        try:
            attachments = self.connector.get_page_attachments(page_id)
            results = []

            for attachment in attachments:
                attachment_data = {
                    "id": attachment.get("id"),
                    "title": attachment.get("title"),
                    "type": attachment.get("metadata", {}).get("mediaType"),
                    "size": attachment.get("metadata", {}).get("size"),
                    "download_url": attachment.get("_links", {}).get("download"),
                    "created_date": attachment.get("metadata", {}).get("createdDate"),
                    "modified_date": attachment.get("metadata", {}).get("mediaType"),
                    "explanation": None,
                    "file_extension": attachment.get("title", "").split(".")[-1] if "." in attachment.get("title", "") else "",
                    "comment": attachment.get("metadata", {}).get("comment", "")
                }

                # Try to get explanation for supported types
                try:
                    explanation = self.connector.explain_attachment(page_id, attachment.get("title"))
                    attachment_data["explanation"] = explanation
                except Exception:
                    pass

                results.append(attachment_data)

            return results

        except Exception as e:
            self.logger.error(f"Failed to read attachments for page {page_id}: {e}")
            return []

    def read_comments(self, page_id: str) -> List[Dict[str, Any]]:
        """Read all comments for a page with enhanced metadata"""
        try:
            comments = self.connector.get_page_comments(page_id)
            results = []

            for comment in comments:
                comment_data = {
                    "id": comment.get("id"),
                    "author": comment.get("author", {}).get("displayName"),
                    "author_avatar": comment.get("author", {}).get("avatarUrls", {}).get("48x48"),
                    "created_date": comment.get("createdDate"),
                    "updated_date": comment.get("updatedDate"),
                    "content": comment.get("body", {}).get("storage", {}).get("value", ""),
                    "url": f"{self.connector.confluence_url}/pages/viewpage.action?pageId={page_id}&focusedCommentId={comment.get('id')}",
                    "is_inline": comment.get("isInlineComment", False),
                    "replies": []
                }
                results.append(comment_data)

            return results

        except Exception as e:
            self.logger.error(f"Failed to read comments for page {page_id}: {e}")
            return []

    def read_page_history(self, page_id: str, limit: int = 25) -> List[Dict[str, Any]]:
        """Read page version history"""
        try:
            history = self.connector.get_page_history(page_id, limit)
            return history
        except Exception as e:
            self.logger.error(f"Failed to read history for page {page_id}: {e}")
            return []

    def read_space_info(self, space_key: str) -> Dict[str, Any]:
        """Read comprehensive space information"""
        try:
            space = self.connector.get_space(space_key, expand=["description", "homepage", "metadata"])
            return space
        except Exception as e:
            self.logger.error(f"Failed to read space info for {space_key}: {e}")
            return {}

    # ==================== WRITE OPERATIONS ====================

    def write_page(
        self,
        space_key: str,
        title: str,
        content: str,
        parent_id: Optional[str] = None,
        content_format: str = "storage",
        labels: Optional[List[str]] = None
    ) -> Dict[str, Any]:
        """Write/create a new page with enhanced options"""
        try:
            # Create the page
            page = self.connector.create_page(
                space_key=space_key,
                title=title,
                content=content,
                parent_id=parent_id,
                content_format=content_format
            )

            result = {
                "page_id": page.get("id"),
                "title": page.get("title"),
                "url": f"{self.connector.confluence_url}/pages/viewpage.action?pageId={page.get('id')}",
                "version": page.get("version", {}).get("number"),
                "success": True
            }

            # Add labels if provided
            if labels and page.get("id"):
                try:
                    self.connector.add_labels(page.get("id"), labels)
                    result["labels_added"] = labels
                except Exception as e:
                    self.logger.warning(f"Failed to add labels: {e}")
                    result["labels_error"] = str(e)

            return result

        except Exception as e:
            self.logger.error(f"Failed to write page '{title}': {e}")
            return {
                "page_id": None,
                "title": title,
                "success": False,
                "error": str(e)
            }

    def write_attachment(
        self,
        page_id: str,
        file_path: str,
        comment: Optional[str] = None
    ) -> Dict[str, Any]:
        """Write/upload an attachment to a page"""
        try:
            attachment = self.connector.upload_attachment(page_id, file_path, comment)

            return {
                "attachment_id": attachment.get("id"),
                "title": attachment.get("title"),
                "size": attachment.get("metadata", {}).get("size"),
                "download_url": attachment.get("_links", {}).get("download"),
                "success": True
            }

        except Exception as e:
            self.logger.error(f"Failed to write attachment '{file_path}': {e}")
            return {
                "attachment_id": None,
                "file_path": file_path,
                "success": False,
                "error": str(e)
            }

    def write_comment(self, page_id: str, comment: str) -> Dict[str, Any]:
        """Write/add a comment to a page"""
        try:
            comment_data = self.connector.add_comment(page_id, comment)

            return {
                "comment_id": comment_data.get("id"),
                "url": f"{self.connector.confluence_url}/pages/viewpage.action?pageId={page_id}&focusedCommentId={comment_data.get('id')}",
                "success": True
            }

        except Exception as e:
            self.logger.error(f"Failed to write comment to page {page_id}: {e}")
            return {
                "comment_id": None,
                "success": False,
                "error": str(e)
            }

    def write_space(self, space_key: str, space_name: str, description: str = "") -> Dict[str, Any]:
        """Create a new space"""
        try:
            # This would require additional API endpoints not in current connector
            # For now, return a placeholder
            return {
                "space_key": space_key,
                "space_name": space_name,
                "success": False,
                "error": "Space creation not implemented in current connector version"
            }
        except Exception as e:
            return {"success": False, "error": str(e)}

    # ==================== APPEND OPERATIONS ====================

    def append_to_page(
        self,
        page_id: str,
        content_to_append: str,
        separator: str = "\n\n"
    ) -> Dict[str, Any]:
        """Append content to an existing page"""
        try:
            # Read current content
            current_data = self.read_page(page_id)
            if not current_data["success"]:
                return current_data

            # Append new content
            updated_content = current_data["content"] + separator + content_to_append

            # Update the page
            updated_page = self.connector.update_page(
                page_id=page_id,
                content=updated_content,
                content_format="storage"
            )

            return {
                "page_id": page_id,
                "original_length": len(current_data["content"]),
                "appended_length": len(content_to_append),
                "final_length": len(updated_content),
                "new_version": updated_page.get("version", {}).get("number"),
                "success": True
            }

        except Exception as e:
            self.logger.error(f"Failed to append to page {page_id}: {e}")
            return {
                "page_id": page_id,
                "success": False,
                "error": str(e)
            }

    def append_comment_to_page(self, page_id: str, comment: str) -> Dict[str, Any]:
        """Append a comment to a page (alias for write_comment)"""
        return self.write_comment(page_id, comment)

    # ==================== SEARCH OPERATIONS ====================

    def search_content(
        self,
        query: str,
        content_type: str = "page",
        limit: int = 25,
        space_key: Optional[str] = None
    ) -> List[Dict[str, Any]]:
        """Search for content with enhanced options"""
        try:
            # Build CQL query
            cql = f'type="{content_type}"'
            if space_key:
                cql += f' and space="{space_key}"'
            if query and not query.startswith('type='):
                cql += f' and {query}'
            elif query:
                cql = query

            results = self.connector.search_content(cql, limit=limit)
            return results

        except Exception as e:
            self.logger.error(f"Failed to search content: {e}")
            return []

    def search_pages_by_label(self, label: str, space_key: Optional[str] = None, limit: int = 25) -> List[Dict[str, Any]]:
        """Search pages by label"""
        cql = f'label="{label}"'
        if space_key:
            cql += f' and space="{space_key}"'
        return self.search_content(cql, "page", limit)

    def search_pages_by_text(self, text: str, space_key: Optional[str] = None, limit: int = 25) -> List[Dict[str, Any]]:
        """Search pages containing specific text"""
        cql = f'text~"{text}"'
        if space_key:
            cql += f' and space="{space_key}"'
        return self.search_content(cql, "page", limit)

    # ==================== BATCH OPERATIONS ====================

    def batch_read_pages(self, page_ids: List[str]) -> List[Dict[str, Any]]:
        """Read multiple pages in batch"""
        results = []
        for page_id in page_ids:
            page_data = self.read_page(page_id)
            results.append(page_data)
        return results

    def batch_write_pages(
        self,
        pages_data: List[Dict[str, Any]]
    ) -> List[Dict[str, Any]]:
        """Write multiple pages in batch"""
        results = []
        for page_data in pages_data:
            result = self.write_page(
                space_key=page_data.get("space_key"),
                title=page_data.get("title"),
                content=page_data.get("content"),
                parent_id=page_data.get("parent_id"),
                labels=page_data.get("labels")
            )
            results.append(result)
        return results

    def batch_add_labels(self, page_ids: List[str], labels: List[str]) -> Dict[str, Any]:
        """Add labels to multiple pages in batch"""
        results = {"success": [], "failed": []}

        for page_id in page_ids:
            try:
                self.connector.add_labels(page_id, labels)
                results["success"].append(page_id)
            except Exception as e:
                self.logger.warning(f"Failed to add labels to page {page_id}: {e}")
                results["failed"].append({"page_id": page_id, "error": str(e)})

        return results

    # ==================== UTILITY OPERATIONS ====================

    def extract_text_from_page(self, page_id: str, include_metadata: bool = False) -> Dict[str, Any]:
        """Extract plain text from page content"""
        try:
            return self.connector.extract_text_from_page(page_id, include_metadata)
        except Exception as e:
            self.logger.error(f"Failed to extract text from page {page_id}: {e}")
            return {
                "text": "",
                "metadata": {},
                "success": False,
                "error": str(e)
            }

    def copy_page(
        self,
        page_id: str,
        destination_space_key: Optional[str] = None,
        destination_parent_id: Optional[str] = None,
        new_title: Optional[str] = None
    ) -> Dict[str, Any]:
        """Copy a page to a new location"""
        try:
            copied_page = self.connector.copy_page(
                page_id=page_id,
                destination_page_id=destination_parent_id,
                space_key=destination_space_key,
                title=new_title
            )

            return {
                "original_page_id": page_id,
                "new_page_id": copied_page.get("id"),
                "new_title": copied_page.get("title"),
                "new_url": f"{self.connector.confluence_url}/pages/viewpage.action?pageId={copied_page.get('id')}",
                "success": True
            }

        except Exception as e:
            self.logger.error(f"Failed to copy page {page_id}: {e}")
            return {
                "original_page_id": page_id,
                "success": False,
                "error": str(e)
            }

    def move_page(
        self,
        page_id: str,
        destination_space_key: str,
        destination_parent_id: Optional[str] = None
    ) -> Dict[str, Any]:
        """Move a page to a new location"""
        try:
            # This would require additional API endpoints
            return {
                "page_id": page_id,
                "success": False,
                "error": "Page move not implemented in current connector version"
            }
        except Exception as e:
            return {"success": False, "error": str(e)}

    def delete_page(self, page_id: str) -> Dict[str, Any]:
        """Delete a page"""
        try:
            # This would require additional API endpoints
            return {
                "page_id": page_id,
                "success": False,
                "error": "Page deletion not implemented in current connector version"
            }
        except Exception as e:
            return {"success": False, "error": str(e)}

    def get_page_statistics(self, page_id: str) -> Dict[str, Any]:
        """Get comprehensive page statistics"""
        try:
            page_data = self.read_page(page_id)
            if not page_data["success"]:
                return page_data

            attachments = self.read_attachments(page_id)
            comments = self.read_comments(page_id)
            children = self.connector.get_page_children(page_id)

            stats = {
                "page_id": page_id,
                "title": page_data["metadata"]["title"],
                "content_length": len(page_data["content"]),
                "word_count": len(page_data["content"].split()),
                "character_count": len(page_data["content"]),
                "attachment_count": len(attachments),
                "comment_count": len(comments),
                "child_page_count": len(children),
                "version": page_data["metadata"]["version"]["number"],
                "created_date": page_data["metadata"]["created_date"],
                "modified_date": page_data["metadata"]["modified_date"],
                "has_attachments": len(attachments) > 0,
                "has_comments": len(comments) > 0,
                "has_children": len(children) > 0
            }

            return {"statistics": stats, "success": True}

        except Exception as e:
            return {"statistics": {}, "success": False, "error": str(e)}

    def export_page_content(self, page_id: str, format_type: str = "html") -> Dict[str, Any]:
        """Export page content in various formats"""
        try:
            page_data = self.read_page(page_id, "storage")
            if not page_data["success"]:
                return page_data

            content = page_data["content"]
            
            if format_type == "html":
                # Convert Confluence storage format to clean HTML
                # This would require HTML parsing libraries
                return {
                    "content": content,
                    "format": format_type,
                    "page_id": page_id,
                    "success": True
                }
            elif format_type == "text":
                # Extract plain text
                text = re.sub(r'<[^>]+>', '', content)
                text = re.sub(r'\s+', ' ', text).strip()
                return {
                    "content": text,
                    "format": format_type,
                    "page_id": page_id,
                    "success": True
                }
            elif format_type == "markdown":
                # Convert Confluence storage format to Markdown
                # This would require conversion logic
                return {
                    "content": content,
                    "format": format_type,
                    "page_id": page_id,
                    "success": True,
                    "note": "Markdown conversion not implemented"
                }
            else:
                return {
                    "content": content,
                    "format": "storage",
                    "page_id": page_id,
                    "success": True
                }

        except Exception as e:
            return {
                "content": "",
                "format": format_type,
                "page_id": page_id,
                "success": False,
                "error": str(e)
            }

    def close(self):
        """Close the connection"""
        if hasattr(self.connector, 'close'):
            self.connector.close()
            self.logger.info("Confluence operations session closed")
