/**
 * Questionnaire availability condition UI (same JSON schema as the Android app).
 */

const CONDITION_MODES = [
    { value: 'always', label: 'Always available' },
    { value: 'requires', label: 'Requires other questionnaires completed' },
    { value: 'requires_answer', label: 'Requires completions + answer check' },
    { value: 'requires_coach_band', label: 'Requires coach category (band)' },
    { value: 'any_of', label: 'Any of these rules (OR) — mix prerequisites & bands' },
    { value: 'custom', label: 'Custom JSON (advanced)' },
];

const SCORING_BANDS = [
    { value: 'green', label: 'Green' },
    { value: 'yellow', label: 'Yellow' },
    { value: 'red', label: 'Red' },
];

const CHOICE_LAYOUT_TYPES = new Set([
    'radio_question',
    'multi_check_box_question',
    'glass_scale_question',
]);

export function defaultConditionMessageKey(questionnaireId) {
    const id = (questionnaireId || 'new').replace(/^questionnaire_/, '');
    const slug = id.replace(/[^a-zA-Z0-9_]+/g, '_').replace(/^_+|_+$/g, '') || 'new';
    const normalized = /^[a-zA-Z]/.test(slug) ? slug : `k_${slug}`;
    return `questionnaire_unlock_${normalized}`;
}

function esc(s) {
    const d = document.createElement('div');
    d.textContent = s ?? '';
    return d.innerHTML;
}

function parseQuestionConfig(q) {
    try {
        return JSON.parse(q?.configJson || '{}');
    } catch {
        return {};
    }
}

/** Stable id stored in conditionJson.questionId (matches app endsWith check). */
export function conditionQuestionId(q) {
    const cfg = parseQuestionConfig(q);
    const key = (q?.questionKey || cfg.questionKey || '').trim();
    if (key) return key;
    if (q?.localId) return q.localId;
    const parts = (q?.questionID || '').split('__');
    return parts[parts.length - 1] || '';
}

function conditionQuestionLabel(q) {
    const id = conditionQuestionId(q);
    const text = (q?.defaultText || '').trim();
    if (!text) return id;
    const short = text.length > 48 ? `${text.slice(0, 45)}…` : text;
    return `${id} — ${short}`;
}

function questionsForQuestionnaire(questionsByQuestionnaire, questionnaireId) {
    if (!questionnaireId) return [];
    return questionsByQuestionnaire?.[questionnaireId] || [];
}

function findQuestion(questionsByQuestionnaire, questionnaireId, questionId) {
    if (!questionnaireId || !questionId) return null;
    return questionsForQuestionnaire(questionsByQuestionnaire, questionnaireId)
        .find(q => {
            const cid = conditionQuestionId(q);
            const local = q.localId || (q.questionID || '').split('__').pop();
            return questionId === cid || questionId === local || questionId === q.questionID;
        }) || null;
}

function questionMatchesSelection(q, selectedQuestionId) {
    if (!selectedQuestionId) return false;
    const cid = conditionQuestionId(q);
    const local = q.localId || (q.questionID || '').split('__').pop();
    return selectedQuestionId === cid
        || selectedQuestionId === local
        || selectedQuestionId === q.questionID;
}

function asRequiresList(obj) {
    if (!obj) return [];
    if (Array.isArray(obj.requiresCompleted)) {
        return obj.requiresCompleted.filter(Boolean).map(String);
    }
    if (typeof obj.requiresCompleted === 'string' && obj.requiresCompleted) {
        return [obj.requiresCompleted];
    }
    return [];
}

function hasQuestionCheck(obj) {
    return Boolean(
        obj?.questionnaire?.trim() &&
        obj?.questionId?.trim() &&
        obj?.operator?.trim() &&
        obj?.value != null && String(obj.value).trim() !== ''
    );
}

function filterRequires(requires, selfId) {
    if (!requires?.length) return [];
    if (!selfId) return [...requires];
    return requires.filter(id => id !== selfId);
}

/** Answer checks cannot reference the questionnaire being edited. */
function sanitizeAnswerRule(rule, selfId) {
    if (!selfId || rule.questionnaire !== selfId) {
        return { ...rule, requires: filterRequires(rule.requires, selfId) };
    }
    return {
        ...rule,
        requires: filterRequires(rule.requires, selfId),
        questionnaire: '',
        questionId: '',
        value: '',
    };
}

