"""
Web interface adapter for ConversationManager.

This module provides a web-compatible interface for handling tool permissions
and other interactive prompts via HTTP/SSE.


"""

import logging
import queue
import uuid
from typing import Optional, Dict


logger = logging.getLogger(__name__)


class WebInterface:
    """
    Web interface adapter for handling interactive prompts.

    This class acts as a bridge between ConversationManager and the web UI,
    managing permission requests and responses via queues.
    """

    def __init__(self):
        """Initialise the web interface."""
        self._permission_requests = {}  # request_id -> request_data
        self._permission_responses = {}  # request_id -> response
        self._pending_request_id = None
        # Security prompt confirmation
        self._security_requests = {}  # request_id -> request_data
        self._security_responses = {}  # request_id -> response (True/False)
        self._pending_security_request_id = None

    def prompt_tool_permission(self, tool_name: str, tool_description: str = None) -> Optional[str]:
        """
        Request tool permission from web user.

        This method:
        1. Creates a permission request with a unique ID
        2. Stores it for the web UI to retrieve
        3. Waits for a response (with timeout)
        4. Returns the user's choice

        Args:
            tool_name: Name of the tool
            tool_description: Optional description of the tool

        Returns:
            'allowed' if user grants permission for all future uses
            'denied' if user denies this and all future uses
            'once' if user grants permission for this time only
            None if user cancelled or timeout
        """
        # Generate unique request ID
        request_id = str(uuid.uuid4())

        # Store the permission request
        self._permission_requests[request_id] = {
            'tool_name': tool_name,
            'tool_description': tool_description,
            'status': 'pending'
        }

        # Store the current pending request ID
        self._pending_request_id = request_id

        logger.info(f"Web permission request created: {request_id} for tool: {tool_name}")

        # Wait for response (with timeout)
        # In a real implementation, this would use asyncio or threading.Event
        # For now, we implement a simple polling mechanism
        import time
        timeout_seconds = 300  # 5 minutes timeout
        poll_interval = 0.5  # Poll every 0.5 seconds
        elapsed = 0

        while elapsed < timeout_seconds:
            if request_id in self._permission_responses:
                response = self._permission_responses[request_id]

                # Clean up
                del self._permission_requests[request_id]
                del self._permission_responses[request_id]
                if self._pending_request_id == request_id:
                    self._pending_request_id = None

                logger.info(f"Web permission response received for {request_id}: {response}")
                return response

            time.sleep(poll_interval)
            elapsed += poll_interval

        # Timeout - clean up and return None
        logger.warning(f"Web permission request {request_id} timed out after {timeout_seconds}s")
        if request_id in self._permission_requests:
            del self._permission_requests[request_id]
        if self._pending_request_id == request_id:
            self._pending_request_id = None

        return None

    def get_pending_permission_request(self) -> Optional[Dict]:
        """
        Get the current pending permission request if any.

        Returns:
            Dictionary with request_id, tool_name, tool_description, or None
        """
        if self._pending_request_id and self._pending_request_id in self._permission_requests:
            return {
                'request_id': self._pending_request_id,
                **self._permission_requests[self._pending_request_id]
            }
        return None

    def submit_permission_response(self, request_id: str, response: str) -> bool:
        """
        Submit a response to a pending permission request.

        Args:
            request_id: The request ID
            response: User's response ('once', 'allowed', 'denied', or None for cancel)

        Returns:
            True if response was accepted, False if request not found
        """
        if request_id not in self._permission_requests:
            logger.warning("Permission response submitted for unknown request")
            return False

        # Store the response
        self._permission_responses[request_id] = response

        # Update request status
        self._permission_requests[request_id]['status'] = 'responded'

        logger.info("Permission response submitted and recorded")
        return True

    def prompt_security_confirmation(self, inspection_result) -> bool:
        """
        Request security confirmation from web user for a risky prompt.

        Args:
            inspection_result: The PromptInspectionResult object with details

        Returns:
            True if user confirms to proceed, False otherwise
        """
        # Generate unique request ID
        request_id = str(uuid.uuid4())

        # Extract details from inspection result
        self._security_requests[request_id] = {
            'severity': getattr(inspection_result, 'severity', 'warning'),
            'issues': getattr(inspection_result, 'issues', []),
            'explanation': getattr(inspection_result, 'explanation', ''),
            'patterns': getattr(inspection_result, 'matched_patterns', []),
            'detection_method': getattr(inspection_result, 'detection_method', 'unknown'),
            'status': 'pending'
        }

        self._pending_security_request_id = request_id

        logger.info(f"Web security confirmation request created: {request_id}")

        # Wait for response (with timeout)
        import time
        timeout_seconds = 300  # 5 minutes timeout
        poll_interval = 0.5
        elapsed = 0

        while elapsed < timeout_seconds:
            if request_id in self._security_responses:
                response = self._security_responses[request_id]

                # Clean up
                del self._security_requests[request_id]
                del self._security_responses[request_id]
                if self._pending_security_request_id == request_id:
                    self._pending_security_request_id = None

                logger.info(f"Web security response received for {request_id}: {response}")
                return response

            time.sleep(poll_interval)
            elapsed += poll_interval

        # Timeout - default to deny for security
        logger.warning(f"Web security request {request_id} timed out - denying by default")
        if request_id in self._security_requests:
            del self._security_requests[request_id]
        if self._pending_security_request_id == request_id:
            self._pending_security_request_id = None

        return False

    def get_pending_security_request(self) -> Optional[Dict]:
        """
        Get the current pending security confirmation request if any.

        Returns:
            Dictionary with request details, or None
        """
        if self._pending_security_request_id and self._pending_security_request_id in self._security_requests:
            return {
                'request_id': self._pending_security_request_id,
                **self._security_requests[self._pending_security_request_id]
            }
        return None

    def submit_security_response(self, request_id: str, confirmed: bool) -> bool:
        """
        Submit a response to a pending security confirmation request.

        Args:
            request_id: The request ID
            confirmed: True if user confirms to proceed, False to cancel

        Returns:
            True if response was accepted, False if request not found
        """
        if request_id not in self._security_requests:
            logger.warning("Security response submitted for unknown request")
            return False

        self._security_responses[request_id] = confirmed
        self._security_requests[request_id]['status'] = 'responded'

        logger.info(f"Security response submitted: confirmed={confirmed}")
        return True

    # Compaction status tracking
    def set_compaction_status(self, status: str, message: str = None,
                              original_tokens: int = None, compacted_tokens: int = None,
                              reduction_pct: float = None, elapsed_time: float = None):
        """
        Set the current compaction status for streaming to web UI.

        Args:
            status: Status type ('start', 'progress', 'complete', 'warning', 'error')
            message: Status message to display
            original_tokens: Original token count (for complete status)
            compacted_tokens: Compacted token count (for complete status)
            reduction_pct: Reduction percentage (for complete status)
            elapsed_time: Time taken in seconds (for complete status)
        """
        self._compaction_status = {
            'status': status,
            'message': message,
            'original_tokens': original_tokens,
            'compacted_tokens': compacted_tokens,
            'reduction_pct': reduction_pct,
            'elapsed_time': elapsed_time,
            'timestamp': __import__('time').time()
        }

    def get_compaction_status(self) -> Optional[Dict]:
        """
        Get and clear the current compaction status if any.

        Returns:
            Dictionary with compaction status, or None if no status pending
        """
        status = getattr(self, '_compaction_status', None)
        if status:
            self._compaction_status = None
            return status
        return None

    def clear_compaction_status(self):
        """Clear any pending compaction status."""
        self._compaction_status = None

    # Conflict resolution for orphan tool results
    def prompt_conflict_resolution(self, tool_use_id: str, error_message: str) -> bool:
        """
        Request user confirmation to remove orphan tool_result from history.

        This happens when a request was cancelled mid-tool-execution, leaving
        a tool_result without its corresponding tool_use block.

        Args:
            tool_use_id: The orphan tool_use_id that has no matching tool_use
            error_message: The original error message from the API

        Returns:
            True if user confirms removal, False otherwise
        """
        import time

        # Generate unique request ID
        request_id = str(uuid.uuid4())

        # Store the conflict resolution request
        if not hasattr(self, '_conflict_requests'):
            self._conflict_requests = {}
        if not hasattr(self, '_conflict_responses'):
            self._conflict_responses = {}

        self._conflict_requests[request_id] = {
            'tool_use_id': tool_use_id,
            'error_message': error_message,
            'status': 'pending'
        }

        self._pending_conflict_request_id = request_id

        logger.info(f"Conflict resolution request created: {request_id} for tool_use_id: {tool_use_id}")

        # Wait for response (with timeout)
        timeout_seconds = 300  # 5 minutes timeout
        poll_interval = 0.5
        elapsed = 0

        while elapsed < timeout_seconds:
            if request_id in self._conflict_responses:
                response = self._conflict_responses[request_id]

                # Clean up
                del self._conflict_requests[request_id]
                del self._conflict_responses[request_id]
                if getattr(self, '_pending_conflict_request_id', None) == request_id:
                    self._pending_conflict_request_id = None

                logger.info(f"Conflict resolution response received for {request_id}: {response}")
                return response

            time.sleep(poll_interval)
            elapsed += poll_interval

        # Timeout - default to no action
        logger.warning(f"Conflict resolution request {request_id} timed out")
        if request_id in self._conflict_requests:
            del self._conflict_requests[request_id]
        if getattr(self, '_pending_conflict_request_id', None) == request_id:
            self._pending_conflict_request_id = None

        return False

    def get_pending_conflict_request(self) -> Optional[Dict]:
        """
        Get the current pending conflict resolution request if any.

        Returns:
            Dictionary with request details, or None
        """
        request_id = getattr(self, '_pending_conflict_request_id', None)
        requests = getattr(self, '_conflict_requests', {})

        if request_id and request_id in requests:
            return {
                'request_id': request_id,
                **requests[request_id]
            }
        return None

    def submit_conflict_response(self, request_id: str, remove_orphan: bool) -> bool:
        """
        Submit a response to a pending conflict resolution request.

        Args:
            request_id: The request ID
            remove_orphan: True to remove the orphan tool_result, False to cancel

        Returns:
            True if response was accepted, False if request not found
        """
        requests = getattr(self, '_conflict_requests', {})
        if request_id not in requests:
            logger.warning("Conflict response submitted for unknown request")
            return False

        if not hasattr(self, '_conflict_responses'):
            self._conflict_responses = {}

        self._conflict_responses[request_id] = remove_orphan
        requests[request_id]['status'] = 'responded'

        logger.info(f"Conflict response submitted: remove_orphan={remove_orphan}")
        return True
