#!/usr/bin/env python3
import polib
from deep_translator import GoogleTranslator
import argparse
import os
import sys
import re


def preserve_braces_content(text):
    """
    Preserve content between braces {} during translation.

    Args:
        text (str): Text that may contain braces

    Returns:
        tuple: (text_with_placeholders, placeholders_dict)
    """
    placeholders = {}
    placeholder_counter = 0

    def replace_braces_content(match):
        nonlocal placeholder_counter
        # Use |||| delimiters that Google Translator is less likely to modify
        placeholder = f"||||{placeholder_counter}||||"
        placeholders[placeholder] = match.group(0)
        placeholder_counter += 1
        return placeholder

    # Replace content between braces with placeholders
    # Updated regex to handle nested braces and more complex patterns
    text_with_placeholders = re.sub(r"\{[^}]*\}", replace_braces_content, text)

    return text_with_placeholders, placeholders


def restore_braces_content(text, placeholders):
    """
    Restore original content between braces from placeholders.

    Args:
        text (str): Translated text with placeholders
        placeholders (dict): Dictionary mapping placeholders to original content

    Returns:
        str: Text with restored braces content
    """
    # Process all placeholders, not just the first one
    for placeholder, original_content in placeholders.items():
        # Try exact match first
        if placeholder in text:
            text = text.replace(placeholder, original_content)
            continue

        # If no exact match, try to handle cases where Google Translator adds spaces
        import re

        number_match = re.search(r"\|\|\|\|(\d+)\|\|\|\|", placeholder)
        if number_match:
            number = number_match.group(1)
            # Try variations with spaces that Google Translator might create
            variations = [
                f"|||| {number} ||||",  # Google added spaces
                f"||||{number} ||||",  # Google added space after number
                f"|||| {number}||||",  # Google added space before number
                f"|||| {number} ||||",  # Google added spaces on both sides
            ]

            for variation in variations:
                if variation in text:
                    text = text.replace(variation, original_content)
                    break  # Found and replaced this placeholder, move to next

    return text


def validate_braces_preservation(original_text, translated_text):
    """
    Validate that braces content was preserved correctly.

    Args:
        original_text (str): Original text with braces
        translated_text (str): Translated text with restored braces

    Returns:
        bool: True if braces content is preserved correctly
    """
    # Extract all content between braces from original text
    original_braces = re.findall(r"\{[^}]*\}", original_text)

    # Extract all content between braces from translated text
    translated_braces = re.findall(r"\{[^}]*\}", translated_text)

    # Check if all original braces content is present in translated text
    for brace_content in original_braces:
        if brace_content not in translated_text:
            return False

    return True


