import type {
    IRouteLocationInterface,
    IRouteParamsInterface,
    IRouteRequestInterface,
    IRouteResponseInterface,
} from "@devowl-wp/api";
import { ERouteHttpVerb } from "@devowl-wp/api";

const routeLocationSupportedLanguagesGet: IRouteLocationInterface = {
    path: "/supported-languages",
    method: ERouteHttpVerb.GET,
};

interface IRouteRequestSupportedLanguagesGet extends IRouteRequestInterface {}

interface IRouteParamsSupportedLanguagesGet extends IRouteParamsInterface {}

interface IRouteResponseSupportedLanguagesGet extends IRouteResponseInterface {
    languages: string[];
}

/**
 * Listing our supported languages.
 *
 * @see https://app.clickup.com/t/863g5edjt (CU-863g5edjt)
 */
enum ESupportedLanguage {
    cs = "cs", // Czech
    da = "da", // Danish
    nl = "nl", // Dutch
    nl_formal = "nl_formal", // Dutch (Formal)
    nl_informal = "nl_informal", // Dutch (Informal)
    en = "en", // English (default)
    es = "es", // Spanish
    fi = "fi", // Finnish
    fr = "fr", // French
    de = "de", // German
    de_formal = "de_formal", // German (Formal)
    de_informal = "de_informal", // German (Informal)
    el = "el", // Greek
    hu = "hu", // Hungarian
    hr = "hr", // Croatian
    it = "it", // Italian
    no = "no", // Norwegian
    pl = "pl", // Polish
    pt = "pt", // Portuguese
    rm = "rm", // Romansh
    sk = "sk", // Slovak
    sl = "sl", // Slovenian
    sv = "sv", // Swedish
}

/**
 * Listing our supported languages mapped to known DeepL API languages.
 */
const deeplLanguageMap: { [key in ESupportedLanguage]?: string } = {
    [ESupportedLanguage.cs]: "cs",
    [ESupportedLanguage.da]: "da",
    [ESupportedLanguage.nl]: "nl",
    [ESupportedLanguage.nl_formal]: "nl_formal",
    [ESupportedLanguage.nl_informal]: "nl_informal",
    [ESupportedLanguage.en]: "en", // or "EN-US" based on preference
    [ESupportedLanguage.es]: "es",
    [ESupportedLanguage.fi]: "fi",
    [ESupportedLanguage.fr]: "fr",
    [ESupportedLanguage.de]: "de",
    [ESupportedLanguage.de_formal]: "de_formal",
    [ESupportedLanguage.de_informal]: "de_informal",
    [ESupportedLanguage.el]: "el",
    [ESupportedLanguage.hu]: "hu",
    [ESupportedLanguage.it]: "it",
    [ESupportedLanguage.no]: "nb",
    [ESupportedLanguage.pl]: "pl",
    [ESupportedLanguage.pt]: "pt-PT", // or "PT-BR" based on preference
    [ESupportedLanguage.rm]: "ro", // Assuming Romansh maps to Romanian, please adjust if different
    [ESupportedLanguage.sk]: "sk",
    [ESupportedLanguage.sl]: "sl", // Slovenian
    [ESupportedLanguage.sv]: "sv",
};
Object.freeze(deeplLanguageMap);

/**
 * Listing our supported languages mapped to known DeepL supported target glossary language codes.
 * Note that some languages are missing because they are not supported by the DeepL API for glossaries.
 *
 * Unsupported languages for glossaries: Czech (cs), Finnish (fi), Greek (el), Hungarian (hu), Slovak (sk)
 *
 * @see https://developers.deepl.com/docs/api-reference/glossaries
 * @see https://app.clickup.com/t/8692xtha4 (CU-8692xtha4)
 * @see https://app.clickup.com/t/8692xtha4?block=block-1845cf8d-14d8-4249-acbb-4ca0dd10de90 (CU-8692xtha4)
 */
const deeplSupportedTargetGlossaryLanguageCodes: { [key in ESupportedLanguage]?: string } = {
    [ESupportedLanguage.da]: "da",
    [ESupportedLanguage.de]: "de",
    [ESupportedLanguage.de_formal]: "de_formal",
    [ESupportedLanguage.de_informal]: "de_informal",
    [ESupportedLanguage.en]: "en",
    [ESupportedLanguage.es]: "es",
    [ESupportedLanguage.fr]: "fr",
    [ESupportedLanguage.it]: "it",
    [ESupportedLanguage.no]: "nb",
    [ESupportedLanguage.nl]: "nl",
    [ESupportedLanguage.nl_formal]: "nl_formal",
    [ESupportedLanguage.nl_informal]: "nl_informal",
    [ESupportedLanguage.pl]: "pl",
    [ESupportedLanguage.pt]: "pt",
    [ESupportedLanguage.rm]: "ro",
    [ESupportedLanguage.sl]: "sl",
    [ESupportedLanguage.sv]: "sv",
};
Object.freeze(deeplSupportedTargetGlossaryLanguageCodes);