function emptyCoachBandFields() {
    return { coachBandProfileID: '', coachBandAllowed: [] };
}

function parseCoachBandFields(obj) {
    const band = obj?.requiresCoachBand;
    if (!band || typeof band !== 'object') return emptyCoachBandFields();
    const allowed = Array.isArray(band.allowed)
        ? band.allowed.filter(Boolean).map(v => String(v).toLowerCase())
        : [];
    return {
        coachBandProfileID: (band.profileID || '').trim(),
        coachBandAllowed: allowed,
    };
}

function hasCoachBandFields(rule) {
    return Boolean(
        (rule?.coachBandProfileID || '').trim() &&
        (rule?.coachBandAllowed || []).filter(Boolean).length
    );
}

function parseRule(obj, selfId = '') {
    if (!obj || typeof obj !== 'object') {
        return {
            type: 'requires',
            requires: [],
            questionnaire: '',
            questionId: '',
            operator: '==',
            value: '',
            ...emptyCoachBandFields(),
        };
    }
    if (obj.alwaysAvailable) {
        return { type: 'always', ...emptyCoachBandFields() };
    }
    const coachBand = parseCoachBandFields(obj);
    const rule = {
        type: hasQuestionCheck(obj) ? 'requires_answer' : 'requires',
        requires: asRequiresList(obj),
        questionnaire: obj.questionnaire || '',
        questionId: obj.questionId || '',
        operator: obj.operator === '!=' ? '!=' : '==',
        value: obj.value != null ? String(obj.value) : '',
        ...coachBand,
    };
    return sanitizeAnswerRule(rule, selfId);
}

export function parseConditionForm(conditionJson, questionnaireId) {
    const raw = (conditionJson || '{}').trim() || '{}';
    let obj;
    try {
        obj = JSON.parse(raw);
    } catch {
        return {
            mode: 'custom',
            customJson: raw,
            messageKey: defaultConditionMessageKey(questionnaireId),
            germanLabel: '',
        };
    }

    const messageKey = (obj.messageKey || '').trim() || defaultConditionMessageKey(questionnaireId);

    if (obj.alwaysAvailable === true) {
        return { mode: 'always', messageKey: '', germanLabel: '', customJson: '' };
    }
    if (obj.requiresCoachBand && typeof obj.requiresCoachBand === 'object' && !Array.isArray(obj.anyOf)) {
        const band = parseCoachBandFields(obj);
        return {
            mode: 'requires_coach_band',
            requires: asRequiresList(obj),
            coachBandProfileID: band.coachBandProfileID,
            coachBandAllowed: band.coachBandAllowed,
            messageKey,
            germanLabel: '',
            customJson: '',
        };
    }
    if (Array.isArray(obj.anyOf) && obj.anyOf.length) {
        return {
            mode: 'any_of',
            rules: obj.anyOf.map(r => parseRule(r, questionnaireId)).filter(r => r.type !== 'always'),
            messageKey,
            germanLabel: '',
            customJson: '',
        };
    }

    const rule = parseRule(obj, questionnaireId);
    return {
        mode: rule.type === 'always' ? 'always' : rule.type,
        requires: rule.requires,
        questionnaire: rule.questionnaire,
        questionId: rule.questionId,
        operator: rule.operator,
        value: rule.value,
        messageKey,
        germanLabel: '',
        customJson: '',
    };
}

function buildRule(rule) {
    if (rule.type === 'always') {
        return { alwaysAvailable: true };
    }
    const out = {};
    if (rule.requires?.length) {
        out.requiresCompleted = [...rule.requires];
    }
    if (rule.type === 'requires_answer') {
        out.questionnaire = (rule.questionnaire || '').trim();
        out.questionId = (rule.questionId || '').trim();
        out.operator = rule.operator === '!=' ? '!=' : '==';
        out.value = String(rule.value ?? '').trim();
    }
    const profileID = (rule.coachBandProfileID || '').trim();
    const allowed = (rule.coachBandAllowed || []).filter(Boolean);
    if (profileID || allowed.length) {
        if (!profileID) {
            throw new Error('Select a scoring profile for the coach category rule (or clear the band checkboxes)');
        }
        if (!allowed.length) {
            throw new Error('Select at least one allowed coach category (band), or clear the scoring profile');
        }
        out.requiresCoachBand = { profileID, allowed: [...allowed] };
    }
    return out;
}

