"""Output formatting and file naming utilities."""

import json
import re
from datetime import datetime, timezone
from pathlib import Path
from typing import Optional

from agentgog.zz_models import Result, Task


def sanitize_filename(filename: str) -> str:
    """Sanitize a string for use as a filename.
    
    Removes or replaces characters that are invalid in filenames.
    
    Args:
        filename: The string to sanitize
        
    Returns:
        Sanitized filename
    """
    # Replace forward slashes and other problematic characters
    sanitized = re.sub(r'[/\\<>:"|?*]', '_', filename)
    # Remove any other non-printable or weird characters
    sanitized = re.sub(r'[^\w\-\.]', '_', sanitized)
    # Remove multiple consecutive underscores
    sanitized = re.sub(r'_+', '_', sanitized)
    # Remove leading/trailing underscores
    sanitized = sanitized.strip('_')
    return sanitized


def generate_result_filename(task: Task) -> str:
    """Generate a result filename based on task and model info.
    
    Format: {id}_{provider}_{model}.json
    Example: calcpi_01_openrouter_google_gemma-3-27b-it_free.json
    
    Args:
        task: The task object
        
    Returns:
        Sanitized filename
    """
    model = task.model or "unknown"
    provider = task.provider or "unknown"
    
    # Sanitize each component
    safe_id = sanitize_filename(task.id)
    safe_provider = sanitize_filename(provider)
    safe_model = sanitize_filename(model)
    
    filename = f"{safe_id}_{safe_provider}_{safe_model}.json"
    return filename


def save_result(
    result: Result,
    output_dir: str,
    filename: Optional[str] = None
) -> str:
    """Save a result to a JSON file.
    
    Args:
        result: The result object to save
        output_dir: Directory to save the file
        filename: Optional custom filename (auto-generated if not provided)
        
    Returns:
        Path to the saved file
    """
    output_path = Path(output_dir)
    output_path.mkdir(parents=True, exist_ok=True)
    
    if filename is None:
        # We need task info to generate filename, but we don't have it here
        # So we'll use a generic name based on result fields
        safe_task_id = sanitize_filename(result.task_id)
        safe_provider = sanitize_filename(result.provider)
        safe_model = sanitize_filename(result.model)
        filename = f"{safe_task_id}_{safe_provider}_{safe_model}.json"
    
    filepath = output_path / filename
    
    with open(filepath, 'w') as f:
        json.dump(result.to_dict(), f, indent=2)
    
    return str(filepath)


def create_result(
    task: Task,
    model: str,
    provider: str,
    success: bool,
    execution_time: float,
    mode: str = "chat",
    output: Optional[str] = None,
    error: Optional[str] = None,
    correct: Optional[bool] = None,
    numeric_diff: Optional[float] = None,
    verification_result: Optional[str] = None
) -> Result:
    """Create a Result object from execution data.
    
    Args:
        task: The task that was executed
        model: The model name used
        provider: The provider name used
        success: Whether the command executed successfully
        execution_time: Time taken in seconds
        mode: Mode of execution (chat, code, agent, etc.)
        output: The output content (if any)
        error: Error message (if any)
        correct: Whether the output is correct (if validated)
        numeric_diff: Numeric difference (if applicable)
        verification_result: Raw verification result from agata compare
        
    Returns:
        Result object
    """
    return Result(
        task_id=task.id,
        model=model,
        provider=provider,
        timestamp=datetime.now(timezone.utc).isoformat().replace('+00:00', 'Z'),
        time_sec=execution_time,
        success=success,
        mode=mode,
        correct=correct,
        output=output,
        expected=task.expected,
        error=error,
        validation_type=task.validate,
        numeric_diff=numeric_diff,
        verification_result=verification_result
    )
