import { jsx as _jsx } from "react/jsx-runtime";
import React from 'react';
import { useLocalStorageState } from '../../hooks/useLocalStorage';
import { useStorageAdapter } from '../StorageAdapterContext';
const STORAGE_VERSION = 1;
const DEFAULT_STORAGE_KEY = 'custom-prompts:index';
const DEFAULT_GROUP_LABEL = 'Custom prompts';
const sanitizeIdSegment = (value) => value
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, '-')
    .replace(/^-+|-+$/g, '');
const PLACEHOLDER_PATTERN = /{{\s*([a-zA-Z0-9_-]+)\s*}}/g;
const DEFAULT_STORE = {
    version: STORAGE_VERSION,
    prompts: {}
};
const normalizeStore = (candidate) => {
    if (!candidate || typeof candidate !== 'object') {
        return { ...DEFAULT_STORE };
    }
    const prompts = {};
    if (candidate.prompts && typeof candidate.prompts === 'object') {
        for (const template of Object.values(candidate.prompts)) {
            if (!template || typeof template !== 'object')
                continue;
            if (typeof template.id !== 'string' || template.id.length === 0)
                continue;
            const normalizedId = template.id;
            prompts[normalizedId] = {
                id: normalizedId,
                name: typeof template.name === 'string' ? template.name : normalizedId,
                title: typeof template.title === 'string' ? template.title : undefined,
                description: typeof template.description === 'string' ? template.description : undefined,
                groupLabel: typeof template.groupLabel === 'string' ? template.groupLabel : undefined,
                argumentsSchema: Array.isArray(template.argumentsSchema) ? template.argumentsSchema : [],
                messages: Array.isArray(template.messages) ? template.messages.filter((message) => (message && typeof message === 'object' && typeof message.role === 'string' && typeof message.content === 'string')) : [],
                createdAt: typeof template.createdAt === 'number' ? template.createdAt : Date.now(),
                updatedAt: typeof template.updatedAt === 'number' ? template.updatedAt : Date.now()
            };
        }
    }
    return {
        version: STORAGE_VERSION,
        prompts
    };
};
const renderTemplateString = (template, args) => {
    if (template.trim().length === 0) {
        return '';
    }
    return template.replace(PLACEHOLDER_PATTERN, (_match, key) => {
        const normalizedKey = key.trim();
        if (normalizedKey.length === 0) {
            return '';
        }
        return args[normalizedKey] ?? '';
    });
};
const mapSchemaFieldToArgument = ([name, schema]) => ({
    name,
    description: schema?.description,
    required: Boolean(schema?.required)
});
const buildPromptDefinition = (template) => ({
    name: template.name,
    description: template.description,
    arguments: (template.argumentsSchema ?? []).map(mapSchemaFieldToArgument)
});
const buildPromptInstance = (template, args) => {
    const messages = template.messages.map((message) => ({
        role: message.role,
        content: [
            {
                type: 'text',
                text: renderTemplateString(message.content, args)
            }
        ]
    }));
    return {
        description: template.description,
        messages
    };
};
const createAdditionalPromptDefinition = (template) => ({
    id: template.id,
    title: template.title ?? template.name,
    description: template.description,
    groupLabel: template.groupLabel ?? DEFAULT_GROUP_LABEL,
    prompt: buildPromptDefinition(template),
    resolvePrompt: async (args) => buildPromptInstance(template, args)
});
const resolveDefinitionKey = (definition, fallbackIndex) => {
    const explicit = typeof definition.id === 'string' && definition.id.trim().length > 0
        ? definition.id.trim()
        : undefined;
    if (explicit) {
        return explicit;
    }
    const promptName = definition.prompt?.name ?? '';
    const derived = sanitizeIdSegment(promptName);
    if (derived.length > 0) {
        return derived;
    }
    return `additional-${fallbackIndex}`;
};
const mergeAdditionalPrompts = (propPrompts, userPrompts) => {
    const merged = [];
    const seen = new Set();
    const addPrompt = (prompt, key) => {
        if (seen.has(key)) {
            return;
        }
        merged.push(prompt);
        seen.add(key);
    };
    propPrompts.forEach((prompt, index) => {
        addPrompt(prompt, resolveDefinitionKey(prompt, index));
    });
    userPrompts.forEach((prompt, index) => {
        addPrompt(prompt, prompt.id ?? resolveDefinitionKey(prompt, index + propPrompts.length));
    });
    return merged;
};
const CustomPromptsContext = React.createContext(undefined);
export const CustomPromptsProvider = ({ children, propPrompts = [], storageKey }) => {
    const storageAdapter = useStorageAdapter();
    const effectiveStorageKey = storageKey ?? DEFAULT_STORAGE_KEY;
    const { value: storedState, update: updateStoredState } = useLocalStorageState(effectiveStorageKey, DEFAULT_STORE, storageAdapter);
    const state = React.useMemo(() => normalizeStore(storedState), [storedState]);
    const setState = React.useCallback((updater) => {
        updateStoredState((previous) => {
            const normalized = normalizeStore(previous);
            return updater({
                ...normalized,
                prompts: { ...normalized.prompts }
            });
        });
    }, [updateStoredState]);
    const propPromptIds = React.useMemo(() => {
        const explicit = new Set();
        const derived = new Set();
        propPrompts.forEach((prompt, index) => {
            if (typeof prompt.id === 'string' && prompt.id.trim().length > 0) {
                explicit.add(prompt.id.trim());
            }
            derived.add(resolveDefinitionKey(prompt, index));
        });
        return {
            explicit,
            derived
        };
    }, [propPrompts]);
    const templates = React.useMemo(() => {
        return Object.values(state.prompts).sort((a, b) => b.updatedAt - a.updatedAt);
    }, [state.prompts]);
    const userPrompts = React.useMemo(() => {
        return templates.map((template) => createAdditionalPromptDefinition(template));
    }, [templates]);
    const combinedPrompts = React.useMemo(() => {
        return mergeAdditionalPrompts(propPrompts, userPrompts);
    }, [propPrompts, userPrompts]);
    const isIdReserved = React.useCallback((id) => {
        if (!id)
            return true;
        if (state.prompts[id])
            return true;
        if (propPromptIds.explicit.has(id))
            return true;
        if (propPromptIds.derived.has(id))
            return true;
        return false;
    }, [propPromptIds, state.prompts]);
    const generateUniqueId = React.useCallback((baseName) => {
        const base = sanitizeIdSegment(baseName);
        const fallback = base.length > 0 ? base : 'custom-prompt';
        let candidate = fallback;
        let attempt = 1;
        while (isIdReserved(candidate)) {
            candidate = `${fallback}-${attempt++}`;
        }
        return candidate;
    }, [isIdReserved]);
    const createPrompt = React.useCallback((input) => {
        const now = Date.now();
        const desiredId = typeof input.id === 'string' ? sanitizeIdSegment(input.id) : '';
        const baseId = desiredId.length > 0 ? desiredId : generateUniqueId(input.name);
        const id = isIdReserved(baseId) ? generateUniqueId(`${input.name}-${now.toString(36)}`) : baseId;
        const template = {
            id,
            name: input.name,
            title: input.title,
            description: input.description,
            groupLabel: input.groupLabel,
            argumentsSchema: input.argumentsSchema ?? [],
            messages: Array.isArray(input.messages) ? input.messages : [],
            createdAt: now,
            updatedAt: now
        };
        setState((current) => ({
            version: STORAGE_VERSION,
            prompts: {
                ...current.prompts,
                [id]: template
            }
        }));
        return id;
    }, [generateUniqueId, isIdReserved, setState]);
    const updatePrompt = React.useCallback((id, updates) => {
        if (propPromptIds.explicit.has(id) || propPromptIds.derived.has(id)) {
            return false;
        }
        let didUpdate = false;
        setState((current) => {
            const existing = current.prompts[id];
            if (!existing) {
                return current;
            }
            didUpdate = true;
            const nextTemplate = {
                ...existing,
                name: updates.name ?? existing.name,
                title: updates.title ?? existing.title,
                description: updates.description ?? existing.description,
                groupLabel: updates.groupLabel ?? existing.groupLabel,
                argumentsSchema: updates.argumentsSchema ?? existing.argumentsSchema,
                messages: updates.messages ? [...updates.messages] : existing.messages,
                updatedAt: Date.now()
            };
            return {
                version: STORAGE_VERSION,
                prompts: {
                    ...current.prompts,
                    [id]: nextTemplate
                }
            };
        });
        return didUpdate;
    }, [propPromptIds, setState]);
    const deletePrompt = React.useCallback((id) => {
        if (propPromptIds.explicit.has(id) || propPromptIds.derived.has(id)) {
            return false;
        }
        let removed = false;
        setState((current) => {
            if (!current.prompts[id]) {
                return current;
            }
            const rest = { ...current.prompts };
            delete rest[id];
            removed = true;
            return {
                version: STORAGE_VERSION,
                prompts: rest
            };
        });
        return removed;
    }, [propPromptIds, setState]);
    const duplicatePrompt = React.useCallback((id, overrides) => {
        const existing = state.prompts[id];
        if (!existing) {
            return null;
        }
        const duplicateName = overrides?.name ?? `${existing.name} copy`;
        const duplicateMessages = overrides?.messages ?? existing.messages.map((message) => ({ ...message }));
        const duplicateSchema = overrides?.argumentsSchema ?? existing.argumentsSchema.map((field) => [field[0], { ...field[1] }]);
        return createPrompt({
            name: duplicateName,
            title: overrides?.title ?? existing.title,
            description: overrides?.description ?? existing.description,
            groupLabel: overrides?.groupLabel ?? existing.groupLabel,
            argumentsSchema: duplicateSchema,
            messages: duplicateMessages
        });
    }, [createPrompt, state.prompts]);
    const importPrompts = React.useCallback((inputs) => {
        const createdIds = [];
        inputs.forEach((input) => {
            try {
                const id = createPrompt(input);
                createdIds.push(id);
            }
            catch (error) {
                console.error('Failed to import custom prompt', error);
            }
        });
        return createdIds;
    }, [createPrompt]);
    const resolvePromptInstance = React.useCallback((id, args) => {
        const template = state.prompts[id];
        if (!template) {
            return undefined;
        }
        return buildPromptInstance(template, args);
    }, [state.prompts]);
    const getTemplate = React.useCallback((id) => {
        return state.prompts[id];
    }, [state.prompts]);
    const contextValue = React.useMemo(() => ({
        templates,
        readonlyPrompts: propPrompts,
        userPrompts,
        combinedPrompts,
        createPrompt,
        updatePrompt,
        deletePrompt,
        duplicatePrompt,
        importPrompts,
        resolvePromptInstance,
        getTemplate
    }), [
        templates,
        propPrompts,
        userPrompts,
        combinedPrompts,
        createPrompt,
        updatePrompt,
        deletePrompt,
        duplicatePrompt,
        importPrompts,
        resolvePromptInstance,
        getTemplate
    ]);
    return (_jsx(CustomPromptsContext.Provider, { value: contextValue, children: children }));
};
export const useCustomPrompts = () => {
    const context = React.useContext(CustomPromptsContext);
    if (!context) {
        throw new Error('useCustomPrompts must be used within a CustomPromptsProvider');
    }
    return context;
};