function assertAnswerNotSelf(questionnaireId, selfId) {
    if (selfId && questionnaireId === selfId) {
        throw new Error('Answer check must use a different questionnaire (not this one)');
    }
}

export function buildConditionJson(form, selfQuestionnaireId = '') {
    if (form.mode === 'custom') {
        const raw = (form.customJson || '{}').trim() || '{}';
        JSON.parse(raw);
        return raw;
    }

    let obj;
    if (form.mode === 'always') {
        obj = { alwaysAvailable: true };
    } else if (form.mode === 'any_of') {
        const rules = (form.rules || []).map(buildRule).filter(r => Object.keys(r).length);
        if (!rules.length) {
            throw new Error('Add at least one rule for "Any of these rules"');
        }
        for (const rule of form.rules || []) {
            if (rule.type === 'requires' && !rule.requires?.length && !hasCoachBandFields(rule)) {
                throw new Error('Each OR rule needs prerequisites and/or a coach category');
            }
            if (rule.type === 'requires_answer') {
                if (!(rule.questionnaire || '').trim()) {
                    throw new Error('Select the questionnaire for each answer-check rule');
                }
                if (!(rule.questionId || '').trim()) {
                    throw new Error('Select the question for each answer-check rule');
                }
                if (!(rule.value ?? '').toString().trim()) {
                    throw new Error('Enter the expected answer for each answer-check rule');
                }
            }
        }
        obj = { anyOf: rules };
    } else if (form.mode === 'requires_coach_band') {
        obj = {};
        if (form.requires?.length) {
            obj.requiresCompleted = [...form.requires];
        }
        const profileID = (form.coachBandProfileID || '').trim();
        const allowed = (form.coachBandAllowed || []).filter(Boolean);
        if (!profileID) {
            throw new Error('Select a scoring profile for the coach category rule');
        }
        if (!allowed.length) {
            throw new Error('Select at least one allowed coach category (band)');
        }
        obj.requiresCoachBand = { profileID, allowed: [...allowed] };
    } else {
        obj = buildRule({
            type: form.mode,
            requires: form.requires || [],
            questionnaire: form.questionnaire,
            questionId: form.questionId,
            operator: form.operator,
            value: form.value,
        });
        if (form.mode === 'requires' && !obj.requiresCompleted?.length) {
            throw new Error('Select at least one required questionnaire');
        }
        if (form.mode === 'requires_answer') {
            if (!obj.questionnaire) {
                throw new Error('Select the questionnaire for the answer check');
            }
            if (!obj.questionId) {
                throw new Error('Select the question for the answer check');
            }
            if (!obj.value) {
                throw new Error('Enter or select the expected answer value');
            }
        }
    }

    const messageKey = (form.messageKey || '').trim();
    if (form.mode !== 'always' && messageKey) {
        obj.messageKey = messageKey;
    }
    return JSON.stringify(obj);
}

function bandCheckboxesHTML(selected, editable, id = 'condCoachBands') {
    const dis = editable ? '' : ' disabled';
    const sel = new Set((selected || []).map(b => String(b).toLowerCase()));
    return `<div class="scoring-band-picker" id="${esc(id)}">
        ${SCORING_BANDS.map(b => {
            const checked = sel.has(b.value) ? ' checked' : '';
            return `<label class="scoring-band-picker-item">
                <input type="checkbox" value="${b.value}"${checked}${dis}>
                <span class="band-badge band-${b.value}">${esc(b.label)}</span>
            </label>`;
        }).join('')}
    </div>`;
}

