"""
Edit application logic for Google Docs.

Coordinates the application of different editing modes (replace_all, insert_at_line,
regex_replace, append) to Google Docs using the Docs API batch update mechanism.
"""

import logging
from typing import Any, Dict, List, Tuple

from docs.docs_types import EditConfig

from .line_parser import (
    extract_document_text,
    find_line_position,
    get_document_end_index,
    parse_document_lines,
)
from .regex_operations import apply_regex_replacements, validate_regex_operations

logger = logging.getLogger(__name__)


async def apply_edit_config(
    docs_service: Any,
    document_id: str,
    content: str,
    edit_config: EditConfig,
    doc_data: Dict,
) -> Tuple[List[Dict], str]:
    """
    Apply an EditConfig to a document and return the batch update requests.

    Args:
        docs_service: The authenticated Google Docs service
        document_id: The document ID to edit
        content: The content to insert/replace
        edit_config: The EditConfig specifying how to edit
        doc_data: The current document data from docs_service.documents().get()

    Returns:
        Tuple[List[Dict], str]: (batch_update_requests, success_message)

    Raises:
        ValueError: If edit configuration is invalid
    """
    requests: List[Dict] = []

    if edit_config.mode == "replace_all":
        logger.info("[apply_edit_config] Mode: replace_all")

        # Get document end index
        end_index = get_document_end_index(doc_data)

        # Delete all existing content (except required first character)
        if end_index > 1:
            requests.append(
                {
                    "deleteContentRange": {
                        "range": {"startIndex": 1, "endIndex": end_index - 1}
                    }
                }
            )

        # Insert new content at the beginning
        requests.append({"insertText": {"location": {"index": 1}, "text": content}})

        message = "Replaced all document content"

    elif edit_config.mode == "insert_at_line":
        logger.info(
            f"[apply_edit_config] Mode: insert_at_line (line {edit_config.line_number})"
        )

        if not edit_config.line_number:
            raise ValueError("line_number is required for insert_at_line mode")

        # Parse document lines
        lines = parse_document_lines(doc_data)

        # Find the insertion position
        insert_index = find_line_position(lines, edit_config.line_number)

        if insert_index is None:
            # If line not found, append to end
            insert_index = get_document_end_index(doc_data) - 1
            logger.warning(
                f"[apply_edit_config] Line {edit_config.line_number} not found, "
                f"appending to end at index {insert_index}"
            )

        # Insert content at the specified position
        requests.append(
            {
                "insertText": {
                    "location": {"index": insert_index},
                    "text": content + "\n",  # Add newline after inserted content
                }
            }
        )

        message = f"Inserted content at line {edit_config.line_number}"

    elif edit_config.mode == "append":
        logger.info("[apply_edit_config] Mode: append")

        # Get document end index
        end_index = get_document_end_index(doc_data)

        # Insert content at the end (before the final required character)
        requests.append(
            {
                "insertText": {
                    "location": {"index": end_index - 1},
                    "text": "\n" + content,  # Add newline before appended content
                }
            }
        )

        message = "Appended content to end of document"

    elif edit_config.mode == "regex_replace":
        logger.info("[apply_edit_config] Mode: regex_replace")

        if not edit_config.regex_operations:
            raise ValueError("regex_operations is required for regex_replace mode")

        # Validate regex operations first
        is_valid, error_msg = validate_regex_operations(edit_config.regex_operations)
        if not is_valid:
            raise ValueError(f"Invalid regex operations: {error_msg}")

        # Extract document text using comprehensive extraction utility
        current_text = extract_document_text(doc_data)

        logger.info(
            f"[apply_edit_config] Extracted {len(current_text)} characters from document"
        )
        logger.info(f"[apply_edit_config] First 200 chars: {repr(current_text[:200])}")

        # Validate that we extracted some text
        if not current_text or len(current_text) <= 1:
            raise ValueError(
                "No text content found in document. The document may be empty or contain only non-text elements."
            )

        # Apply regex operations
        modified_text, replacement_count = apply_regex_replacements(
            current_text, edit_config.regex_operations
        )

        # Get document end index
        end_index = get_document_end_index(doc_data)

        # Delete all existing content
        if end_index > 1:
            requests.append(
                {
                    "deleteContentRange": {
                        "range": {"startIndex": 1, "endIndex": end_index - 1}
                    }
                }
            )

        # Insert modified content
        requests.append(
            {"insertText": {"location": {"index": 1}, "text": modified_text}}
        )

        message = f"Applied {len(edit_config.regex_operations)} regex operations ({replacement_count} replacements)"

    else:
        raise ValueError(f"Unknown edit mode: {edit_config.mode}")

    logger.info(f"[apply_edit_config] Generated {len(requests)} batch update requests")
    return requests, message
