import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { useState, useEffect, useCallback, useMemo, useRef, } from "react";
import { Button } from "../../../components/ui/button";
import { Input } from "../../../components/ui/input";
import { Select } from "../../../components/ui/select";
import { SearchInput } from "../../../components/SearchInput";
import { setupWizardService, providerSupportsModelImport, } from "../../../setup/services/setupWizardService";
import { SetupStepError } from "../SetupStepError";
import { SetupStepBackButton, SetupStepFooter, SetupStepLayout, } from "../SetupStepLayout";
import { LoadingState } from "../../ui/LoadingState";
import { Brain, Image, Hash, RefreshCw, Cloud, Check, CheckCircle2, ArrowRight, } from "lucide-react";
export function ModelSelectionStep({ category, onNext, onSkip, onBack, }) {
    const [loading, setLoading] = useState(false);
    const [providerModels, setProviderModels] = useState([]);
    const [providers, setProviders] = useState([]);
    const [providerTypes, setProviderTypes] = useState([]);
    const [providerTypesLoaded, setProviderTypesLoaded] = useState(false);
    const [selectedProviderId, setSelectedProviderId] = useState(undefined);
    const [error, setError] = useState(null);
    const [manualName, setManualName] = useState("");
    const [creating, setCreating] = useState(false);
    const [filterText, setFilterText] = useState("");
    const [selectedModelFromList, setSelectedModelFromList] = useState(null);
    const [importedModelId, setImportedModelId] = useState(null);
    const autoLoadedProviderRef = useRef(null);
    useEffect(() => {
        // 1. Load providers
        setupWizardService
            .getProviders()
            .then((p) => {
            setProviders(p);
        })
            .catch((e) => setError(e?.message || "Failed to load providers"));
        setupWizardService
            .getProviderTypes()
            .then(setProviderTypes)
            .catch((e) => console.warn("Failed to load provider model import support", e))
            .finally(() => setProviderTypesLoaded(true));
        // 2. Check if a model is already configured for this category
        const checkExisting = async () => {
            try {
                const normalizeId = (id) => id.replace(/[{}()]/g, "").toLowerCase();
                if (category === "embeddings") {
                    const config = await setupWizardService.getEmbeddingsConfig();
                    if (config.modelId) {
                        const normId = normalizeId(config.modelId);
                        const installedModels = await setupWizardService.getInstalledModels();
                        const model = installedModels.find((m) => normalizeId(m.id) === normId);
                        if (model) {
                            setImportedModelId(model.id);
                            setSelectedModelFromList({
                                id: model.name || model.key,
                                name: model.name,
                                modelType: "embeddings",
                                provider: model.providerName || "",
                                inputModalities: [],
                                outputModalities: [],
                                isInstalled: true,
                                installedItemId: model.id,
                                pricingDiffers: false,
                            });
                        }
                    }
                }
                else {
                    const defaults = await setupWizardService.getDefaultModels();
                    const rawId = category === "chat" ? defaults.chatModelId : defaults.imageModelId;
                    if (rawId) {
                        const normId = normalizeId(rawId);
                        const installedModels = await setupWizardService.getInstalledModels();
                        const model = installedModels.find((m) => normalizeId(m.id) === normId);
                        if (model) {
                            setImportedModelId(model.id);
                            setSelectedModelFromList({
                                id: model.name || model.key,
                                name: model.name,
                                modelType: category,
                                provider: model.providerName || "",
                                inputModalities: [],
                                outputModalities: [],
                                isInstalled: true,
                                installedItemId: model.id,
                                pricingDiffers: false,
                            });
                        }
                    }
                }
            }
            catch (e) {
                console.warn("Failed to check existing configuration", e);
            }
        };
        checkExisting();
    }, [category]);
    const selectedProvider = useMemo(() => providers.find((provider) => provider.id === selectedProviderId), [providers, selectedProviderId]);
    const selectedProviderSupportsImport = useMemo(() => providerSupportsModelImport(selectedProvider, providerTypes), [selectedProvider, providerTypes]);
    const isProviderSupportLoading = !!selectedProviderId && !providerTypesLoaded;
    const categoryInfo = useMemo(() => {
        switch (category) {
            case "chat":
                return {
                    title: "Set Default Chat Model",
                    description: "Agents use this model for general chat and content generation.",
                    icon: Brain,
                    templateType: "Ai Chat Model",
                    label: "Chat",
                    confirmationTitle: "Default chat model set",
                    manualActionLabel: "Set as default chat model",
                    defaultActionLabel: "Import and set as default chat model",
                    placeholder: "e.g. gpt-4o",
                };
            case "image":
                return {
                    title: "Set Default Image Model",
                    description: "This model will be used for image generation and editing.",
                    icon: Image,
                    templateType: "Ai Image Model",
                    label: "Image",
                    confirmationTitle: "Default image model set",
                    manualActionLabel: "Set as default image model",
                    defaultActionLabel: "Import and set as default image model",
                    placeholder: "e.g. dall-e-3",
                };
            case "embeddings":
                return {
                    title: "Set Default Embeddings Model",
                    description: "Used for semantic search and content indexing.",
                    icon: Hash,
                    templateType: "Ai Embeddings Model",
                    label: "Embeddings",
                    confirmationTitle: "Default embeddings model set",
                    manualActionLabel: "Set as default embeddings model",
                    defaultActionLabel: "Import and set as default embeddings model",
                    placeholder: "e.g. text-embedding-3-small",
                };
        }
    }, [category]);
    const loadProviderModels = useCallback(async (pId) => {
        const id = pId || selectedProviderId;
        if (!id)
            return;
        try {
            setLoading(true);
            setError(null);
            const models = await setupWizardService.getProviderModels(id);
            setProviderModels(models);
        }
        catch (e) {
            setError(e?.message || "Failed to fetch models from provider");
        }
        finally {
            setLoading(false);
        }
    }, [selectedProviderId]);
    useEffect(() => {
        if (!selectedProviderId || !selectedProviderSupportsImport)
            return;
        if (autoLoadedProviderRef.current === selectedProviderId)
            return;
        autoLoadedProviderRef.current = selectedProviderId;
        loadProviderModels(selectedProviderId);
    }, [
        selectedProviderId,
        selectedProviderSupportsImport,
        loadProviderModels,
    ]);
    const filteredProviderModels = useMemo(() => {
        const categoryModels = providerModels.filter((m) => m.modelType?.toLowerCase() === category.toLowerCase());
        if (!filterText.trim())
            return categoryModels;
        const term = filterText.toLowerCase();
        return categoryModels.filter((m) => m.id.toLowerCase().includes(term) ||
            m.description?.toLowerCase().includes(term));
    }, [providerModels, filterText, category]);
    const handleCreateManual = useCallback(async () => {
        if (!manualName || !selectedProviderId)
            return;
        try {
            setCreating(true);
            setError(null);
            const modelId = await setupWizardService.createModel({
                templateType: categoryInfo.templateType,
                modelName: manualName,
                providerId: selectedProviderId,
            });
            onNext(modelId);
        }
        catch (e) {
            setError(e?.message || "Failed to create model");
        }
        finally {
            setCreating(false);
        }
    }, [manualName, selectedProviderId, categoryInfo, onNext]);
    const handleImportModel = useCallback(async () => {
        if (!selectedProviderId || !selectedModelFromList)
            return;
        try {
            setCreating(true);
            setError(null);
            const result = await setupWizardService.upsertProviderModels({
                providerId: selectedProviderId,
                selectedModelIds: [selectedModelFromList.id],
                mode: "createMissing",
            });
            if (result.errors.length > 0) {
                throw new Error(result.errors[0]);
            }
            const installedModels = await setupWizardService.getInstalledModels();
            const installed = installedModels.find((m) => m.name === selectedModelFromList.id);
            if (installed) {
                setImportedModelId(installed.id);
            }
            else {
                throw new Error("Model imported but could not find the new item");
            }
        }
        catch (e) {
            setError(e?.message || "Failed to import model");
        }
        finally {
            setCreating(false);
        }
    }, [selectedProviderId, selectedModelFromList]);
    const handleContinue = () => {
        if (importedModelId) {
            onNext(importedModelId);
        }
    };
    const handleBackFromConfirmation = () => {
        setImportedModelId(null);
    };
    const footer = importedModelId ? (_jsxs(SetupStepFooter, { children: [_jsx(SetupStepBackButton, { onClick: handleBackFromConfirmation, disabled: creating }), _jsx("div", { className: "flex-1" }), _jsxs(Button, { size: "lg", onClick: handleContinue, disabled: creating || !importedModelId, className: "min-w-[140px]", children: ["Continue", _jsx(ArrowRight, { className: "ml-2 h-4 w-4", strokeWidth: 3 })] })] })) : (_jsxs(SetupStepFooter, { children: [_jsx(SetupStepBackButton, { onClick: onBack, disabled: creating }), _jsx("div", { className: "flex-1" }), _jsx(Button, { variant: "ghost", size: "lg", onClick: onSkip, disabled: creating, children: "Skip category" })] }));
    return (_jsxs(SetupStepLayout, { icon: categoryInfo.icon, title: categoryInfo.title, description: categoryInfo.description, header: importedModelId ? _jsx(_Fragment, {}) : undefined, titleClassName: "mb-2", descriptionClassName: "max-w-[280px] text-sm leading-relaxed", bodyClassName: importedModelId
            ? "flex flex-col justify-center"
            : "space-y-6", footer: footer, children: [importedModelId ? (_jsxs("div", { className: "animate-in fade-in zoom-in mx-auto w-full max-w-md space-y-4 text-center duration-300", children: [_jsx(CheckCircle2, { className: "text-feedback-green mx-auto h-6 w-6", strokeWidth: 1.75 }), _jsxs("div", { className: "space-y-2", children: [_jsx("h3", { className: "text-neutral-grey-100 text-2xl font-medium tracking-normal", children: categoryInfo.confirmationTitle }), _jsx("p", { className: "text-neutral-grey-50 text-sm leading-relaxed", children: categoryInfo.description })] }), _jsxs("div", { className: "bg-neutral-grey-5 flex h-9 items-center gap-2 rounded-md px-3 text-left", children: [_jsx("span", { className: "bg-highlight-100 flex h-4 w-4 shrink-0 items-center justify-center rounded-full text-white", children: _jsx(Check, { className: "h-3 w-3", strokeWidth: 3 }) }), _jsx("span", { className: "text-neutral-grey-100 truncate text-xs font-medium", children: selectedModelFromList?.id })] })] })) : (_jsxs(_Fragment, { children: [_jsx("div", { className: "grid gap-4", children: providers.length > 0 && (_jsxs("div", { className: "space-y-1.5", children: [_jsx("label", { className: "text-neutral-grey-100 mb-1 block text-[14px] font-medium", children: "AI Provider" }), _jsx(Select, { value: selectedProviderId, onValueChange: (id) => {
                                        setSelectedProviderId(id);
                                        setSelectedModelFromList(null);
                                        setProviderModels([]);
                                        setFilterText("");
                                        autoLoadedProviderRef.current = null;
                                    }, options: providers.map((p) => ({
                                        value: p.id,
                                        label: p.name,
                                    })), placeholder: "Select provider...", className: "h-8" })] })) }), !selectedProviderId ? null : isProviderSupportLoading ? (_jsx(LoadingState, { message: "Checking provider...", spinnerClassName: "text-neutral-grey-50", textClassName: "text-neutral-grey-50 text-sm" })) : !selectedProviderSupportsImport ? (_jsxs("div", { className: "animate-in fade-in slide-in-from-bottom-2 space-y-4", children: [_jsxs("div", { className: "space-y-1.5", children: [_jsx("label", { className: "text-neutral-grey-100 mb-1 block text-[14px] font-medium", children: "Model Identifier" }), _jsx(Input, { value: manualName, onChange: (e) => setManualName(e.target.value), placeholder: categoryInfo.placeholder, className: "border-border-default focus:ring-feedback-blue h-8 bg-white" })] }), _jsx("div", { className: "flex justify-center", children: _jsxs(Button, { onClick: handleCreateManual, disabled: creating || !manualName || !selectedProviderId, children: [creating ? (_jsx(RefreshCw, { className: "mr-2 h-4 w-4 animate-spin" })) : null, categoryInfo.manualActionLabel] }) })] })) : (_jsx("div", { className: "animate-in fade-in slide-in-from-bottom-2 space-y-4", children: loading ? (_jsx(LoadingState, { message: "Loading model catalog...", spinnerClassName: "text-neutral-grey-50", textClassName: "text-neutral-grey-50 text-sm" })) : (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "space-y-2", children: [_jsxs("span", { className: "text-neutral-grey-100 mb-1 block text-[14px] font-medium", children: [filteredProviderModels.length, " Models Found"] }), _jsx("div", { className: "group relative", children: _jsx(SearchInput, { placeholder: "Search for a model...", value: filterText, onChange: setFilterText, size: "md", inputClassName: "border-border-default bg-neutral-grey-5 focus:ring-feedback-blue transition-all focus:bg-white" }) }), _jsx("div", { className: "custom-scrollbar divide-border-default border-border-default max-h-[220px] divide-y overflow-y-auto rounded-2xl border bg-white", children: filteredProviderModels.length === 0 ? (_jsx("div", { className: "text-neutral-grey-50 p-12 text-center text-sm font-medium italic", children: providerModels.length === 0
                                                    ? `No ${category} models found.`
                                                    : "No models match your search." })) : (filteredProviderModels.map((model) => {
                                                const isSelected = selectedModelFromList?.id === model.id;
                                                return (_jsxs("label", { className: `group flex w-full cursor-pointer items-start gap-3 px-4 py-3.5 text-left transition-all ${creating
                                                        ? "cursor-not-allowed opacity-50"
                                                        : "hover:bg-neutral-grey-5"}`, children: [_jsx("input", { type: "radio", name: `${category}-model-selection`, checked: isSelected, onChange: () => setSelectedModelFromList(model), disabled: creating, className: "border-neutral-grey-15 checked:border-highlight-100 checked:bg-highlight-100 checked:bg-[radial-gradient(circle,_white_0_35%,_transparent_40%)] focus:ring-highlight-100/20 mt-0.5 h-4 w-4 shrink-0 cursor-pointer appearance-none rounded-full border bg-white transition-colors focus:ring-2 focus:outline-none disabled:cursor-not-allowed" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "text-neutral-grey-100 truncate text-sm font-medium transition-colors", children: model.id }), model.description && (_jsx("div", { className: "text-neutral-grey-50 group-hover:text-neutral-grey-50 mt-0.5 truncate text-[11px] transition-colors", children: model.description }))] })] }, model.id));
                                            })) })] }), _jsx("div", { className: "flex justify-center", children: _jsx(Button, { onClick: handleImportModel, disabled: creating || !selectedModelFromList, children: creating ? (_jsxs(_Fragment, { children: [_jsx(RefreshCw, { className: "mr-2 h-4 w-4 animate-spin" }), "Importing..."] })) : (_jsxs(_Fragment, { children: [_jsx(Cloud, { className: "mr-2 h-4 w-4", strokeWidth: 2.5 }), categoryInfo.defaultActionLabel] })) }) })] })) }))] })), error && _jsx(SetupStepError, { children: error })] }));
}
//# sourceMappingURL=ModelSelectionStep.js.map