function scoringProfileSelectHTML(selectedId, scoringProfiles, editable, id = 'condCoachBandProfile') {
    const dis = editable ? '' : ' disabled';
    const list = (scoringProfiles || []).filter(p => p.profileID);
    if (!list.length) {
        return '<p class="data-toolbar-hint">No active scoring profiles. Create one under Questionnaires → Scoring profiles.</p>';
    }
    const options = ['<option value="">— Select scoring profile —</option>']
        .concat(list.map(p => {
            const pid = p.profileID;
            const sel = selectedId === pid ? ' selected' : '';
            const label = (p.name || '').trim() || 'Unnamed profile';
            return `<option value="${esc(pid)}"${sel}>${esc(label)}</option>`;
        }));
    return `<select id="${esc(id)}" class="scoring-profile-select"${dis}>${options.join('')}</select>`;
}

function coachBandFieldsHTML(prefix, rule, scoringProfiles, editable, {
    optional = false,
} = {}) {
    const profileId = `${prefix}CoachBandProfile`;
    const bandsId = `${prefix}CoachBands`;
    return `
        <div class="scoring-coach-band-fields" style="margin-top:12px">
            <label class="form-label">${optional
                ? 'Optional: coach category (leave empty = any band / no category check)'
                : 'Coach category'}</label>
            ${optional
                ? '<p class="field-hint" style="margin:0 0 8px">Use this when only some paths depend on green/yellow/red. Other OR rules can omit it so the questionnaire unlocks regardless of band.</p>'
                : ''}
            <div class="form-group">
                <label class="form-label">Scoring profile</label>
                ${scoringProfileSelectHTML(rule.coachBandProfileID || '', scoringProfiles, editable, profileId)}
            </div>
            <div class="form-group">
                <label class="form-label">Allowed coach categories</label>
                ${bandCheckboxesHTML(rule.coachBandAllowed || [], editable, bandsId)}
                ${optional ? '' : '<p class="field-hint">Unlocks only after the coach sets one of these categories during score review.</p>'}
            </div>
        </div>`;
}

function coachBandRuleHTML(form, allQuestionnaires, scoringProfiles, selfId, editable) {
    return `
        <div class="scoring-coach-band-panel condition-rule-block">
            <label class="form-label">Optional: must also be completed first</label>
            ${requiresCheckboxes('condRequires', form.requires || [], allQuestionnaires, selfId, editable)}
            ${coachBandFieldsHTML('cond', form, scoringProfiles, editable, { optional: false })}
        </div>`;
}

function readCoachBandAllowed(id = 'condCoachBands') {
    const root = document.getElementById(id);
    if (!root) return [];
    return [...root.querySelectorAll('input[type=checkbox]:checked')].map(cb => cb.value);
}

function readCoachBandPrefix(prefix) {
    return {
        coachBandProfileID: document.getElementById(`${prefix}CoachBandProfile`)?.value?.trim() || '',
        coachBandAllowed: readCoachBandAllowed(`${prefix}CoachBands`),
    };
}

function requiresCheckboxes(id, selected, allQuestionnaires, selfId, editable) {
    const list = (allQuestionnaires || []).filter(q => q.questionnaireID !== selfId);
    if (!list.length) {
        return '<p class="data-toolbar-hint">No other questionnaires to require.</p>';
    }
    return `<div class="condition-requires-list" id="${id}">
        ${list.map(q => {
            const checked = selected.includes(q.questionnaireID) ? ' checked' : '';
            return `<label class="checkbox-label condition-requires-item">
                <input type="checkbox" value="${esc(q.questionnaireID)}"${checked}${editable ? '' : ' disabled'}>
                ${esc(q.name || q.questionnaireID)}
            </label>`;
        }).join('')}
    </div>`;
}

function questionnaireSelectHTML(prefix, selectedId, allQuestionnaires, selfId, editable) {
    const dis = editable ? '' : ' disabled';
    const list = (allQuestionnaires || []).filter(
        q => q.questionnaireID && q.questionnaireID !== selfId
    );
    const options = ['<option value="">— Select questionnaire —</option>']
        .concat(list.map(q => {
            const id = q.questionnaireID;
            const sel = selectedId === id ? ' selected' : '';
            const label = q.name ? `${q.name}` : id;
            const suffix = q.name && q.name !== id ? ` (${id})` : '';
            return `<option value="${esc(id)}"${sel}>${esc(label)}${esc(suffix)}</option>`;
        }));
    return `<select id="${prefix}Questionnaire" class="condition-qn-select"${dis}>${options.join('')}</select>`;
}

