// Auto-extracted from backup-page.js (verbatim) — augments BackupPage.prototype. Loaded after the base.
Object.assign(BackupPage.prototype, {
    renderLocFields(idx, suffixes, loc) {
        if (typeof ConfigShared === 'undefined' || !ConfigShared.generateField) {
            return `<div class="backup-empty-state">Configuration system not loaded.</div>`;
        }
        const locValueLookup = {
            NAME: loc.name, ENABLED: loc.enabled ? 'true' : 'false', TYPE: loc.type,
            ENGINE: loc.engine || 'restic',
            PATH_MODE: loc.path_mode || 'custom',
            PATH: loc.path, URI: loc.uri, SSH_USER: loc.ssh_user, SSH_HOST: loc.ssh_host,
            SSH_PORT: loc.ssh_port, SSH_PATH: loc.ssh_path,
            SSH_AUTH: loc.ssh_auth || 'key', SSH_PASS: '',
            S3_ACCESS_KEY: '', S3_SECRET_KEY: '',
            B2_ACCOUNT_ID: '', B2_ACCOUNT_KEY: '',
            APPEND_ONLY: loc.append_only ? 'true' : 'false',
            CUSTOM_RETENTION: loc.custom_retention ? 'true' : 'false',
            KEEP_LAST: loc.keep_last, KEEP_DAILY: loc.keep_daily,
            KEEP_WEEKLY: loc.keep_weekly, KEEP_MONTHLY: loc.keep_monthly,
            KEEP_YEARLY: loc.keep_yearly
        };

        // Field metadata comes from configs.json (window.configData) via
        // locFieldMeta; the basic/advanced split is decided by the caller, which
        // renders each group into its own tab (Connection vs Advanced).
        let html = '<div class="config-fields">';
        for (const suffix of suffixes) {
            const m = this.locFieldMeta(idx, suffix);
            if (!m.exists) continue;
            const value = (locValueLookup[suffix] ?? '').toString();
            html += ConfigShared.generateField(`config-${m.key}`, m.key, value, m.title, m.description, {}, {});
        }
        html += '</div>';
        return html;
    },
    locFieldMeta(idx, suffix) {
        const key = `CFG_BACKUP_LOC_${idx}_${suffix}`;
        const cfg = window.configData?.config?.[key] || {};
        const def = BACKUP_LOC_FIELD_DEFS[suffix] || {};
        return {
            key,
            exists: !!(cfg.title || cfg.description || BACKUP_LOC_FIELD_DEFS[suffix]),
            title: cfg.title || def.title || suffix,
            description: cfg.description ?? def.description ?? '',
            advanced: LOC_ADVANCED_SUFFIXES.has(suffix) || cfg.advanced === true
        };
    },
    locFieldsForType(type) {
        return this.locSchema?.types?.[type]
            || BACKUP_LOC_FIELDS_BY_TYPE[type]
            || BACKUP_LOC_FIELDS_BY_TYPE.local;
    },
    locFieldGroups(idx, type) {
        const suffixes = this.locFieldsForType(type);
        const connection = [];
        const advanced = [];
        for (const suffix of suffixes) {
            const m = this.locFieldMeta(idx, suffix);
            if (!m.exists) continue;
            (m.advanced ? advanced : connection).push(suffix);
        }
        return { connection, advanced };
    },
    renderConnectionInner(idx, type, loc, connectionSuffixes) {
        let html = this.renderLocFields(idx, connectionSuffixes, loc);
        if (type === 'sftp') html += this.renderBackupSshKeyCard(loc);
        return html;
    },
    formRetention(prefix, values, includeInherit = false) {
        const preset = backupRetentionDetectPreset(values, includeInherit);
        const meta = BACKUP_RETENTION_PRESET_META[preset];
        const presetOptions = this.retentionPresetOptions(preset, includeInherit);

        const customRetentionHidden = includeInherit
            ? `<input type="hidden" name="${prefix}CUSTOM_RETENTION" value="${preset === 'inherit-global' ? 'false' : 'true'}" data-backup-field>`
            : '';

        return `
            <div class="backup-form-grid backup-retention-block" data-retention-prefix="${this.escape(prefix)}" data-retention-allow-inherit="${includeInherit ? '1' : '0'}">
                <label class="backup-form-row">
                    <span class="backup-form-label">Backup style <span class="tooltip" data-retention-tooltip title="${this.escape(meta?.hint || '')}">ℹ️</span></span>
                    <select class="form-control" data-retention-preset>${presetOptions}</select>
                </label>
                ${customRetentionHidden}
            </div>
            <div class="backup-retention-advanced" data-retention-advanced ${preset === 'custom' ? '' : 'hidden'}>
                <div class="backup-form-grid">
                    ${this.formInput(`${prefix}KEEP_LAST`,    'Keep last',    values.last,    'number', '', 'backups')}
                    ${this.formInput(`${prefix}KEEP_DAILY`,   'Keep daily',   values.daily,   'number', '', 'days')}
                    ${this.formInput(`${prefix}KEEP_WEEKLY`,  'Keep weekly',  values.weekly,  'number', '', 'weeks')}
                    ${this.formInput(`${prefix}KEEP_MONTHLY`, 'Keep monthly', values.monthly, 'number', '', 'months')}
                    ${this.formInput(`${prefix}KEEP_YEARLY`,  'Keep yearly',  values.yearly,  'number', '', 'years')}
                </div>
            </div>
        `;
    },
    formInput(name, label, value, type = 'text', placeholder = '', unit = '') {
        const escVal = this.escape(value ?? '');
        const escPh = this.escape(placeholder);
        const escLabel = this.escape(label);
        const inputHTML = `<input type="${type}" name="${name}" value="${escVal}" placeholder="${escPh}" class="form-control" data-backup-field>`;
        const wrapped = unit ? `<div class="input-group">${inputHTML}<span class="input-group-text">${this.escape(unit)}</span></div>` : inputHTML;
        return `
            <label class="backup-form-row">
                <span class="backup-form-label">${escLabel}</span>
                ${wrapped}
            </label>
        `;
    },
    formSelect(name, label, value, options) {
        const escLabel = this.escape(label);
        const opts = options.map(([v, lbl]) => `<option value="${this.escape(v)}" ${v === value ? 'selected' : ''}>${this.escape(lbl)}</option>`).join('');
        return `
            <label class="backup-form-row">
                <span class="backup-form-label">${escLabel}</span>
                <select name="${name}" class="form-control" data-backup-field>${opts}</select>
            </label>
        `;
    },
    formToggle(name, label, checked) {
        const escLabel = this.escape(label);
        return `
            <label class="backup-form-row backup-form-row-toggle">
                <span class="backup-form-label">${escLabel}</span>
                <span class="backup-toggle">
                    <input type="checkbox" name="${name}" ${checked ? 'checked' : ''} data-backup-field data-backup-bool>
                    <span class="backup-toggle-slider"></span>
                </span>
            </label>
        `;
    },
    formCrontab(name, label, value) {
        if (typeof ConfigShared === 'undefined' || !ConfigShared.createCrontabField) {
            return this.formInput(name, label, value, 'text', 'minute hour day month weekday');
        }
        const fieldId = `config-${name}`;
        let cronHtml = ConfigShared.createCrontabField(fieldId, name, value, label, '');
        cronHtml = cronHtml.replace(`name="${name}"`, `name="${name}" data-backup-field`);
        return `
            <label class="backup-form-row">
                <span class="backup-form-label">${this.escape(label)}</span>
                ${cronHtml}
            </label>
        `;
    },
    formReadOnly(label, value) {
        return `
            <div class="backup-form-row">
                <span class="backup-form-label">${this.escape(label)}</span>
                <span class="backup-form-readonly">${this.escape(value)}</span>
            </div>
        `;
    },
    tagFieldsForSave(container) {
        container.querySelectorAll('input[name], select[name], textarea[name]').forEach(el => {
            if (!el.hasAttribute('data-backup-field')) {
                el.setAttribute('data-backup-field', '');
                if (el.type === 'checkbox') el.setAttribute('data-backup-bool', '');
            }
        });
    },
});
