"""Compile the current translation strings files for testing."""
import argparse
import json
from pathlib import Path
import re
from shutil import rmtree
import sys

from . import download, upload
from .const import INTEGRATIONS_DIR
from .util import get_base_arg_parser


def valid_integration(integration):
    """Test if it's a valid integration."""
    if not (INTEGRATIONS_DIR / integration).is_dir():
        raise argparse.ArgumentTypeError(
            f"The integration {integration} does not exist."
        )

    return integration


def get_arguments() -> argparse.Namespace:
    """Get parsed passed in arguments."""
    parser = get_base_arg_parser()
    parser.add_argument(
        "--integration", type=valid_integration, help="Integration to process."
    )
    return parser.parse_args()


def flatten_translations(translations):
    """Flatten all translations."""
    stack = [iter(translations.items())]
    key_stack = []
    flattened_translations = {}
    while stack:
        for k, v in stack[-1]:
            key_stack.append(k)
            if isinstance(v, dict):
                stack.append(iter(v.items()))
                break
            elif isinstance(v, str):
                common_key = "::".join(key_stack)
                flattened_translations[common_key] = v
                key_stack.pop()
        else:
            stack.pop()
            if len(key_stack) > 0:
                key_stack.pop()

    return flattened_translations


def substitute_translation_references(integration_strings, flattened_translations):
    """Recursively processes all translation strings for the integration."""
    result = {}
    for key, value in integration_strings.items():
        if isinstance(value, dict):
            sub_dict = substitute_translation_references(value, flattened_translations)
            result[key] = sub_dict
        elif isinstance(value, str):
            result[key] = substitute_reference(value, flattened_translations)

    return result


def substitute_reference(value, flattened_translations):
    """Substitute localization key references in a translation string."""
    matches = re.findall(r"\[\%key:((?:[\w]+|[:]{2})*)\%\]", value)
    if not matches:
        return value

    new = value
    for key in matches:
        if key in flattened_translations:
            new = new.replace(f"[%key:{key}%]", flattened_translations[key])
        else:
            print(f"Invalid substitution key '{key}' found in string '{value}'")
            sys.exit(1)

    return new


def run():
    """Run the script."""
    args = get_arguments()
    if args.integration:
        integration = args.integration
    else:
        integration = None
        while (
            integration is None
            or not Path(f"homeassistant/components/{integration}").exists()
        ):
            if integration is not None:
                print(f"Integration {integration} doesn't exist!")
                print()
            integration = input("Integration to process: ")

    translations = upload.generate_upload_data()

    if integration not in translations["component"]:
        print("Integration has no strings.json")
        sys.exit(1)

    flattened_translations = flatten_translations(translations)
    integration_strings = translations["component"][integration]

    translations["component"][integration] = substitute_translation_references(
        integration_strings, flattened_translations
    )

    if download.DOWNLOAD_DIR.is_dir():
        rmtree(str(download.DOWNLOAD_DIR))

    download.DOWNLOAD_DIR.mkdir(parents=True)

    (download.DOWNLOAD_DIR / "en.json").write_text(
        json.dumps({"component": {integration: translations["component"][integration]}})
    )

    download.write_integration_translations()

    return 0