function questionSelectHTML(prefix, questionnaireId, selectedQuestionId, questionsByQuestionnaire, editable) {
    const dis = editable ? '' : ' disabled';
    const questions = questionsForQuestionnaire(questionsByQuestionnaire, questionnaireId);
    if (!questionnaireId) {
        return `<select id="${prefix}QuestionId" class="condition-question-select" disabled${dis}>
            <option value="">Select a questionnaire first</option>
        </select>`;
    }
    const options = ['<option value="">— Select question —</option>'];
    for (const q of questions) {
        const val = conditionQuestionId(q);
        const sel = questionMatchesSelection(q, selectedQuestionId) ? ' selected' : '';
        options.push(`<option value="${esc(val)}"${sel}>${esc(conditionQuestionLabel(q))}</option>`);
    }
    const known = questions.some(q => questionMatchesSelection(q, selectedQuestionId));
    if (selectedQuestionId && !known) {
        options.push(
            `<option value="${esc(selectedQuestionId)}" selected>${esc(selectedQuestionId)} (saved)</option>`
        );
    }
    if (!questions.length) {
        options.push('<option value="" disabled>No questions in this questionnaire</option>');
    }
    return `<select id="${prefix}QuestionId" class="condition-question-select"${dis}>${options.join('')}</select>`;
}

function answerValueFieldHTML(prefix, rule, questionsByQuestionnaire, editable) {
    const dis = editable ? '' : ' disabled';
    const q = findQuestion(questionsByQuestionnaire, rule.questionnaire, rule.questionId);
    const options = q?.answerOptions || [];
    const hasChoices = q && CHOICE_LAYOUT_TYPES.has(q.type) && options.length > 0;

    if (hasChoices) {
        const opts = ['<option value="">— Select answer —</option>'];
        for (const opt of options) {
            const val = (opt.optionKey || opt.defaultText || '').trim();
            if (!val) continue;
            const label = opt.labelGerman || opt.defaultText || val;
            const sel = rule.value === val ? ' selected' : '';
            opts.push(`<option value="${esc(val)}"${sel}>${esc(val)} — ${esc(label)}</option>`);
        }
        if (rule.value && !options.some(o => (o.optionKey || o.defaultText || '').trim() === rule.value)) {
            opts.push(`<option value="${esc(rule.value)}" selected>${esc(rule.value)} (saved)</option>`);
        }
        return `<select id="${prefix}Value" class="condition-value-select"${dis}>${opts.join('')}</select>`;
    }

    return `<input type="text" id="${prefix}Value" class="condition-value-input" value="${esc(rule.value)}" placeholder="e.g. consent_signed"${dis}>`;
}

function answerFieldsHTML(prefix, rule, allQuestionnaires, questionsByQuestionnaire, selfId, editable) {
    const dis = editable ? '' : ' disabled';
    return `
        <div class="condition-answer-grid meta-form">
            <div class="form-group">
                <label>Questionnaire (answer check)</label>
                ${questionnaireSelectHTML(prefix, rule.questionnaire, allQuestionnaires, selfId, editable)}
                <p class="field-hint">Must be a different questionnaire than this one.</p>
            </div>
            <div class="form-group">
                <label>Question</label>
                ${questionSelectHTML(prefix, rule.questionnaire, rule.questionId, questionsByQuestionnaire, editable)}
            </div>
            <div class="form-group">
                <label>Operator</label>
                <select id="${prefix}Operator"${dis}>
                    <option value="==" ${rule.operator !== '!=' ? 'selected' : ''}>equals (==)</option>
                    <option value="!=" ${rule.operator === '!=' ? 'selected' : ''}>not equals (!=)</option>
                </select>
            </div>
            <div class="form-group">
                <label>Expected answer</label>
                ${answerValueFieldHTML(prefix, rule, questionsByQuestionnaire, editable)}
            </div>
        </div>`;
}