/**
 * Listing our supported languages mapped to known Weblate language codes.
 */
const weblateLanguageMap: { [key in ESupportedLanguage]?: string } = {
    [ESupportedLanguage.cs]: "cs", // Czech
    [ESupportedLanguage.da]: "da", // Danish
    [ESupportedLanguage.nl]: "nl", // Dutch (used for Dutch Formal/Informal distinction)
    [ESupportedLanguage.nl_formal]: "nl@formal", // Dutch (Formal)
    [ESupportedLanguage.nl_informal]: "nl@informal", // Dutch (Informal)
    [ESupportedLanguage.en]: "en", // English (default)
    [ESupportedLanguage.es]: "es@formal", // Spanish (Formal)
    [ESupportedLanguage.fi]: "fi", // Finnish
    [ESupportedLanguage.fr]: "fr@formal", // French (Formal)
    [ESupportedLanguage.de]: "de", // German
    [ESupportedLanguage.de_formal]: "de@formal", // German (Formal)
    [ESupportedLanguage.de_informal]: "de@informal", // German (Informal)
    [ESupportedLanguage.el]: "el", // Greek
    [ESupportedLanguage.hu]: "hu", // Hungarian
    [ESupportedLanguage.hr]: "hr", // Croatian
    [ESupportedLanguage.it]: "it@formal", // Italian (Formal)
    [ESupportedLanguage.no]: "nb_NO", // Norwegian (Bokmål)
    [ESupportedLanguage.pl]: "pl@formal", // Polish (Formal)
    [ESupportedLanguage.pt]: "pt@formal", // Portuguese (Formal)
    [ESupportedLanguage.rm]: "ro", // Romansh (no entry in provided data)
    [ESupportedLanguage.sk]: "sk", // Slovak
    [ESupportedLanguage.sl]: "sl", // Slovenian
    [ESupportedLanguage.sv]: "sv", // Swedish
};
Object.freeze(weblateLanguageMap);

/** The T–V distinction is the contextual use of different pronouns that exists in some languages and serves to convey formality or familiarity. */
const TV_DISTINCT_LANGUAGES = [ESupportedLanguage.de, ESupportedLanguage.nl];

/**
 * The default language is English.
 */
const DEFAULT_LANGUAGE = ESupportedLanguage.en;

/**
 * Converts a supported language code to the corresponding Deepl API language code.
 *
 * @param supportedLanguage - The supported language code.
 * @returns - The Deepl API language code, or undefined if the language is not supported.
 */
function getDeeplLanguageCode(supportedLanguage: ESupportedLanguage | string): string | undefined {
    return deeplLanguageMap[supportedLanguage as ESupportedLanguage];
}

/**
 * Converts a supported language code to the corresponding Deepl supported target glossary language code.
 *
 * @param supportedLanguage - The supported language code.
 * @returns - The Deepl supported target glossary language code, or undefined if the language is not supported.
 */
function getDeeplSupportedTargetGlossaryLanguageCode(
    supportedLanguage: ESupportedLanguage | string,
): string | undefined {
    return deeplSupportedTargetGlossaryLanguageCodes[supportedLanguage as ESupportedLanguage];
}

/**
 * Converts a supported language code to the corresponding Weblate language code.
 *
 * @param supportedLanguage - The supported language code.
 * @returns - The Weblate language code, or undefined if the language is not supported.
 */
function getWeblateLanguageCode(supportedLanguage: ESupportedLanguage | string): string | undefined {
    return weblateLanguageMap[supportedLanguage as ESupportedLanguage];
}

/**
 * Find supported languages as key string of ESupportedLanguage.
 */
function getSupportedLanguageKeys() {
    return Object.keys(ESupportedLanguage).filter((language) => {
        return isNaN(Number(language));
    });
}

/**
 * Find supported languages as ESupportedLanguage array.
 */
function getSupportedLanguages(includeTVDistinctLanguages = true) {
    let languages = Object.keys(ESupportedLanguage)
        .filter((language) => {
            return isNaN(Number(language));
        })
        .map((key) => ESupportedLanguage[key] as ESupportedLanguage);

    if (!includeTVDistinctLanguages) {
        languages = languages.filter((lang) => !TV_DISTINCT_LANGUAGES.includes(lang));
    }
    return languages;
}

export {
    DEFAULT_LANGUAGE,
    TV_DISTINCT_LANGUAGES,
    getDeeplLanguageCode,
    getDeeplSupportedTargetGlossaryLanguageCode,
    getSupportedLanguages,
    getSupportedLanguageKeys,
    getWeblateLanguageCode,
    ESupportedLanguage,
    type IRouteParamsSupportedLanguagesGet,
    type IRouteRequestSupportedLanguagesGet,
    type IRouteResponseSupportedLanguagesGet,
    routeLocationSupportedLanguagesGet,
};
