"""Platform neutralizer validator for removing platform-specific language."""

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

from urarovite.validators.base import BaseValidator, ValidationResult
from urarovite.core.exceptions import ValidationError


class PlatformNeutralizerValidator(BaseValidator):
    """Validator to detect and neutralize platform-specific mentions like Excel/Google Sheets."""

    def __init__(self):
        """Initialize the platform neutralizer validator."""
        super().__init__(
            validator_id="platform_neutralizer",
            name="Neutralize Platform-Specific Language",
            description="Detects 'Excel'/'Google Sheets' mentions in prompts and replaces with neutral phrasing.",
        )

    # Platform-specific terms and their neutral replacements (context-aware)
    PLATFORM_REPLACEMENTS = {
        # Excel variations with context
        r'\bin\s+Excel\s+(?:file|document|workbook|spreadsheet)\b': 'in a spreadsheet',
        r'\bthe\s+Excel\s+(?:file|document|workbook|spreadsheet)\b': 'the spreadsheet',
        r'\ban?\s+Excel\s+(?:file|document|workbook|spreadsheet)\b': 'a spreadsheet',
        r'\bExcel\s+(?:file|document|workbook|spreadsheet)\b': 'spreadsheet',
        r'\bExcel\s+(?:sheet|worksheet)\b': 'worksheet',
        r'\ban?\s+Excel\b': 'a spreadsheet',
        r'\bthe\s+Excel\b': 'the spreadsheet',
        r'\buse\s+Excel\b': 'use a spreadsheet',
        r'\bExcel\b': 'spreadsheet',
        
        # Google Sheets variations with context
        r'\bin\s+Google\s+Sheets?\b': 'in a spreadsheet',
        r'\bthe\s+Google\s+Sheets?\b': 'the spreadsheet',
        r'\ban?\s+Google\s+Sheets?\b': 'a spreadsheet',
        r'\bGoogle\s+Sheets?\b': 'spreadsheet',
        r'\bin\s+Google\s+(?:spreadsheet|workbook)\b': 'in a spreadsheet',
        r'\bthe\s+Google\s+(?:spreadsheet|workbook)\b': 'the spreadsheet',
        r'\bGoogle\s+(?:spreadsheet|workbook)\b': 'spreadsheet',
        
        # File/document combinations
        r'\bGoogle\s+(?:Sheets?\s+)?(?:file|document)\b': 'spreadsheet',
        r'\bExcel\s+(?:chart|graph)\b': 'chart',
        r'\bGoogle\s+(?:Sheets?\s+)?(?:chart|graph)\b': 'chart',
    }

    def validate(
        self,
        sheets_service: Any,
        sheet_id: str,
        mode: str = "flag",
        target_column: str = "prompt",
        **kwargs
    ) -> Dict[str, Any]:
        """Validate and optionally fix platform-specific language in prompts.

        Args:
            sheets_service: Google Sheets service instance
            sheet_id: ID of the sheet to validate
            mode: Either "flag" or "fix"
            target_column: Column to check for platform mentions (default: "prompt")

        Returns:
            Dictionary containing validation results
        """
        result = ValidationResult()

        try:
            # Get all data from the sheet
            all_data, sheet_name = self._get_all_sheet_data(sheets_service, sheet_id)

            if not all_data:
                result.add_error("Sheet is empty or could not be read")
                return result.to_dict()

            headers = all_data[0]
            data_rows = all_data[1:]

            # Find the target column index
            try:
                target_col_index = headers.index(target_column)
            except ValueError:
                result.add_error(f"Column '{target_column}' not found in sheet")
                return result.to_dict()

            prompts_with_platforms = []
            cleaned_prompts = []

            # Check each row for platform mentions
            for row_index, row in enumerate(data_rows, start=2):  # Start at 2 for sheet row numbering
                if target_col_index >= len(row):
                    continue  # Skip rows without enough columns

                prompt_text = row[target_col_index].strip()
                if not prompt_text:
                    continue

                # Find platform mentions
                mentions = self._find_platform_mentions(prompt_text)

                if mentions:
                    if mode == "flag":
                        prompts_with_platforms.append({
                            "row": row_index,
                            "original_text": prompt_text,
                            "mentions": [m["original"] for m in mentions]
                        })
                        result.add_issue()
                    else:  # fix mode
                        cleaned_text, editor_note = self._neutralize_platform_language(prompt_text, mentions)
                        
                        # Update the row data
                        updated_row = row.copy()
                        if len(updated_row) <= target_col_index:
                            # Extend row if needed
                            updated_row.extend([''] * (target_col_index + 1 - len(updated_row)))
                        updated_row[target_col_index] = cleaned_text

                        cleaned_prompts.append({
                            "row": row_index,
                            "original_text": prompt_text,
                            "cleaned_text": cleaned_text.split('\n')[0],  # First line only
                            "editor_note": editor_note,
                            "mentions_neutralized": [m["original"] for m in mentions]
                        })

                        # Replace the row in our data
                        data_rows[row_index - 2] = updated_row
                        result.add_fix()

            if mode == "fix" and result.fixes_applied > 0:
                # Update the sheet with cleaned data
                updated_data = [headers] + data_rows
                self._update_sheet_data(sheets_service, sheet_id, sheet_name, updated_data)

            # Set results
            if mode == "flag":
                result.details["prompts_with_platforms"] = prompts_with_platforms
                if result.issues_found == 0:
                    result.set_automated_log("No platform-specific language found")
                else:
                    result.set_automated_log(f"Found {result.issues_found} prompts with platform-specific language")
            else:
                result.details["cleaned_prompts"] = cleaned_prompts
                if result.fixes_applied == 0:
                    result.set_automated_log("No platform-specific language found")
                else:
                    result.set_automated_log(f"Neutralized platform language in {result.fixes_applied} prompts")

        except ValidationError:
            raise
        except Exception as e:
            result.add_error(f"Unexpected error: {str(e)}")
            result.set_automated_log("Validation failed")

        return result.to_dict()

    def _find_platform_mentions(self, text: str) -> List[Dict[str, str]]:
        """Find platform-specific mentions in text.

        Args:
            text: Text to search

        Returns:
            List of dictionaries with mention details
        """
        mentions = []

        for pattern, replacement in self.PLATFORM_REPLACEMENTS.items():
            matches = re.finditer(pattern, text, re.IGNORECASE)
            for match in matches:
                mentions.append({
                    "original": match.group(),
                    "replacement": replacement,
                    "start_pos": match.start(),
                    "end_pos": match.end(),
                    "pattern": pattern
                })

        # Sort by position and remove overlaps
        mentions.sort(key=lambda x: x["start_pos"])
        
        # Remove overlapping mentions (keep the first/longest)
        filtered_mentions = []
        for mention in mentions:
            overlaps = False
            for existing in filtered_mentions:
                if (mention["start_pos"] < existing["end_pos"] and 
                    mention["end_pos"] > existing["start_pos"]):
                    overlaps = True
                    break
            
            if not overlaps:
                filtered_mentions.append(mention)

        return filtered_mentions

    def _neutralize_platform_language(self, text: str, mentions: List[Dict[str, str]]) -> Tuple[str, str]:
        """Replace platform-specific language with neutral terms.

        Args:
            text: Original text
            mentions: List of mentions to replace

        Returns:
            Tuple of (neutralized_text, editor_note)
        """
        if not mentions:
            return text, ""

        # Work backwards to preserve positions
        cleaned_text = text
        replaced_terms = []

        for mention in reversed(mentions):
            start_pos = mention["start_pos"]
            end_pos = mention["end_pos"]
            replacement = mention["replacement"]
            original = mention["original"]

            # Replace the mention
            cleaned_text = cleaned_text[:start_pos] + replacement + cleaned_text[end_pos:]
            replaced_terms.append(f"'{original}' → '{replacement}'")

        # Generate editor note
        if len(replaced_terms) == 1:
            editor_note = f"[Editor: Neutralized platform language: {replaced_terms[0]}]"
        else:
            editor_note = f"[Editor: Neutralized {len(replaced_terms)} platform terms: {', '.join(replaced_terms)}]"

        # Add editor note to the text
        final_text = f"{cleaned_text}\n\n{editor_note}"

        return final_text, editor_note