function singleRuleHTML(prefix, rule, allQuestionnaires, questionsByQuestionnaire, selfId, editable, {
    scoringProfiles = [],
    showOptionalCoachBand = false,
} = {}) {
    const showAnswer = rule.type === 'requires_answer';
    return `
        <div class="condition-rule-block">
            <label class="form-label">Must be completed</label>
            ${requiresCheckboxes(`${prefix}Requires`, rule.requires || [], allQuestionnaires, selfId, editable)}
            ${showAnswer ? `
                <label class="form-label" style="margin-top:12px">And answer must match</label>
                ${answerFieldsHTML(prefix, rule, allQuestionnaires, questionsByQuestionnaire, selfId, editable)}
            ` : ''}
            ${showOptionalCoachBand
                ? coachBandFieldsHTML(prefix, rule, scoringProfiles, editable, { optional: true })
                : ''}
        </div>`;
}

export function renderConditionEditorHTML(form, {
    questionnaireId,
    allQuestionnaires,
    questionsByQuestionnaire,
    scoringProfiles = [],
    germanLabel,
    editable,
}) {
    const dis = editable ? '' : ' disabled';
    const modeOptions = CONDITION_MODES.map(m =>
        `<option value="${m.value}" ${form.mode === m.value ? 'selected' : ''}>${m.label}</option>`
    ).join('');

    const rules = form.rules?.length ? form.rules : [{
        type: 'requires',
        requires: [],
        questionnaire: '',
        questionId: '',
        operator: '==',
        value: '',
        ...emptyCoachBandFields(),
    }];

    return `
        <div class="condition-editor" id="conditionEditor">
            <h4 style="margin:0 0 12px;font-size:.95rem">Availability</h4>
            <div class="form-group">
                <label>When can counselors open this questionnaire?</label>
                <select id="conditionMode"${dis}>${modeOptions}</select>
            </div>

            <div id="conditionPanelRequires" class="condition-mode-panel" style="display:${form.mode === 'requires' ? '' : 'none'}">
                ${singleRuleHTML('cond', { type: 'requires', requires: form.requires || [] }, allQuestionnaires, questionsByQuestionnaire, questionnaireId, editable)}
            </div>

            <div id="conditionPanelRequiresAnswer" class="condition-mode-panel" style="display:${form.mode === 'requires_answer' ? '' : 'none'}">
                ${singleRuleHTML('cond', {
                    type: 'requires_answer',
                    requires: form.requires || [],
                    questionnaire: form.questionnaire || '',
                    questionId: form.questionId || '',
                    operator: form.operator || '==',
                    value: form.value || '',
                }, allQuestionnaires, questionsByQuestionnaire, questionnaireId, editable)}
            </div>

            <div id="conditionPanelRequiresCoachBand" class="condition-mode-panel" style="display:${form.mode === 'requires_coach_band' ? '' : 'none'}">
                ${coachBandRuleHTML(form, allQuestionnaires, scoringProfiles, questionnaireId, editable)}
            </div>

            <div id="conditionPanelAnyOf" class="condition-mode-panel" style="display:${form.mode === 'any_of' ? '' : 'none'}">
                <p class="data-toolbar-hint" style="margin:0 0 10px">
                    Unlock if <strong>any one</strong> rule matches. Mix prerequisites and coach categories per rule:
                    e.g. Rule 1 = questionnaires A+B + green band; Rule 2 = questionnaire C only (any band).
                </p>
                <div id="conditionAnyOfRules">
                    ${rules.map((rule, i) => `
                        <div class="condition-anyof-rule card" data-rule-index="${i}">
                            <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px">
                                <strong>Rule ${i + 1}</strong>
                                ${editable && rules.length > 1 ? `<button type="button" class="btn btn-sm remove-anyof-rule">Remove</button>` : ''}
                            </div>
                            <div class="form-group">
                                <label>Rule type</label>
                                <select class="anyof-rule-type" data-rule-index="${i}"${dis}>
                                    <option value="requires" ${rule.type === 'requires' ? 'selected' : ''}>Requires completions</option>
                                    <option value="requires_answer" ${rule.type === 'requires_answer' ? 'selected' : ''}>Requires completions + answer</option>
                                </select>
                            </div>
                            ${singleRuleHTML(`anyof${i}`, rule, allQuestionnaires, questionsByQuestionnaire, questionnaireId, editable, {
                                scoringProfiles,
                                showOptionalCoachBand: true,
                            })}
                        </div>
                    `).join('')}
                </div>
                ${editable ? '<button type="button" class="btn btn-sm" id="addAnyOfRule" style="margin-top:8px">+ Add rule</button>' : ''}
            </div>

            <div id="conditionPanelCustom" class="condition-mode-panel" style="display:${form.mode === 'custom' ? '' : 'none'}">
                <textarea id="conditionCustomJson" rows="8" class="condition-json-fallback"${dis}>${esc(form.customJson || '{}')}</textarea>
            </div>

            <div id="conditionLockedMessage" class="condition-locked-message" style="display:${form.mode === 'always' ? 'none' : ''};margin-top:16px;padding-top:16px;border-top:1px solid var(--border)">
                <p class="data-toolbar-hint" style="margin:0 0 10px">Shown on the app when locked. Also listed under Translations → App strings.</p>
                <div class="meta-form">
                    <div class="form-group">
                        <label>Message key</label>
                        <input type="text" id="conditionMessageKey" value="${esc(form.messageKey || '')}" placeholder="${esc(defaultConditionMessageKey(questionnaireId))}"${dis}>
                    </div>
                    <div class="form-group">
                        <label>German label</label>
                        <input type="text" id="conditionGermanLabel" value="${esc(germanLabel || '')}" placeholder="e.g. Complete Demografie and RHS first"${dis}>
                    </div>
                </div>
            </div>
        </div>`;
}

