function MusicUploadPanel({ value, nativeMusic, templateId, projectId, scopeKey = '', user, active = true, disabled = false, onChange, onBusyChange, openSignIn }) {
    const api = typeof useBuilderApi === 'function' ? useBuilderApi() : window.EA;
    const M = window.EverafterMusicConfig;
    const [selected, setSelected] = React.useState(() => M.selection(value));
    const [uploading, setUploading] = React.useState(false);
    const [progress, setProgress] = React.useState(0);
    const [error, setError] = React.useState('');
    const input = React.useRef(null);
    const audio = React.useRef(null);
    const request = React.useRef(null);
    const sequence = React.useRef(0);
    const callbacks = React.useRef({ onChange, onBusyChange });
    callbacks.current = { onChange, onBusyChange };
    const scope = [templateId, scopeKey, projectId || 'new', user?.id || 'anonymous'].join(':');
    const currentScope = React.useRef(scope);
    currentScope.current = scope;
    const signedIn = Boolean(user?.id && api?.isLoggedIn());
    const designPreview = window.EA_UI_PREVIEW === true;
    const hasUpload = Boolean(value?.uploadId && M.safeSource(value.src, true));
    const fallbackMusic = window.EverafterTemplateMusic?.fallbackFor(templateId);
    const originalMusic = nativeMusic?.src ? nativeMusic : fallbackMusic || nativeMusic;
    let previewUrl = hasUpload ? value.src : M.safeSource(value?.src || originalMusic?.src || '');
    if (previewUrl && !/^https:/i.test(previewUrl)) {
        try {
            const path = window.TemplateCatalog?.get(templateId)?.builderTemplatePath || (typeof TemplateCatalog !== 'undefined' ? TemplateCatalog.get(templateId)?.builderTemplatePath : '');
            const base = new URL(typeof resolveWeddingAssetUrl === 'function' ? resolveWeddingAssetUrl(path) : window.EA_APP?.path(path) || path, window.location.origin);
            previewUrl = new URL(previewUrl.startsWith('/') ? window.EA_APP?.path(previewUrl) || previewUrl : previewUrl, base).href;
        }
        catch (_) {
            previewUrl = '';
        }
    }
    const busy = disabled || uploading;
    React.useEffect(() => { if (!active)
        audio.current?.pause(); }, [active]);
    React.useEffect(() => { setSelected(M.selection(value)); }, [value?.source, value?.enabled, value?.uploadId]);
    React.useEffect(() => {
        ++sequence.current;
        request.current?.abort();
        request.current = null;
        setUploading(false);
        setProgress(0);
        setError('');
        callbacks.current.onBusyChange?.(false);
        audio.current?.pause();
        return () => {
            ++sequence.current;
            request.current?.abort();
            request.current = null;
            audio.current?.pause();
            callbacks.current.onBusyChange?.(false);
        };
    }, [scope]);
    function choose(source) {
        audio.current?.pause();
        setError('');
        setSelected(source);
        if (source === 'template')
            callbacks.current.onChange(M.template(nativeMusic));
        if (source === 'off')
            callbacks.current.onChange(M.off(value));
        if (source === 'upload' && hasUpload)
            callbacks.current.onChange({ ...value, source: 'upload', enabled: true });
    }
    async function upload(event) {
        const file = event.target.files?.[0];
        event.target.value = '';
        if (!file || disabled || uploading || request.current)
            return;
        if (designPreview) {
            setError('Music uploads are unavailable in this design preview.');
            return;
        }
        if (!signedIn) {
            setError('Sign in before uploading your music.');
            openSignIn?.('builder');
            return;
        }
        if (!/\.(mp3|m4a|ogg|wav)$/i.test(file.name || '')) {
            setError('Choose an MP3, M4A, OGG or WAV audio file.');
            return;
        }
        if (!file.size || file.size > 10 * 1024 * 1024) {
            setError('Choose an audio file up to 10 MB.');
            return;
        }
        if (!api?.uploadAudio) {
            setError('Music uploads are unavailable. Please reload and try again.');
            return;
        }
        const capturedScope = scope, capturedOwner = user.id, token = ++sequence.current;
        const controller = new AbortController();
        request.current = controller;
        const current = () => currentScope.current === capturedScope && sequence.current === token && !controller.signal.aborted && api?.isLoggedIn() && (!api.currentUser || api.currentUser()?.id === capturedOwner);
        audio.current?.pause();
        setError('');
        setProgress(0);
        setUploading(true);
        callbacks.current.onBusyChange?.(true);
        try {
            const result = await api.uploadAudio(file, { projectId: projectId || undefined, signal: controller.signal, onProgress: percent => { if (current())
                    setProgress(Math.max(0, Math.min(100, Number(percent) || 0))); } });
            if (!current())
                return;
            const music = M.uploaded(result);
            if (!result.upload?.name)
                music.name = file.name.slice(0, 200);
            callbacks.current.onChange(music);
            setSelected('upload');
            setProgress(100);
        }
        catch (err) {
            if (current())
                setError(err.message || 'The music upload failed. Please try again.');
        }
        finally {
            if (currentScope.current === capturedScope && sequence.current === token) {
                request.current = null;
                setUploading(false);
                callbacks.current.onBusyChange?.(false);
            }
        }
    }
    function remove() {
        audio.current?.pause();
        setError('');
        setSelected('template');
        callbacks.current.onChange(M.template(nativeMusic));
    }
    return React.createElement("section", { className: "music-upload-panel", "aria-label": "Music settings" },
        React.createElement("p", { className: "music-upload-intro" }, "Set the soundtrack for your page. Guests choose when to play it."),
        React.createElement("label", { className: "builder-field" },
            React.createElement("span", null, "Music"),
            React.createElement("select", { value: selected, disabled: busy, onChange: event => choose(event.target.value) },
                React.createElement("option", { value: "template" }, "Original template music"),
                React.createElement("option", { value: "upload" }, "My uploaded music"),
                React.createElement("option", { value: "off" }, "Music off"))),
        selected === 'template' && (fallbackMusic && !value?.source ? React.createElement("div", { className: "music-upload-file" },
            React.createElement("p", { className: "music-upload-hint" }, "Your saved page does not yet use this soundtrack. Add it so guests can choose to play it."),
            React.createElement("button", { type: "button", className: "builder-add-btn", disabled: busy, onClick: () => choose('template') }, "Use original music")) : React.createElement("p", { className: "music-upload-hint" }, "Use the template\u2019s soundtrack or ambience. Guests can play or pause it on your page.")),
        selected === 'off' && React.createElement("p", { className: "music-upload-hint" },
            "Music is off.",
            hasUpload ? ' Your uploaded track is kept so you can turn it on again.' : ''),
        (selected === 'upload' || hasUpload) && React.createElement("div", { className: "music-upload-file" },
            hasUpload && React.createElement("div", { className: "music-upload-track" },
                React.createElement("strong", null, value.name || 'Your uploaded music'),
                React.createElement("span", null,
                    value.sizeBytes ? (value.sizeBytes / (1024 * 1024)).toFixed(1) + ' MB' : 'Uploaded audio',
                    value.durationSeconds ? ' · ' + Math.floor(value.durationSeconds / 60) + ':' + String(Math.floor(value.durationSeconds % 60)).padStart(2, '0') : '')),
            React.createElement("p", { className: "music-upload-hint" }, "MP3, M4A, OGG or WAV \u00B7 up to 10 MB. Choose music you have permission to share."),
            React.createElement("input", { ref: input, type: "file", accept: ".mp3,.m4a,.ogg,.wav,audio/mpeg,audio/mp4,audio/ogg,audio/wav", onChange: upload, disabled: busy || !signedIn || designPreview, hidden: true, "aria-label": "Choose a music file" }),
            React.createElement("div", { className: "music-upload-actions" },
                React.createElement("button", { type: "button", className: "builder-add-btn", disabled: busy || designPreview, onClick: () => signedIn ? input.current?.click() : openSignIn?.('builder') }, !signedIn ? 'Sign in to upload music' : hasUpload ? 'Replace music' : 'Upload music'),
                hasUpload && React.createElement("button", { type: "button", disabled: busy, onClick: remove }, "Remove uploaded music")),
            designPreview && React.createElement("p", { className: "music-upload-hint" }, "Music uploads are unavailable in this design preview.")),
        uploading && React.createElement("div", { className: "music-upload-progress", role: "status", "aria-live": "polite" },
            React.createElement("progress", { value: progress, max: "100" }),
            React.createElement("span", null, progress >= 99 ? 'Checking your audio…' : 'Uploading music… ' + Math.round(progress) + '%')),
        error && React.createElement("p", { className: "music-upload-error", role: "alert" }, error),
        previewUrl && React.createElement("div", { className: "music-upload-preview" },
            React.createElement("span", null, "Listen here"),
            React.createElement("audio", { key: previewUrl, ref: audio, controls: true, preload: "none", src: previewUrl, "aria-label": "Preview music" }),
            React.createElement("p", { className: "music-upload-hint" }, "This preview plays only when you press Play.")));
}
window.MusicUploadPanel = MusicUploadPanel;
