import pathlib
from pathlib import Path

import dotenv
import requests
from jinja2 import Template
from pydantic import Extra
from requests import Response
from utils import CodeDest, CodeKeys, inject_inline, log

from mealie.schema._mealie import MealieModel

BASE = pathlib.Path(__file__).parent.parent.parent

API_KEY = dotenv.get_key(BASE / ".env", "CROWDIN_API_KEY")


NAMES = {
    "en-US": "American English",
    "en-GB": "British English",
    "af-ZA": "Afrikaans (Afrikaans)",
    "ar-SA": "العربية (Arabic)",
    "ca-ES": "Català (Catalan)",
    "cs-CZ": "Čeština (Czech)",
    "da-DK": "Dansk (Danish)",
    "de-DE": "Deutsch (German)",
    "el-GR": "Ελληνικά (Greek)",
    "es-ES": "Español (Spanish)",
    "fi-FI": "Suomi (Finnish)",
    "fr-FR": "Français (French)",
    "he-IL": "עברית (Hebrew)",
    "hu-HU": "Magyar (Hungarian)",
    "it-IT": "Italiano (Italian)",
    "ja-JP": "日本語 (Japanese)",
    "ko-KR": "한국어 (Korean)",
    "no-NO": "Norsk (Norwegian)",
    "nl-NL": "Nederlands (Dutch)",
    "pl-PL": "Polski (Polish)",
    "pt-BR": "Português do Brasil (Brazilian Portuguese)",
    "pt-PT": "Português (Portuguese)",
    "ro-RO": "Română (Romanian)",
    "ru-RU": "Pусский (Russian)",
    "sr-SP": "српски (Serbian)",
    "sv-SE": "Svenska (Swedish)",
    "tr-TR": "Türkçe (Turkish)",
    "uk-UA": "Українська (Ukrainian)",
    "vi-VN": "Tiếng Việt (Vietnamese)",
    "zh-CN": "简体中文 (Chinese simplified)",
    "zh-TW": "繁體中文 (Chinese traditional)",
}

LOCALE_TEMPLATE = """// This Code is auto generated by gen_global_components.py
export const LOCALES = [{% for locale in locales %}
  {
    name: "{{ locale.name }}",
    value: "{{ locale.locale }}",
    progress: {{ locale.progress }},
  },{% endfor %}
]

"""


class TargetLanguage(MealieModel):
    id: str
    name: str
    locale: str
    threeLettersCode: str
    twoLettersCode: str
    progress: float = 0.0

    class Config:
        extra = Extra.allow


class CrowdinApi:
    project_name = "Mealie"
    project_id = "451976"
    api_key = API_KEY

    def __init__(self, api_key: str):
        api_key = api_key

    @property
    def headers(self) -> dict:
        return {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {self.api_key}",
        }

    def get_projects(self) -> Response:
        return requests.get("https://api.crowdin.com/api/v2/projects", headers=self.headers)

    def get_project(self) -> Response:
        return requests.get(f"https://api.crowdin.com/api/v2/projects/{self.project_id}", headers=self.headers)

    def get_languages(self) -> list[TargetLanguage]:
        response = self.get_project()
        tls = response.json()["data"]["targetLanguages"]

        models = [TargetLanguage(**t) for t in tls]

        models.insert(
            0,
            TargetLanguage(
                id="en-US", name="English", locale="en-US", threeLettersCode="en", twoLettersCode="en", progress=100
            ),
        )

        progress: list[dict] = self.get_progress()["data"]

        for model in models:
            if model.locale in NAMES:
                model.name = NAMES[model.locale]

            for p in progress:
                if p["data"]["languageId"] == model.id:
                    model.progress = p["data"]["translationProgress"]

        models.sort(key=lambda x: x.locale, reverse=True)
        return models

    def get_progress(self) -> dict:
        response = requests.get(
            f"https://api.crowdin.com/api/v2/projects/{self.project_id}/languages/progress?limit=500",
            headers=self.headers,
        )
        return response.json()


PROJECT_DIR = Path(__file__).parent.parent.parent


datetime_dir = PROJECT_DIR / "frontend" / "lang" / "dateTimeFormats"
locales_dir = PROJECT_DIR / "frontend" / "lang" / "messages"
nuxt_config = PROJECT_DIR / "frontend" / "nuxt.config.js"

"""
This snippet walks the message and dat locales directories and generates the import information
for the nuxt.config.js file and automatically injects it into the nuxt.config.js file. Note that
the code generation ID is hardcoded into the script and required in the nuxt config.
"""


def inject_nuxt_values():
    all_date_locales = [
        f'"{match.stem}": require("./lang/dateTimeFormats/{match.name}"),' for match in datetime_dir.glob("*.json")
    ]

    all_langs = []
    for match in locales_dir.glob("*.json"):
        lang_string = f'{{ code: "{match.stem}", file: "{match.name}" }},'
        all_langs.append(lang_string)

    log.debug(f"injecting locales into nuxt config -> {nuxt_config}")
    inject_inline(nuxt_config, CodeKeys.nuxt_local_messages, all_langs)
    inject_inline(nuxt_config, CodeKeys.nuxt_local_dates, all_date_locales)


def generate_locales_ts_file():
    api = CrowdinApi("")
    models = api.get_languages()
    tmpl = Template(LOCALE_TEMPLATE)
    rendered = tmpl.render(locales=models)

    log.debug(f"generating locales ts file -> {CodeDest.use_locales}")
    with open(CodeDest.use_locales, "w") as f:
        f.write(rendered)  # type:ignore


def main():
    if API_KEY is None or API_KEY == "":
        log.error("CROWDIN_API_KEY is not set")
        return

    generate_locales_ts_file()
    inject_nuxt_values()


if __name__ == "__main__":
    main()