function readRequires(containerId) {
    const root = document.getElementById(containerId);
    if (!root) return [];
    return [...root.querySelectorAll('input[type=checkbox]:checked')].map(cb => cb.value);
}

function readAnswerPrefix(prefix) {
    return {
        questionnaire: document.getElementById(`${prefix}Questionnaire`)?.value?.trim() || '',
        questionId: document.getElementById(`${prefix}QuestionId`)?.value?.trim() || '',
        operator: document.getElementById(`${prefix}Operator`)?.value || '==',
        value: document.getElementById(`${prefix}Value`)?.value?.trim() ?? '',
    };
}

export function readConditionFormFromDOM() {
    const mode = document.getElementById('conditionMode')?.value || 'always';
    const form = { mode, messageKey: '', germanLabel: '', customJson: '' };

    if (mode === 'custom') {
        form.customJson = document.getElementById('conditionCustomJson')?.value || '{}';
        try {
            const obj = JSON.parse(form.customJson);
            form.messageKey = (obj.messageKey || '').trim();
        } catch { /* validated on save */ }
        form.germanLabel = document.getElementById('conditionGermanLabel')?.value?.trim() || '';
        return form;
    }

    if (mode === 'always') {
        return form;
    }

    form.messageKey = document.getElementById('conditionMessageKey')?.value?.trim() || '';
    form.germanLabel = document.getElementById('conditionGermanLabel')?.value?.trim() || '';

    if (mode === 'requires') {
        form.requires = readRequires('condRequires');
        return form;
    }

    if (mode === 'requires_answer') {
        form.requires = readRequires('condRequires');
        Object.assign(form, readAnswerPrefix('cond'));
        return form;
    }

    if (mode === 'requires_coach_band') {
        form.requires = readRequires('condRequires');
        Object.assign(form, readCoachBandPrefix('cond'));
        return form;
    }

    if (mode === 'any_of') {
        form.rules = [];
        document.querySelectorAll('#conditionAnyOfRules .condition-anyof-rule').forEach((el, i) => {
            const type = el.querySelector('.anyof-rule-type')?.value || 'requires';
            const requires = readRequires(`anyof${i}Requires`);
            const rule = {
                type,
                requires,
                ...readAnswerPrefix(`anyof${i}`),
                ...readCoachBandPrefix(`anyof${i}`),
            };
            form.rules.push(rule);
        });
    }

    return form;
}