def translate_po_file(
    input_file,
    target_language="es",
    source_language="auto",
    output_file=None,
    force=False,
    verbose=True,
    in_place=True,
):
    """
    Translate a PO file using Google Translator.

    Args:
        input_file (str): Path to the input PO file
        target_language (str, optional): Target language code. Defaults to 'es'.
        source_language (str, optional): Source language code. Defaults to 'auto'.
        output_file (str, optional): Path to the output PO file.
        force (bool, optional): Overwrite existing translations. Defaults to False.
        verbose (bool, optional): Print detailed information. Defaults to True.
        in_place (bool, optional): Replace the original file. Defaults to False.

    Returns:
        tuple: (translated entries count, skipped entries count)
    """
    # If in_place is True, use the input file as output
    if in_place:
        output_file = input_file
    # If no output file specified, create one in the same directory
    elif output_file is None:
        base, ext = os.path.splitext(input_file)
        output_file = f"{base}_translated{ext}"

    # Load the PO file
    try:
        po = polib.pofile(input_file)
    except Exception as e:
        print(f"Error reading PO file: {e}")
        sys.exit(1)

    # Counters
    translated_count = 0
    skipped_count = 0
    error_count = 0

    # Translator instance
    translator = GoogleTranslator(source=source_language, target=target_language)

    # Iterate through PO entries
    for entry in po:
        # Skip entries with comments or references that look like system entries
        if entry.msgid.startswith("Project-Id-Version") or not entry.msgid.strip():
            skipped_count += 1
            continue

        # Check if translation already exists - only translate missing translations
        if entry.msgstr and entry.msgstr.strip() and not force:
            skipped_count += 1
            if verbose:
                print(f"Skipped (already translated): {entry.msgid[:50]}...")
            continue

        try:
            # Show what we're translating
            if verbose:
                print(f"Translating: {entry.msgid[:50]}...")
                if entry.msgstr:
                    print(f"  Current msgstr: '{entry.msgstr}'")
                else:
                    print(f"  No existing translation")

            # Preserve content between braces
            text_with_placeholders, placeholders = preserve_braces_content(entry.msgid)

            # Translate the entry with placeholders
            translated_text_with_placeholders = translator.translate(
                text_with_placeholders
            )

            # Restore original braces content
            translated_text = restore_braces_content(
                translated_text_with_placeholders, placeholders
            )

            # Validate that braces content was preserved
            if not validate_braces_preservation(entry.msgid, translated_text):
                if verbose:
                    print(
                        f"Warning: Braces content not preserved correctly for: {entry.msgid}"
                    )
                    print(f"Original: {entry.msgid}")
                    print(f"Translated: {translated_text}")

            # Update the translation
            entry.msgstr = translated_text
            translated_count += 1

            # Verbose output
            if verbose:
                print(f"  → Translated to: {translated_text[:50]}...")
                if placeholders:
                    print(
                        f"    Preserved braces content: {list(placeholders.values())}"
                    )

        except Exception as e:
            error_count += 1
            if verbose:
                print(f"Translation error for: {entry.msgid}")
                print(f"Error details: {e}")

    # Save the translated file
    po.save(output_file)

    # Print summary
    print("\nTranslation Summary:")
    print(f"- Input file: {input_file}")
    print(f"- Output file: {output_file}")
    print(f"- Target language: {target_language}")
    print(f"- Entries translated: {translated_count}")
    print(f"- Entries skipped: {skipped_count}")
    print(f"- Translation errors: {error_count}")

    return translated_count, skipped_count


def main():
    """
    Command-line interface for PO file translation.
    """
    parser = argparse.ArgumentParser(
        description="Translate PO files using Google Translator"
    )

    parser.add_argument("input_file", help="Path to the input PO file")

    parser.add_argument(
        "-t",
        "--target-language",
        default="es",
        help="Target language code (default: es)",
    )

    parser.add_argument(
        "-s",
        "--source-language",
        default="auto",
        help="Source language code (default: auto)",
    )

    parser.add_argument("-o", "--output-file", help="Path to the output PO file")

    parser.add_argument(
        "-f", "--force", action="store_true", help="Overwrite existing translations"
    )

    parser.add_argument(
        "-v",
        "--verbose",
        action="store_true",
        default=True,
        help="Print detailed translation information (default: True)",
    )

    parser.add_argument(
        "--quiet",
        "-q",
        dest="verbose",
        action="store_false",
        help="Suppress detailed translation information",
    )

    parser.add_argument(
        "-i",
        "--in-place",
        action="store_true",
        help="Replace the original file instead of creating a new one (default behavior)",
    )

    parser.add_argument(
        "--no-in-place",
        action="store_true",
        dest="no_in_place",
        help="Create a new file with _translated suffix instead of replacing the original",
    )

    # Parse arguments
    args = parser.parse_args()

    # Determine in_place value:
    # - Default: True (replace original)
    # - If --no-in-place is set: False (create new file)
    # - If -i is explicitly set: True (replace original, overrides --no-in-place)
    # - If -o is set: False (create new file with specified name)
    if args.output_file:
        args.in_place = False
    elif args.no_in_place and not args.in_place:
        args.in_place = False
    else:
        # Default behavior: in_place = True
        args.in_place = True

    # Validate that in-place and output-file are not used together
    if args.in_place and args.output_file:
        parser.error("Cannot use --in-place (-i) and --output-file (-o) together")

    # Perform translation
    translate_po_file(
        input_file=args.input_file,
        target_language=args.target_language,
        source_language=args.source_language,
        output_file=args.output_file,
        force=args.force,
        verbose=args.verbose,
        in_place=args.in_place,
    )


if __name__ == "__main__":
    main()
