import { useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import * as Popover from "@radix-ui/react-popover";
import * as ScrollArea from "@radix-ui/react-scroll-area";
import { Command } from "cmdk";
import { errorDialog } from "@/lib/dialogs.ts";
import { CheckIcon, ChevronDown, LanguagesIcon, Search } from "lucide-react";
import { Preferences } from "@bindings/services";
import { LanguageCode, type Language } from "@bindings/i18n/models.js";
import { HelpText } from "@/components/typography/HelpText";
import { Label } from "@/components/typography/Label";
import { loadLanguages } from "@/lib/i18n";
import { cn } from "@/lib/cn";
import { formatErrorMessage } from "@/lib/errors";

// Intentionally no flag icons here: flags represent countries, not
// languages (German is spoken across DE/AT/CH; English across US/UK/AU/
// etc.). Each label shows the endonym followed by the englishName in
// parentheses when the two differ (e.g. "Deutsch (German)"), in both
// the trigger and the dropdown rows.
// See: https://www.flagsarenotlanguages.com/blog/

const labelFor = (lang: Language): string =>
    lang.englishName && lang.englishName !== lang.displayName
        ? `${lang.displayName} (${lang.englishName})`
        : lang.displayName;

export function LanguagePicker() {
    const { t, i18n } = useTranslation();
    const [languages, setLanguages] = useState<Language[]>([]);
    const [open, setOpen] = useState(false);
    const [busy, setBusy] = useState(false);

    useEffect(() => {
        let cancelled = false;
        loadLanguages()
            .then((list) => {
                if (!cancelled) setLanguages(list);
            })
            .catch(() => {});
        return () => {
            cancelled = true;
        };
    }, []);

    const sorted = useMemo(
        () => [...languages].sort((a, b) => a.displayName.localeCompare(b.displayName)),
        [languages],
    );

    const current = useMemo(
        () =>
            languages.find((l) => l.code === i18n.language) ??
            languages.find((l) => l.code === "en"),
        [languages, i18n.language],
    );

    const select = async (code: string) => {
        if (busy || code === i18n.language) {
            setOpen(false);
            return;
        }
        setBusy(true);
        try {
            await Preferences.SetLanguage(code as LanguageCode);
        } catch (e) {
            await errorDialog({
                Title: t("settings.error.saveTitle"),
                Message: formatErrorMessage(e),
            });
        } finally {
            setBusy(false);
            setOpen(false);
        }
    };

    return (
        <div className={"flex items-center gap-6 justify-between"}>
            <div className={"flex-1 max-w-md"}>
                <Label as={"div"}>{t("settings.general.language.label")}</Label>
                <HelpText margin={false}>{t("settings.general.language.help")}</HelpText>
            </div>
            <div className={"shrink-0"}>
                <Popover.Root open={open} onOpenChange={setOpen}>
                    <Popover.Trigger asChild>
                        <button
                            type={"button"}
                            disabled={busy || languages.length === 0}
                            className={cn(
                                "inline-flex items-center gap-2 h-[40px] px-3 min-w-[240px]",
                                "rounded-md border bg-white dark:bg-nb-gray-900",
                                "border-neutral-200 dark:border-nb-gray-700",
                                "text-xs font-semibold text-nb-gray-100 cursor-default outline-none",
                                "hover:border-nb-gray-600 data-[state=open]:border-nb-gray-600",
                                "disabled:opacity-50",
                            )}
                        >
                            <LanguagesIcon size={16} className={"text-nb-gray-200 shrink-0"} />
                            <span className={"truncate flex-1 text-left"}>
                                {current ? labelFor(current) : "—"}
                            </span>
                            <ChevronDown size={12} className={"text-nb-gray-400 shrink-0"} />
                        </button>
                    </Popover.Trigger>

                    <Popover.Portal>
                        <Popover.Content
                            align={"start"}
                            sideOffset={6}
                            onCloseAutoFocus={(e) => e.preventDefault()}
                            className={cn(
                                "w-[var(--radix-popover-trigger-width)]",
                                "rounded-lg border border-nb-gray-850 bg-nb-gray-920 shadow-lg p-1 z-50",
                                "origin-[var(--radix-popover-content-transform-origin)]",
                                "data-[state=open]:animate-in data-[state=closed]:animate-out",
                                "data-[state=open]:fade-in-0 data-[state=closed]:fade-out-0",
                                "data-[state=open]:zoom-in-95 data-[state=closed]:zoom-out-95",
                                "data-[side=bottom]:slide-in-from-top-1",
                                "data-[side=top]:slide-in-from-bottom-1",
                                "duration-150 ease-out",
                            )}
                        >
                            <Command
                                loop
                                className={cn(
                                    "flex flex-col",
                                    "[&_[cmdk-input-wrapper]]:flex [&_[cmdk-input-wrapper]]:items-center",
                                )}
                            >
                                <div className={"px-1 pb-1"}>
                                    <div className={"group flex items-center gap-2 px-1 h-8"}>
                                        <Search size={14} className={"text-nb-gray-200 shrink-0"} />
                                        <Command.Input
                                            autoFocus
                                            placeholder={t("settings.general.language.search")}
                                            className={cn(
                                                "w-full bg-transparent text-xs text-nb-gray-100 placeholder:text-nb-gray-300",
                                                "outline-none border-none",
                                            )}
                                        />
                                    </div>
                                </div>

                                <ScrollArea.Root type={"auto"} className={"overflow-hidden -mx-1"}>
                                    <ScrollArea.Viewport className={"max-h-64 px-1"}>
                                        <Command.List>
                                            <Command.Empty>
                                                <div
                                                    className={
                                                        "px-3 py-4 text-center text-[0.7rem] text-nb-gray-400"
                                                    }
                                                >
                                                    {t("settings.general.language.empty")}
                                                </div>
                                            </Command.Empty>

                                            {sorted.map((lang) => {
                                                const checked = lang.code === i18n.language;
                                                return (
                                                    <Command.Item
                                                        key={lang.code}
                                                        value={`${lang.displayName} ${lang.englishName} ${lang.code}`}
                                                        onSelect={() => void select(lang.code)}
                                                        className={cn(
                                                            "flex items-center gap-2 px-2 py-2 rounded-md cursor-default outline-none my-0.5",
                                                            "text-xs font-semibold text-nb-gray-200",
                                                            "data-[selected=true]:bg-nb-gray-850 data-[selected=true]:text-nb-gray-50",
                                                        )}
                                                    >
                                                        <span className={"flex-1 min-w-0 truncate"}>
                                                            {labelFor(lang)}
                                                        </span>
                                                        <span
                                                            className={
                                                                "w-4 shrink-0 flex items-center justify-center"
                                                            }
                                                        >
                                                            {checked && (
                                                                <CheckIcon
                                                                    size={14}
                                                                    className={"text-netbird"}
                                                                />
                                                            )}
                                                        </span>
                                                    </Command.Item>
                                                );
                                            })}
                                        </Command.List>
                                    </ScrollArea.Viewport>
                                    <ScrollArea.Scrollbar
                                        orientation={"vertical"}
                                        className={cn(
                                            "flex select-none touch-none transition-colors",
                                            "w-1.5 bg-transparent py-1",
                                        )}
                                    >
                                        <ScrollArea.Thumb
                                            className={
                                                "flex-1 rounded-full bg-nb-gray-800 hover:bg-nb-gray-700 relative"
                                            }
                                        />
                                    </ScrollArea.Scrollbar>
                                </ScrollArea.Root>
                            </Command>
                        </Popover.Content>
                    </Popover.Portal>
                </Popover.Root>
            </div>
        </div>
    );
}