function wireConditionSelects(container, { questionnaireId, onChange }) {
    container.querySelectorAll('.condition-qn-select').forEach(sel => {
        sel.addEventListener('change', () => {
            const prefix = sel.id.replace(/Questionnaire$/, '');
            const form = readConditionFormFromDOM();
            if (prefix === 'cond' && form.mode === 'requires_answer') {
                const answer = readAnswerPrefix('cond');
                answer.questionnaire = sel.value;
                if (answer.questionnaire !== form.questionnaire) {
                    answer.questionId = '';
                    answer.value = '';
                }
                form.questionnaire = answer.questionnaire;
                form.questionId = answer.questionId;
                form.value = answer.value;
            } else if (form.rules) {
                const idx = parseInt(prefix.replace(/^anyof/, ''), 10);
                if (!Number.isNaN(idx) && form.rules[idx]) {
                    const prev = form.rules[idx].questionnaire;
                    form.rules[idx].questionnaire = sel.value;
                    if (sel.value !== prev) {
                        form.rules[idx].questionId = '';
                        form.rules[idx].value = '';
                    }
                }
            }
            onChange(form);
        });
    });

    container.querySelectorAll('.condition-question-select').forEach(sel => {
        sel.addEventListener('change', () => {
            const prefix = sel.id.replace(/QuestionId$/, '');
            const form = readConditionFormFromDOM();
            const qId = sel.value;
            if (prefix === 'cond' && form.mode === 'requires_answer') {
                form.questionId = qId;
                form.value = '';
            } else if (form.rules) {
                const idx = parseInt(prefix.replace(/^anyof/, ''), 10);
                if (!Number.isNaN(idx) && form.rules[idx]) {
                    form.rules[idx].questionId = qId;
                    form.rules[idx].value = '';
                }
            }
            onChange(form);
        });
    });
}

/**
 * Mount editor into container; returns { readForm, buildJson }.
 */
export function mountConditionEditor(container, {
    questionnaireId,
    allQuestionnaires,
    questionsByQuestionnaire = {},
    scoringProfiles = [],
    conditionJson,
    germanLabel,
    editable,
}) {
    let form = parseConditionForm(conditionJson, questionnaireId);
    let label = germanLabel || '';

    const render = () => {
        container.innerHTML = renderConditionEditorHTML(
            { ...form, germanLabel: label },
            {
                questionnaireId,
                allQuestionnaires,
                questionsByQuestionnaire,
                scoringProfiles,
                germanLabel: label,
                editable,
            }
        );
        wire();
    };

    const wire = () => {
        const modeEl = document.getElementById('conditionMode');
        modeEl?.addEventListener('change', () => {
            form = readConditionFormFromDOM();
            form.mode = modeEl.value;
            if (form.mode === 'always') {
                form.messageKey = '';
            } else if (!form.messageKey) {
                form.messageKey = defaultConditionMessageKey(questionnaireId);
            }
            render();
        });

        document.getElementById('addAnyOfRule')?.addEventListener('click', () => {
            form = readConditionFormFromDOM();
            form.mode = 'any_of';
            form.rules = form.rules || [];
            form.rules.push({
                type: 'requires',
                requires: [],
                questionnaire: '',
                questionId: '',
                operator: '==',
                value: '',
                ...emptyCoachBandFields(),
            });
            label = document.getElementById('conditionGermanLabel')?.value || label;
            render();
        });

        container.querySelectorAll('.remove-anyof-rule').forEach(btn => {
            btn.addEventListener('click', () => {
                form = readConditionFormFromDOM();
                label = document.getElementById('conditionGermanLabel')?.value || label;
                const idx = parseInt(btn.closest('.condition-anyof-rule')?.dataset.ruleIndex || '-1', 10);
                form.rules.splice(idx, 1);
                render();
            });
        });

        container.querySelectorAll('.anyof-rule-type').forEach(sel => {
            sel.addEventListener('change', () => {
                form = readConditionFormFromDOM();
                label = document.getElementById('conditionGermanLabel')?.value || label;
                const idx = parseInt(sel.dataset.ruleIndex || '0', 10);
                if (form.rules?.[idx]) {
                    form.rules[idx].type = sel.value;
                }
                render();
            });
        });

        wireConditionSelects(container, {
            questionnaireId,
            onChange: (updated) => {
                form = updated;
                label = document.getElementById('conditionGermanLabel')?.value || label;
                render();
            },
        });
    };

    render();

    return {
        readForm: () => {
            form = readConditionFormFromDOM();
            label = document.getElementById('conditionGermanLabel')?.value?.trim() || label;
            return { ...form, germanLabel: label };
        },
        buildJson: () => buildConditionJson(readConditionFormFromDOM(), questionnaireId),
    };
}
