'use strict';
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
import { Controller } from '@hotwired/stimulus';
// @ts-ignore
import { getComponent } from '@symfony/ux-live-component';
export default class default_1 extends Controller {
    constructor() {
        super(...arguments);
        this.comp = null;
    }
    initialize() {
        return __awaiter(this, void 0, void 0, function* () {
            try {
                this.comp = yield getComponent(this.element);
            }
            catch (_a) {
                this.comp = null;
            }
        });
    }
    connect() {
        this.sync();
    }
    /**
     * Change handler for all decision controls. The input carries:
     *   data-model-name — writable prop path, e.g. `participantDecisions[«uuid»]`
     *   data-decide     — 'switch' (checked ⇒ '1', unchecked ⇒ '0')
     *                     'check'  (checked ⇒ '1', unchecked ⇒ null)
     *                     'radio'  (the input's own value)
     */
    decide(event) {
        var _a;
        const input = event.currentTarget;
        const model = input.dataset.modelName;
        if (!model) {
            return;
        }
        let value;
        switch (input.dataset.decide) {
            case 'switch':
                value = input.checked ? '1' : '0';
                break;
            case 'check':
                value = input.checked ? '1' : null;
                break;
            default:
                value = input.value;
        }
        try {
            (_a = this.comp) === null || _a === void 0 ? void 0 : _a.set(model, value, false);
        }
        catch (_b) {
            // Model not writable / component gone — server re-validates on submit.
        }
        this.reflectSeg(input);
        this.sync();
    }
    /**
     * Mirror a radio group's state onto its pill labels and hide the "please
     * decide" caption. The on/off utility classes are declared on the labels
     * (data-on-classes / data-off-classes) and swapped here — plain class
     * toggling is the only styling path whose invalidation every browser gets
     * right (CSS :has()/attribute-variant invalidation proved flaky).
     */
    reflectSeg(input) {
        var _a, _b;
        const seg = input.closest('[data-seg]');
        if (!seg) {
            return;
        }
        seg.querySelectorAll('label').forEach((label) => {
            var _a, _b, _c;
            const on = ((_a = label.dataset.onClasses) !== null && _a !== void 0 ? _a : '').split(/\s+/).filter(Boolean);
            const off = ((_b = label.dataset.offClasses) !== null && _b !== void 0 ? _b : '').split(/\s+/).filter(Boolean);
            const icon = label.querySelector('svg');
            if ((_c = label.querySelector('input')) === null || _c === void 0 ? void 0 : _c.checked) {
                label.setAttribute('data-on', '');
                label.classList.add(...on);
                label.classList.remove(...off);
                icon === null || icon === void 0 ? void 0 : icon.classList.remove('hidden');
            }
            else {
                label.removeAttribute('data-on');
                label.classList.remove(...on);
                label.classList.add(...off);
                icon === null || icon === void 0 ? void 0 : icon.classList.add('hidden');
            }
            // Re-insert the same node: forces a fresh style resolution on
            // engines whose recalc goes stale for morphed radio labels
            // (observed in embedded Chromium). No-op otherwise — same element,
            // listeners and state preserved.
            label.replaceWith(label);
        });
        (_b = (_a = seg.parentElement) === null || _a === void 0 ? void 0 : _a.querySelector('[data-caption]')) === null || _b === void 0 ? void 0 : _b.classList.add('hidden');
    }
    /** Recompute the submit gate from the DOM state of all decisions. */
    sync() {
        let ok = true;
        for (const el of this.decisionTargets) {
            const mode = el.dataset.mode;
            if ('compulsory' === mode) {
                const box = el.querySelector('input[type="checkbox"]');
                if (box && !box.checked) {
                    ok = false;
                }
            }
            else if ('force_decision' === mode) {
                if (!el.querySelector('input[type="radio"]:checked')) {
                    ok = false;
                }
            }
            else if ('extra' === mode) {
                // Offer-specific question. Only the ones the admin marked as
                // required block the submit — an optional question may stay
                // empty (data-required is rendered by _extras.html.twig, and
                // the server re-checks the same rule on submit).
                if ('1' !== el.dataset.required) {
                    continue;
                }
                const fileBox = el.querySelector('[data-extra-file]');
                if (fileBox) {
                    // File answers are uploaded server-side the moment they are
                    // picked, so the stored state — not an input value — says
                    // whether the question is answered.
                    if ('1' !== fileBox.dataset.extraFile) {
                        ok = false;
                    }
                }
                else if (el.querySelector('input[type="radio"]')) {
                    if (!el.querySelector('input[type="radio"]:checked')) {
                        ok = false;
                    }
                }
                else {
                    const field = el.querySelector('textarea, input');
                    if (!field || '' === field.value.trim()) {
                        ok = false;
                    }
                }
            }
        }
        this.submitTargets.forEach((btn) => {
            btn.disabled = !ok;
            // The Cms:Button component also bakes these classes into a
            // server-rendered disabled button — toggle them along with the
            // property, or the button stays visually dead and unclickable.
            ['pointer-events-none', 'opacity-50', 'cursor-not-allowed'].forEach((cls) => btn.classList.toggle(cls, !ok));
        });
        this.blockerOkTargets.forEach((el) => el.classList.toggle('hidden', !ok));
        this.blockerOpenTargets.forEach((el) => el.classList.toggle('hidden', ok));
    }
}
default_1.targets = ['decision', 'submit', 'blockerOk', 'blockerOpen'];
