import { EIso3166OneAlpha2English } from "../types/iso-3166-one-alpha2/country-key-english.js";
import { EIso3166OneAlpha2German } from "../types/iso-3166-one-alpha2/country-key-german.js";
import {
    EIso3166OneAlpha2,
    EIso3166OneAlpha2AWSCountries,
    EIso3166OneAlpha2AdequacyCountries,
    EIso3166OneAlpha2AkamaiCountries,
    EIso3166OneAlpha2AutomatticCountries,
    EIso3166OneAlpha2BunnyNetCountries,
    EIso3166OneAlpha2CloudflareCountries,
    EIso3166OneAlpha2CountryGroup,
    EIso3166OneAlpha2EeaCountries,
    EIso3166OneAlpha2EuCountries,
    EIso3166OneAlpha2FastlyCountries,
    EIso3166OneAlpha2GcoreCountries,
    EIso3166OneAlpha2GoogleCloudCountries,
    EIso3166OneAlpha2MicrosoftAzureCountries,
} from "../types/iso-3166-one-alpha2/country-key.js";

type TLanguage = "de" | `de_${"formal" | "informal"}` | "en";

/**
 * Get key-value pares as object of countries available in ISO 3166-1 alpha2.
 *
 * @param language Language of values
 * @return key-value object with all countries
 */
function iso3166OneAlpha2KeyValue(language: TLanguage = "en") {
    const defaultTranslations = Object.entries(EIso3166OneAlpha2English);
    const countryCodes = Object.values(EIso3166OneAlpha2);
    let translations: [string, string][];
    const result: Record<string, string> = {};

    switch (language) {
        case "de":
        case "de_formal":
        case "de_informal":
            translations = Object.entries(EIso3166OneAlpha2German);
            break;
        default:
            translations = defaultTranslations;
            break;
    }

    // Fill country codes in result object with translations, and if there is no translation, take it from the default language (en)
    for (const key of countryCodes) {
        const findByKey = ([translationKey]: [string, string]) => translationKey === key;
        result[key] = translations.find(findByKey)?.[1] || defaultTranslations.find(findByKey)?.[1];
    }

    return result;
}

function resolveDataProcessingCountries(countries: string[]) {
    let resolveDataProcessingInCountries = [];
    if (countries) {
        const countryGroups: EIso3166OneAlpha2CountryGroup[] = [];
        const filteredDataProcessingInCountries = countries.filter((entry) => {
            if (entry in EIso3166OneAlpha2CountryGroup) {
                countryGroups.push(entry as EIso3166OneAlpha2CountryGroup);
                return false;
            }
            return true;
        });

        const resolvedCountries = countryGroups
            .map((group) => {
                switch (group) {
                    case EIso3166OneAlpha2CountryGroup.AWS:
                        return Object.values(EIso3166OneAlpha2AWSCountries);
                    case EIso3166OneAlpha2CountryGroup.CLOUDFLARE:
                        return Object.values(EIso3166OneAlpha2CloudflareCountries);
                    case EIso3166OneAlpha2CountryGroup.EEA:
                        return Object.values(EIso3166OneAlpha2EeaCountries);
                    case EIso3166OneAlpha2CountryGroup.EU:
                        return Object.values(EIso3166OneAlpha2EuCountries);
                    case EIso3166OneAlpha2CountryGroup.FASTLY:
                        return Object.values(EIso3166OneAlpha2FastlyCountries);
                    case EIso3166OneAlpha2CountryGroup.GOOGLECLOUD:
                        return Object.values(EIso3166OneAlpha2GoogleCloudCountries);
                    case EIso3166OneAlpha2CountryGroup.AUTOMATTIC:
                        return Object.values(EIso3166OneAlpha2AutomatticCountries);
                    case EIso3166OneAlpha2CountryGroup.AKAMAI:
                        return Object.values(EIso3166OneAlpha2AkamaiCountries);
                    case EIso3166OneAlpha2CountryGroup.BUNNYNET:
                        return Object.values(EIso3166OneAlpha2BunnyNetCountries);
                    case EIso3166OneAlpha2CountryGroup.GCORE:
                        return Object.values(EIso3166OneAlpha2GcoreCountries);
                    case EIso3166OneAlpha2CountryGroup.MICROSOFTAZURE:
                        return Object.values(EIso3166OneAlpha2MicrosoftAzureCountries);
                    default:
                        return [];
                }
            })
            .flat();

        resolveDataProcessingInCountries = [
            ...new Set([...filteredDataProcessingInCountries, ...(resolvedCountries as any)]),
        ];
    }
    return resolveDataProcessingInCountries;
}

function getGdprCountries(): string[] {
    return [
        ...new Set([
            ...Object.values(EIso3166OneAlpha2AdequacyCountries),
            ...Object.values(EIso3166OneAlpha2EeaCountries),
        ]),
    ]
        .filter(Boolean)
        .map((country) => String(country))
        .sort((a, b) => String(a).localeCompare(String(b)));
}

function isEuCountry(countryCode: string): boolean {
    if (!countryCode) return false;
    const normalized = String(countryCode).toUpperCase();
    const euCountries = new Set(
        Object.values(EIso3166OneAlpha2EuCountries).map((countryCode) => String(countryCode).toUpperCase()),
    );
    return euCountries.has(normalized);
}

export type { TLanguage };
export { getGdprCountries, resolveDataProcessingCountries, iso3166OneAlpha2KeyValue, isEuCountry };
