// retoor <retoor@molodetz.nl>

import { OptimisticAction } from "./OptimisticAction.js";

export class PollManager extends OptimisticAction {
    constructor() {
        super();
        document.addEventListener("click", (event) => this.onClick(event));
        document.addEventListener("submit", (event) => this.onSubmit(event), true);
    }

    onClick(event) {
        const option = event.target.closest(".poll-option");
        if (option && !option.disabled) {
            event.preventDefault();
            this.vote(option);
            return;
        }
        const toggle = event.target.closest("[data-poll-toggle]");
        if (toggle) {
            event.preventDefault();
            this.toggleBuilder(toggle);
            return;
        }
        const addOption = event.target.closest("[data-poll-add-option]");
        if (addOption) {
            event.preventDefault();
            this.addOption(addOption);
            return;
        }
        const removeOption = event.target.closest("[data-poll-remove-option]");
        if (removeOption) {
            event.preventDefault();
            this.removeOption(removeOption);
        }
    }

    async vote(option) {
        const poll = option.closest(".poll");
        if (!poll) {
            return;
        }
        const pollUid = poll.dataset.pollUid;
        const optionUid = option.dataset.optionUid;
        await this.submit(`/polls/${pollUid}/vote`, { option_uid: optionUid }, null, (result) => this.render(poll, result));
    }

    render(poll, result) {
        const byUid = {};
        (result.options || []).forEach((option) => {
            byUid[option.uid] = option;
        });
        poll.querySelectorAll(".poll-option").forEach((button) => {
            const data = byUid[button.dataset.optionUid];
            if (!data) {
                return;
            }
            const chosen = result.my_choice === data.uid;
            button.classList.toggle("chosen", chosen);
            button.setAttribute("aria-pressed", chosen ? "true" : "false");
            const bar = button.querySelector(".poll-option-bar");
            if (bar) {
                bar.style.setProperty("--poll-pct", `${data.pct}%`);
            }
            const pct = button.querySelector(".poll-option-pct");
            if (pct) {
                pct.textContent = `${data.pct}%`;
            }
            const check = button.querySelector(".poll-option-check");
            if (check) {
                check.hidden = !chosen;
            }
        });
        const total = poll.querySelector(".poll-total");
        if (total) {
            total.textContent = `${result.total} vote${result.total === 1 ? "" : "s"}`;
        }
    }

    toggleBuilder(toggle) {
        const form = toggle.closest("form");
        const builder = form ? form.querySelector("[data-poll-builder]") : null;
        if (!builder) {
            return;
        }
        const activating = builder.hidden;
        builder.hidden = !activating;
        this.setPollEnabled(builder, activating);
        const label = toggle.querySelector("[data-poll-toggle-label]");
        if (label) {
            label.textContent = activating ? "Remove poll" : "Add poll";
        }
    }

    setPollEnabled(builder, enabled) {
        builder.querySelectorAll("input[name='poll_question'], input[name='poll_options']").forEach((input) => {
            input.disabled = !enabled;
            if (!enabled) {
                input.value = "";
            }
        });
        const error = builder.querySelector("[data-poll-error]");
        if (error) {
            error.hidden = true;
            error.textContent = "";
        }
    }

    addOption(button) {
        const form = button.closest("form");
        const container = form ? form.querySelector("[data-poll-options]") : null;
        if (!container) {
            return;
        }
        const rows = container.querySelectorAll(".poll-builder-row");
        if (rows.length >= 6) {
            return;
        }
        const row = document.createElement("div");
        row.className = "poll-builder-row";
        const input = document.createElement("input");
        input.type = "text";
        input.name = "poll_options";
        input.maxLength = 100;
        input.placeholder = `Option ${rows.length + 1}`;
        const remove = document.createElement("button");
        remove.type = "button";
        remove.className = "poll-builder-remove";
        remove.dataset.pollRemoveOption = "";
        remove.setAttribute("aria-label", "Remove option");
        remove.textContent = "×";
        row.appendChild(input);
        row.appendChild(remove);
        container.appendChild(row);
    }

    removeOption(button) {
        const container = button.closest("[data-poll-options]");
        if (!container) {
            return;
        }
        if (container.querySelectorAll(".poll-builder-row").length <= 2) {
            return;
        }
        const row = button.closest(".poll-builder-row");
        if (row) {
            row.remove();
        }
    }

    onSubmit(event) {
        const form = event.target;
        if (!form || typeof form.querySelector !== "function") {
            return;
        }
        const builder = form.querySelector("[data-poll-builder]");
        if (!builder || builder.hidden) {
            return;
        }
        const question = builder.querySelector("input[name='poll_question']");
        const options = [...builder.querySelectorAll("input[name='poll_options']")]
            .map((input) => input.value.trim())
            .filter(Boolean);
        let problem = "";
        if (!question || !question.value.trim()) {
            problem = "Add a poll question, or remove the poll.";
        } else if (options.length < 2) {
            problem = "Add at least two poll options, or remove the poll.";
        }
        if (problem) {
            event.preventDefault();
            event.stopImmediatePropagation();
            const error = builder.querySelector("[data-poll-error]");
            if (error) {
                error.textContent = problem;
                error.hidden = false;
            }
        }
    }
}
