"""
Integrated file attachment service for message processing.
"""

from __future__ import annotations

import logging
from typing import TYPE_CHECKING, Any

from slack_chat_migrator.types import UploadResult
from slack_chat_migrator.utils.logging import log_with_context

if TYPE_CHECKING:
    from slack_chat_migrator.services.chat_adapter import ChatAdapter
    from slack_chat_migrator.services.files.file import FileHandler


class MessageAttachmentProcessor:
    """Handles file attachments during message creation."""

    def __init__(self, file_handler: FileHandler, dry_run: bool = False) -> None:
        """Initialize the attachment processor.

        Args:
            file_handler: The FileHandler instance
            dry_run: Whether to run in dry run mode
        """
        self.file_handler = file_handler
        self.dry_run = dry_run

    def _get_current_channel(self) -> str | None:
        """Return the current channel name for logging context."""
        return self.file_handler.state.context.current_channel

    def process_message_attachments(
        self,
        message: dict[str, Any],
        channel: str,
        space: str | None = None,
        user_id: str | None = None,
        user_service: ChatAdapter | None = None,
        sender_email: str | None = None,
    ) -> list[dict[str, Any]]:
        """Process all file attachments for a message and return attachment payload list.

        Args:
            message: The Slack message containing files
            channel: Channel name for context
            space: Optional space ID where files will be used
            user_id: User ID of the message sender (for external user handling)
            user_service: Optional user-specific Chat service to use for uploads
            sender_email: Optional email of the message sender

        Returns:
            List of attachment objects for Google Chat message payload
        """
        files = message.get("files", [])

        # Also check for files in forwarded message attachments
        attachments = message.get("attachments", [])
        for attachment in attachments:
            # Check if this is a forwarded/shared message with files
            if (
                attachment.get("is_share") or attachment.get("is_msg_unfurl")
            ) and "files" in attachment:
                forwarded_files = attachment.get("files", [])
                files.extend(forwarded_files)
                log_with_context(
                    logging.DEBUG,
                    f"Found {len(forwarded_files)} files in forwarded message attachment",
                    channel=channel,
                )

        if not files:
            return []

        if self.dry_run:
            log_with_context(
                logging.DEBUG,
                f"[DRY RUN] Would process {len(files)} attachments",
                channel=channel,
            )
            # Return mock attachment objects for dry run
            mock_attachments = []
            for i, file_obj in enumerate(files):
                file_name = file_obj.get("name", f"file_{i}")
                mock_attachments.append(
                    {
                        "driveDataRef": {"driveFileId": f"DRY_FILE_{i}_{file_name}"},
                        "contentName": file_name,
                        "contentType": "application/octet-stream",
                        "name": f"attachment-dry-{i}",
                    }
                )
            return mock_attachments

        attachments = []

        log_with_context(
            logging.DEBUG,
            f"Processing {len(files)} attachments for message",
            channel=channel,
        )

        for file_obj in files:
            try:
                # Ensure the file has the user ID from the message if it doesn't have one
                if "user" not in file_obj and user_id:
                    file_obj["user"] = user_id

                # Upload the file using FileHandler
                upload_result = self.file_handler.upload_attachment(
                    file_obj, channel, space, user_service, sender_email
                )

                if upload_result.skipped:
                    log_with_context(
                        logging.DEBUG,
                        f"Skipping attachment (reason: {upload_result.skip_reason or 'unknown'}): {upload_result.name or 'unknown'}",
                        channel=channel,
                        file_id=file_obj.get("id", "unknown"),
                    )
                    continue

                if upload_result.success:
                    attachment = self._create_attachment_from_result(upload_result)
                    if attachment:
                        attachments.append(attachment)
                        log_with_context(
                            logging.DEBUG,
                            f"Added attachment to message: {upload_result.name or 'unknown'}",
                            channel=channel,
                            file_id=file_obj.get("id", "unknown"),
                        )
                    else:
                        log_with_context(
                            logging.WARNING,
                            f"Failed to create attachment from upload result for file: {file_obj.get('name', 'unknown')}",
                            channel=channel,
                            file_id=file_obj.get("id", "unknown"),
                            upload_result_type=upload_result.upload_type or "unknown",
                        )
                else:
                    log_with_context(
                        logging.WARNING,
                        f"Failed to upload file: {file_obj.get('name', 'unknown')}",
                        channel=channel,
                        file_id=file_obj.get("id", "unknown"),
                    )

            except Exception as e:
                log_with_context(
                    logging.ERROR,
                    f"Error processing file attachment: {file_obj.get('name', 'unknown')} - {e!s}",
                    channel=channel,
                    file_id=file_obj.get("id", "unknown"),
                    error=str(e),
                )
                # Continue processing other files even if one fails
                continue

        return attachments

    def _create_attachment_from_result(
        self, upload_result: UploadResult
    ) -> dict[str, Any] | None:
        """Create Google Chat attachment object from upload result.

        Args:
            upload_result: UploadResult from FileHandler.upload_attachment()

        Returns:
            Google Chat attachment object or None if failed
        """
        log_with_context(
            logging.DEBUG,
            f"Creating attachment from upload result: type={upload_result.upload_type}",
            upload_type=upload_result.upload_type,
            channel=self._get_current_channel(),
        )

        if upload_result.upload_type == "drive":
            drive_id = upload_result.drive_id

            log_with_context(
                logging.DEBUG,
                f"Processing Drive attachment: drive_id={drive_id}, file_name={upload_result.name}",
                drive_id=drive_id,
                file_name=upload_result.name,
                channel=self._get_current_channel(),
            )

            if drive_id:
                attachment = {"driveDataRef": {"driveFileId": drive_id}}

                log_with_context(
                    logging.DEBUG,
                    f"Created Drive attachment with driveFileId: {drive_id}",
                    drive_id=drive_id,
                    file_name=upload_result.name,
                    channel=self._get_current_channel(),
                )

                return attachment
            else:
                log_with_context(
                    logging.WARNING,
                    f"Drive upload result missing drive file ID: {upload_result}",
                    channel=self._get_current_channel(),
                )

        elif upload_result.upload_type == "direct":
            attachment_ref = upload_result.attachment_ref
            if attachment_ref and isinstance(attachment_ref, dict):
                log_with_context(
                    logging.DEBUG,
                    f"Using direct upload attachment: {attachment_ref}",
                    attachment_ref=attachment_ref,
                    channel=self._get_current_channel(),
                )
                return attachment_ref
            else:
                log_with_context(
                    logging.WARNING,
                    f"Direct upload result missing or invalid attachment_ref: {upload_result}",
                    channel=self._get_current_channel(),
                )
        else:
            log_with_context(
                logging.WARNING,
                f"Unknown upload result type: {upload_result.upload_type}",
                channel=self._get_current_channel(),
            )

        return None

    def count_message_files(self, message: dict[str, Any]) -> int:
        """Count the number of files in a message.

        Args:
            message: The Slack message object

        Returns:
            Number of files in the message
        """
        if not message or not isinstance(message, dict):
            return 0
        return len(message.get("files", []))

    def has_files(self, message: dict[str, Any]) -> bool:
        """Check if a message has file attachments.

        Args:
            message: The Slack message object

        Returns:
            True if message has files, False otherwise
        """
        return self.count_message_files(message) > 0
