const appState = {
    data: null,
    userId: localStorage.getItem("nht:userId") || "",
    view: localStorage.getItem("nht:view") || "weekly",
    date: localStorage.getItem("nht:date") || new Date().toISOString().slice(0, 10),
};

const accentChoices = ["green", "blue", "red", "pink", "orange"];

const $ = (selector, root = document) => root.querySelector(selector);
const $$ = (selector, root = document) => Array.from(root.querySelectorAll(selector));

function escapeHtml(value) {
    return String(value ?? "")
        .replaceAll("&", "&amp;")
        .replaceAll("<", "&lt;")
        .replaceAll(">", "&gt;")
        .replaceAll('"', "&quot;")
        .replaceAll("'", "&#039;");
}

function number(value, digits = 0) {
    const numeric = Number(value || 0);
    return numeric.toLocaleString(undefined, {
        maximumFractionDigits: digits,
        minimumFractionDigits: digits,
    });
}

function shortDate(value) {
    const date = new Date(`${value}T00:00:00`);
    return date.toLocaleDateString(undefined, { month: "short", day: "numeric" });
}

function longDate(value) {
    const date = new Date(`${value}T00:00:00`);
    return date.toLocaleDateString(undefined, {
        weekday: "short",
        month: "short",
        day: "numeric",
        year: "numeric",
    });
}

function addDays(dateString, days) {
    const date = new Date(`${dateString}T00:00:00`);
    date.setDate(date.getDate() + days);
    return date.toISOString().slice(0, 10);
}

function dateRange(start, end) {
    const days = [];
    let cursor = start;
    while (cursor <= end) {
        days.push(cursor);
        cursor = addDays(cursor, 1);
    }
    return days;
}

function showToast(message) {
    const toast = $("#toast");
    toast.textContent = message;
    toast.classList.add("show");
    window.clearTimeout(showToast.timer);
    showToast.timer = window.setTimeout(() => toast.classList.remove("show"), 2400);
}

async function api(action, payload = null, method = "POST") {
    const options = { method };
    if (payload) {
        options.headers = { "Content-Type": "application/json" };
        options.body = JSON.stringify(payload);
    }

    const response = await fetch(`/api.php?action=${encodeURIComponent(action)}`, options);
    const json = await response.json();
    if (!response.ok || json.error) {
        throw new Error(json.error || "Request failed.");
    }
    return json;
}

async function loadState() {
    const params = new URLSearchParams({
        action: "state",
        view: appState.view,
        date: appState.date,
    });

    if (appState.userId) {
        params.set("user_id", appState.userId);
    }

    const response = await fetch(`/api.php?${params.toString()}`);
    const json = await response.json();
    if (!response.ok || json.error) {
        throw new Error(json.error || "Unable to load tracker state.");
    }

    appState.data = json;
    appState.userId = String(json.currentUser.id);
    appState.view = json.view;
    appState.date = json.range.anchor;
    localStorage.setItem("nht:userId", appState.userId);
    localStorage.setItem("nht:view", appState.view);
    localStorage.setItem("nht:date", appState.date);
    render();
}

function render() {
    if (!appState.data) return;

    applyTheme();
    renderControls();
    renderSummaries();
    renderMedical();
    renderTimeline();
    renderNutrition();
    renderRoutines();
    renderSupplements();
    renderAdmin();
    renderLibraries();
    populateForms();
}

function applyTheme() {
    const user = appState.data.currentUser;
    const mode = user.theme_mode || "dark";
    const accent = accentChoices.includes(user.theme_accent) ? user.theme_accent : "green";

    document.body.dataset.theme = mode;
    document.body.dataset.accent = accent;

    $("#darkModeButton").classList.toggle("active", mode === "dark");
    $("#lightModeButton").classList.toggle("active", mode === "light");
    $$("[data-accent]").forEach((button) => {
        button.classList.toggle("active", button.dataset.accent === accent);
    });
}

function renderControls() {
    const data = appState.data;
    const user = data.currentUser;
    $("#profileFocus").textContent = user.fitness_focus || "Multi-profile medical dashboard";
    if (data.currentUserIsAdmin) {
        $("#profileFocus").textContent += " / admin";
    }
    $("#rangeCopy").textContent = `${data.view[0].toUpperCase()}${data.view.slice(1)} view: ${longDate(data.range.start)} to ${longDate(data.range.end)}`;
    $("#datePicker").value = data.range.anchor;

    $("#profileSelect").innerHTML = data.users
        .map((profile) => `<option value="${profile.id}" ${profile.id === user.id ? "selected" : ""}>${escapeHtml(profile.name)} (${escapeHtml(profile.role)})</option>`)
        .join("");

    $$("[data-view]").forEach((button) => {
        button.classList.toggle("active", button.dataset.view === data.view);
    });
}

function renderSummaries() {
    const { latestVitals, medicationLogs, labResults, symptomLogs, allergyRecords, appointments } = appState.data;
    const medicationTaken = medicationLogs.filter((item) => item.status === "taken").length;
    const bp = latestVitals && Number(latestVitals.systolic) > 0 ? `${latestVitals.systolic}/${latestVitals.diastolic}` : "No BP";
    const highestSeverity = symptomLogs.reduce((max, item) => Math.max(max, Number(item.severity || 0)), 0);
    const activeAllergies = allergyRecords.filter((item) => item.status === "active").length;
    const scheduledAppointments = appointments.filter((item) => item.status === "scheduled").length;

    const cards = [
        ["Medications", `${number(medicationLogs.length)}`, `${number(medicationTaken)} taken in range`],
        ["Blood Pressure", bp, latestVitals ? `${number(latestVitals.pulse)} pulse` : "No vitals log"],
        ["Glucose", latestVitals && Number(latestVitals.glucose_mg_dl) > 0 ? `${number(latestVitals.glucose_mg_dl)} mg/dL` : "No glucose", latestVitals ? `${number(latestVitals.oxygen_pct, 1)}% oxygen` : "No oxygen log"],
        ["Labs", `${number(labResults.length)}`, "results in range"],
        ["Symptoms", `${number(symptomLogs.length)}`, `highest severity ${number(highestSeverity)}`],
        ["Allergies", `${number(activeAllergies)}`, `${number(allergyRecords.length)} total records`],
        ["Appointments", `${number(scheduledAppointments)}`, "scheduled in range"],
    ];

    $("#summaryGrid").innerHTML = cards
        .map(([label, value, detail]) => `
            <article class="summary-card">
                <span>${escapeHtml(label)}</span>
                <strong>${escapeHtml(value)}</strong>
                <small>${escapeHtml(detail)}</small>
            </article>
        `)
        .join("");
}

function renderTimeline() {
    const { range, workouts } = appState.data;
    const byDate = new Map();
    workouts.forEach((workout) => {
        if (!byDate.has(workout.scheduled_on)) byDate.set(workout.scheduled_on, []);
        byDate.get(workout.scheduled_on).push(workout);
    });

    const html = dateRange(range.start, range.end).map((date) => {
        const entries = byDate.get(date) || [];
        const volume = entries.reduce((sum, workout) => sum + Number(workout.sets || 0) * Number(workout.reps || 0) * Number(workout.weight_lbs || 0), 0);
        const minutes = entries.reduce((sum, workout) => sum + Number(workout.duration_min || 0), 0);
        return `
            <section class="timeline-day">
                <div class="timeline-date">
                    <strong>${longDate(date)}</strong>
                    <span class="timeline-meta">${entries.length} workouts / ${number(minutes)} min / ${number(volume)} lb</span>
                </div>
                <div class="workout-list">
                    ${entries.length ? entries.map(renderWorkoutItem).join("") : `<div class="empty-state">No workouts scheduled</div>`}
                </div>
            </section>
        `;
    }).join("");

    $("#workoutTimeline").innerHTML = html || `<div class="empty-state">No planner days found</div>`;
}

function renderWorkoutItem(workout) {
    const liftLine = Number(workout.weight_lbs) > 0
        ? `${number(workout.sets)} x ${number(workout.reps)} @ ${number(workout.weight_lbs, 1)} lb`
        : "";
    const cardioLine = Number(workout.duration_min) || Number(workout.distance_mi)
        ? `${number(workout.duration_min)} min${Number(workout.distance_mi) ? ` / ${number(workout.distance_mi, 2)} mi` : ""}`
        : "";
    const details = [workout.workout_type, workout.exercise_name, liftLine, cardioLine, workout.intensity]
        .filter(Boolean)
        .join(" | ");

    return `
        <article class="workout-item">
            <div class="workout-top">
                <div>
                    <h3>${escapeHtml(workout.title)}</h3>
                    <p class="details-line">${escapeHtml(details || "Open workout")}</p>
                    ${workout.routine_name ? `<p class="timeline-meta">${escapeHtml(workout.routine_name)}</p>` : ""}
                </div>
                <span class="badge ${escapeHtml(workout.status)}">${escapeHtml(workout.status)}</span>
            </div>
            ${workout.notes ? `<p class="muted">${escapeHtml(workout.notes)}</p>` : ""}
            <div class="status-row">
                ${["planned", "complete", "skipped"].map((status) => `
                    <button class="status-button" type="button" data-workout-id="${workout.id}" data-status="${status}">
                        ${status}
                    </button>
                `).join("")}
            </div>
        </article>
    `;
}

function renderMedical() {
    renderMedicationLogs();
    renderVitalLogs();
    renderLabResults();
    renderSymptomLogs();
    renderAllergyRecords();
    renderAppointments();
    renderImmunizationRecords();
    renderStudies();
}

function renderMedicationLogs() {
    const logs = appState.data.medicationLogs || [];
    $("#medicationLogList").innerHTML = logs.length ? logs.map((log) => `
        <article class="workout-item">
            <div class="workout-top">
                <div>
                    <h3>${escapeHtml(log.medication_name)}</h3>
                    <p class="details-line">${shortDate(log.taken_on)} | ${escapeHtml(log.dose || "open dose")} | ${escapeHtml(log.route || "route not set")} | ${escapeHtml(log.frequency || "frequency not set")}</p>
                    ${log.class_name ? `<p class="timeline-meta">${escapeHtml(log.class_name)}</p>` : ""}
                </div>
                <span class="badge ${escapeHtml(log.status)}">${escapeHtml(log.status)}</span>
            </div>
            <p class="muted">${escapeHtml([log.prescriber, log.notes].filter(Boolean).join(" | ") || "No notes")}</p>
            ${log.rxnorm_url ? `<a class="text-button source-button" href="${escapeHtml(log.rxnorm_url)}">RxNorm</a>` : ""}
        </article>
    `).join("") : `<div class="empty-state">No medication logs in this range</div>`;
}

function renderVitalLogs() {
    const logs = appState.data.vitalLogs || [];
    $("#vitalLogList").innerHTML = logs.length ? logs.map((log) => {
        const bp = Number(log.systolic) > 0 ? `${log.systolic}/${log.diastolic}` : "No BP";
        return `
            <article class="log-item">
                <div class="log-top">
                    <strong>${shortDate(log.measured_on)}</strong>
                    <span class="badge">${bp}</span>
                </div>
                <p>${number(log.pulse)} pulse / ${number(log.temperature_f, 1)} F / ${number(log.oxygen_pct, 1)}% O2 / ${number(log.glucose_mg_dl)} glucose / pain ${number(log.pain_score)}</p>
                <p class="muted">${escapeHtml([log.symptoms, log.notes].filter(Boolean).join(" | ") || "No symptoms noted")}</p>
            </article>
        `;
    }).join("") : `<div class="empty-state">No vitals in this range</div>`;
}

function renderLabResults() {
    const labs = appState.data.labResults || [];
    $("#labResultList").innerHTML = labs.length ? labs.map((lab) => `
        <article class="log-item">
            <div class="log-top">
                <strong>${escapeHtml(lab.test_name)}</strong>
                <span class="badge">${escapeHtml(lab.result_value)} ${escapeHtml(lab.unit || "")}</span>
            </div>
            <p>${shortDate(lab.collected_on)} / ${escapeHtml(lab.reference_range || "No reference range")}</p>
            <p class="muted">${escapeHtml([lab.ordering_clinician, lab.notes].filter(Boolean).join(" | ") || "No notes")}</p>
        </article>
    `).join("") : `<div class="empty-state">No lab results in this range</div>`;
}

function renderSymptomLogs() {
    const logs = appState.data.symptomLogs || [];
    $("#symptomLogList").innerHTML = logs.length ? logs.map((log) => `
        <article class="log-item">
            <div class="log-top">
                <strong>${escapeHtml(log.symptom)}</strong>
                <span class="badge">severity ${number(log.severity)}</span>
            </div>
            <p>${shortDate(log.observed_on)} / ${escapeHtml(log.body_area || "body area not set")} / ${escapeHtml(log.duration || "duration not set")}</p>
            <p class="muted">${escapeHtml([log.triggers, log.action_taken, log.notes].filter(Boolean).join(" | ") || "No notes")}</p>
        </article>
    `).join("") : `<div class="empty-state">No symptom logs in this range</div>`;
}

function renderAllergyRecords() {
    const records = appState.data.allergyRecords || [];
    $("#allergyRecordList").innerHTML = records.length ? records.map((record) => `
        <article class="log-item">
            <div class="log-top">
                <strong>${escapeHtml(record.allergen)}</strong>
                <span class="badge ${escapeHtml(record.status)}">${escapeHtml(record.severity)}</span>
            </div>
            <p>${escapeHtml(record.reaction || "Reaction not set")} / ${escapeHtml(record.status)}</p>
            <p class="muted">${escapeHtml([record.first_noted_on ? `first noted ${shortDate(record.first_noted_on)}` : "", record.notes].filter(Boolean).join(" | ") || "No notes")}</p>
        </article>
    `).join("") : `<div class="empty-state">No allergy records yet</div>`;
}

function renderAppointments() {
    const appointments = appState.data.appointments || [];
    $("#appointmentList").innerHTML = appointments.length ? appointments.map((appointment) => `
        <article class="log-item">
            <div class="log-top">
                <strong>${escapeHtml(appointment.reason)}</strong>
                <span class="badge ${escapeHtml(appointment.status)}">${escapeHtml(appointment.status)}</span>
            </div>
            <p>${shortDate(appointment.appointment_on)} / ${escapeHtml(appointment.clinician || "clinician not set")} / ${escapeHtml(appointment.specialty || "specialty not set")}</p>
            <p class="muted">${escapeHtml([appointment.location, appointment.follow_up_notes].filter(Boolean).join(" | ") || "No follow-up notes")}</p>
        </article>
    `).join("") : `<div class="empty-state">No appointments in this range</div>`;
}

function renderImmunizationRecords() {
    const records = appState.data.immunizationRecords || [];
    $("#immunizationRecordList").innerHTML = records.length ? records.slice(0, 8).map((record) => `
        <article class="log-item">
            <div class="log-top">
                <strong>${escapeHtml(record.vaccine_name)}</strong>
                <span class="badge">${shortDate(record.administered_on)}</span>
            </div>
            <p>${escapeHtml(record.dose || "dose not set")} / ${escapeHtml(record.clinician_or_site || "site not set")}</p>
            <p class="muted">${escapeHtml([record.next_due_on ? `next due ${shortDate(record.next_due_on)}` : "", record.lot_number ? `lot ${record.lot_number}` : "", record.notes].filter(Boolean).join(" | ") || "No notes")}</p>
        </article>
    `).join("") : `<div class="empty-state">No immunization records yet</div>`;
}

function renderStudies() {
    const studies = (appState.data.researchStudies || []).slice(0, 6);
    $("#studyList").innerHTML = studies.length ? studies.map((study) => `
        <article class="supplement-item">
            <div class="supplement-top">
                <div>
                    <h3>${escapeHtml(study.title)}</h3>
                    <p class="details-line">${escapeHtml(study.category)} | ${escapeHtml(study.related_medicine || "general")}</p>
                </div>
                <span class="badge">${escapeHtml(study.study_type || "research")}</span>
            </div>
            <p>${escapeHtml(study.summary)}</p>
            <div class="status-row">
                <a class="status-button" href="${escapeHtml(study.source_url)}">NIH/NLM</a>
                <a class="status-button" href="${escapeHtml(study.pubmed_url)}">PubMed</a>
                <a class="status-button" href="${escapeHtml(study.clinicaltrials_url)}">ClinicalTrials.gov</a>
            </div>
        </article>
    `).join("") : `<div class="empty-state">No study links seeded</div>`;
}

function renderNutrition() {
    const { nutritionSummary, nutritionLogs } = appState.data;
    const target = nutritionSummary.target;
    const actual = nutritionSummary.actual;
    const macros = [
        ["Calories", "calories", "kcal"],
        ["Protein", "protein_g", "g"],
        ["Carbs", "carbs_g", "g"],
        ["Fat", "fat_g", "g"],
        ["Water", "water_ml", "ml"],
    ];

    const macroHtml = macros.map(([label, key, unit]) => {
        const targetValue = Number(target[key] || 0);
        const actualValue = Number(actual[key] || 0);
        const percent = targetValue > 0 ? Math.min((actualValue / targetValue) * 100, 140) : 0;
        return `
            <div class="macro-row">
                <div class="macro-copy">
                    <span>${label}</span>
                    <span>${number(actualValue)} / ${number(targetValue)} ${unit}</span>
                </div>
                <div class="bar" style="--value: ${percent}%"><span></span></div>
            </div>
        `;
    }).join("");

    const logHtml = nutritionLogs.length
        ? nutritionLogs.map((log) => `
            <article class="log-item">
                <div class="log-top">
                    <strong>${shortDate(log.logged_on)}</strong>
                    <span class="badge">${number(log.calories)} kcal</span>
                </div>
                <p>${number(log.protein_g)}g protein / ${number(log.carbs_g)}g carbs / ${number(log.fat_g)}g fat / ${number(log.water_ml)}ml water</p>
                ${log.notes ? `<p class="muted">${escapeHtml(log.notes)}</p>` : ""}
            </article>
        `).join("")
        : `<div class="empty-state">No nutrition logs in this range</div>`;

    $("#nutritionCompare").innerHTML = `
        <div class="macro-list">${macroHtml}</div>
        <div class="panel-heading" style="margin-top: 16px;">
            <div>
                <p class="eyebrow">Selected Target</p>
                <h3>${escapeHtml(target.label)} (${escapeHtml(target.scope)})</h3>
            </div>
            <span class="badge">${escapeHtml(target.scaled_from)} basis</span>
        </div>
        <div class="nutrition-list">${logHtml}</div>
    `;
}

function renderRoutines() {
    const routines = appState.data.routines;
    $("#routineList").innerHTML = routines.length
        ? routines.map((routine) => `
            <article class="routine-item">
                <div class="routine-top">
                    <div>
                        <h3>${escapeHtml(routine.name)}</h3>
                        <p class="routine-meta">${escapeHtml(routine.workout_type)} / ${escapeHtml(routine.planner_scope)} / ${escapeHtml(routine.intensity || "open intensity")}</p>
                    </div>
                    <span class="badge">${routine.active ? "active" : "paused"}</span>
                </div>
                <p class="details-line">Nutrition: ${escapeHtml(routine.nutrition_goal_label || "separate target")}</p>
                ${routine.notes ? `<p class="muted">${escapeHtml(routine.notes)}</p>` : ""}
            </article>
        `).join("")
        : `<div class="empty-state">No routines yet</div>`;
}

function renderSupplements() {
    const logs = appState.data.supplementLogs;
    $("#supplementLogList").innerHTML = logs.length
        ? logs.map((log) => `
            <article class="supplement-item">
                <div class="supplement-top">
                    <div>
                        <h3>${escapeHtml(log.supplement_name || "Custom supplement")}</h3>
                        <p class="details-line">${shortDate(log.taken_on)} / ${escapeHtml(log.timing)} / ${escapeHtml(log.dose || "open dose")}</p>
                    </div>
                    <span class="badge ${escapeHtml(log.status)}">${escapeHtml(log.status)}</span>
                </div>
                ${log.supplement_purpose ? `<p>${escapeHtml(log.supplement_purpose)}</p>` : ""}
                ${log.notes ? `<p class="muted">${escapeHtml(log.notes)}</p>` : ""}
            </article>
        `).join("")
        : `<div class="empty-state">No supplement logs in this range</div>`;
}

function renderAdmin() {
    const panel = $("#adminPanel");
    if (!panel) return;

    const isAdminUser = Boolean(appState.data.currentUserIsAdmin);
    panel.hidden = !isAdminUser;
    if (!isAdminUser) {
        return;
    }

    const summary = appState.data.adminSummary || {};
    const statCards = [
        ["Total", summary.total_users || 0],
        ["Active", summary.active_users || 0],
        ["Inactive", summary.inactive_users || 0],
        ["Admins", summary.admins || 0],
        ["Members", summary.members || 0],
    ];
    $("#adminStats").innerHTML = statCards.map(([label, value]) => `
        <article class="admin-stat">
            <span>${escapeHtml(label)}</span>
            <strong>${number(value)}</strong>
        </article>
    `).join("");

    const currentId = Number(appState.data.currentUser.id);
    const rows = appState.data.adminUsers || [];
    $("#adminUserList").innerHTML = rows.length
        ? rows.map((user) => {
            const isCurrent = Number(user.id) === currentId;
            const toggleStatus = user.status === "active" ? "inactive" : "active";
            const training = user.training_level ? ` / ${user.training_level}` : "";
            const height = Number(user.height_in) > 0 ? ` / ${number(user.height_in, 1)} in` : "";
            return `
                <article class="admin-user-card" data-admin-user-card="${user.id}">
                    <div class="admin-user-main">
                        <div>
                            <h3>${escapeHtml(user.name)}${isCurrent ? " (current)" : ""}</h3>
                            <p class="details-line">${escapeHtml(user.email || "No email")}</p>
                            <p class="details-line">${escapeHtml(user.fitness_focus || "No care focus set")}</p>
                            <p class="timeline-meta">${escapeHtml(user.phone || "No phone")}${escapeHtml(training)}${escapeHtml(height)}</p>
                        </div>
                        <div class="admin-badges">
                            <span class="badge ${escapeHtml(user.role)}">${escapeHtml(user.role)}</span>
                            <span class="badge ${escapeHtml(user.status)}">${escapeHtml(user.status)}</span>
                        </div>
                    </div>
                    <div class="admin-user-metrics">
                        <span>${number(user.routine_count)} routines</span>
                        <span>${number(user.workout_count)} workouts</span>
                        <span>${number(user.nutrition_log_count)} nutrition logs</span>
                        <span>${number(user.supplement_log_count)} supplement logs</span>
                        <span>${number(user.metric_count)} metrics</span>
                        <span>${number(user.medication_log_count)} meds</span>
                        <span>${number(user.vital_log_count)} vitals</span>
                        <span>${number(user.lab_result_count)} labs</span>
                        <span>${number(user.appointment_count)} appointments</span>
                    </div>
                    <div class="status-row">
                        <button class="status-button" type="button" data-admin-action="edit" data-admin-user-id="${user.id}">Edit</button>
                        <button class="status-button" type="button" data-admin-action="status" data-admin-user-id="${user.id}" data-next-status="${toggleStatus}">
                            ${toggleStatus === "active" ? "Activate" : "Deactivate"}
                        </button>
                        <button class="status-button danger-action" type="button" data-admin-action="delete" data-admin-user-id="${user.id}" ${isCurrent ? "disabled" : ""}>Delete</button>
                    </div>
                </article>
            `;
        }).join("")
        : `<div class="empty-state">No profiles found</div>`;
}

function resetAdminUserForm() {
    const form = $("#adminUserForm");
    if (!form) return;
    form.reset();
    form.elements.target_user_id.value = "";
    form.elements.role.value = "member";
    form.elements.status.value = "active";
    form.elements.theme_mode.value = "dark";
    form.elements.theme_accent.value = "green";
    $("#adminUserFormTitle").textContent = "Create Profile";
}

function fillAdminUserForm(user) {
    const form = $("#adminUserForm");
    if (!form || !user) return;

    form.elements.target_user_id.value = user.id || "";
    form.elements.name.value = user.name || "";
    form.elements.email.value = user.email || "";
    form.elements.role.value = user.role || "member";
    form.elements.status.value = user.status || "active";
    form.elements.phone.value = user.phone || "";
    form.elements.birthday.value = user.birthday || "";
    form.elements.height_in.value = Number(user.height_in || 0) > 0 ? user.height_in : "";
    form.elements.training_level.value = user.training_level || "";
    form.elements.theme_mode.value = user.theme_mode || "dark";
    form.elements.theme_accent.value = user.theme_accent || "green";
    form.elements.fitness_focus.value = user.fitness_focus || "";
    form.elements.emergency_contact.value = user.emergency_contact || "";
    $("#adminUserFormTitle").textContent = `Edit ${user.name}`;
}

function renderLibraries() {
    $("#exerciseLibrary").innerHTML = appState.data.exercises.map((exercise) => `
        <span class="chip">
            ${escapeHtml(exercise.name)}
            <small>${escapeHtml(exercise.category)} / ${escapeHtml(exercise.default_unit || "custom")}</small>
        </span>
    `).join("");

    $("#supplementLibrary").innerHTML = appState.data.supplements.map((supplement) => `
        <span class="chip">
            ${escapeHtml(supplement.name)}
            <small>${escapeHtml(supplement.timing)} / ${escapeHtml(supplement.default_dose || "custom")}</small>
        </span>
    `).join("");
}

function option(value, label, selected = false) {
    return `<option value="${escapeHtml(value)}" ${selected ? "selected" : ""}>${escapeHtml(label)}</option>`;
}

function populateForms() {
    const { routines, exercises, supplements, nutritionGoals, medicationCatalog, range } = appState.data;
    const routineOptions = option("", "No routine") + routines.map((routine) => option(routine.id, `${routine.name} (${routine.planner_scope})`)).join("");
    const goalOptions = option("", "Separate target") + nutritionGoals.map((goal) => option(goal.id, `${goal.label} (${goal.scope})`)).join("");
    const exerciseOptions = option("", "Choose exercise") + exercises.map((exercise) => option(exercise.id, `${exercise.name} (${exercise.category})`)).join("");
    const supplementOptions = option("", "Choose supplement") + supplements.map((supplement) => option(supplement.id, `${supplement.name} (${supplement.timing})`)).join("");
    const medicationOptions = option("", "Choose medication") + medicationCatalog.map((medicine) => option(medicine.id, `${medicine.generic_name} (${medicine.class_name})`)).join("");

    $$("#workoutForm [name='routine_id']").forEach((select) => select.innerHTML = routineOptions);
    $$("#routineForm [name='nutrition_goal_id']").forEach((select) => select.innerHTML = goalOptions);
    $$("#workoutForm [name='exercise_id']").forEach((select) => select.innerHTML = exerciseOptions);
    $$("#supplementLogForm [name='supplement_id']").forEach((select) => select.innerHTML = supplementOptions);
    $$("#medicationLogForm [name='medication_id']").forEach((select) => select.innerHTML = medicationOptions);

    const dateFields = [
        "#medicationLogForm [name='taken_on']",
        "#vitalLogForm [name='measured_on']",
        "#labResultForm [name='collected_on']",
        "#symptomLogForm [name='observed_on']",
        "#appointmentForm [name='appointment_on']",
        "#immunizationRecordForm [name='administered_on']",
        "#workoutForm [name='scheduled_on']",
        "#routineForm [name='start_date']",
        "#nutritionGoalForm [name='start_date']",
        "#nutritionLogForm [name='logged_on']",
        "#supplementLogForm [name='taken_on']",
        "#metricForm [name='measured_on']",
    ];
    dateFields.forEach((selector) => {
        const input = $(selector);
        if (input && !input.value) input.value = range.anchor;
    });
}

function formPayload(form) {
    const payload = Object.fromEntries(new FormData(form).entries());
    payload.user_id = appState.data.currentUser.id;
    return payload;
}

function adminUserPayload(form) {
    const payload = Object.fromEntries(new FormData(form).entries());
    payload.acting_user_id = appState.data.currentUser.id;
    return payload;
}

function wireForm(selector, action, message, afterSave = null) {
    const form = $(selector);
    form.addEventListener("submit", async (event) => {
        event.preventDefault();
        try {
            const result = await api(action, formPayload(form));
            if (afterSave) afterSave(result);
            form.reset();
            await loadState();
            showToast(message);
        } catch (error) {
            showToast(error.message);
        }
    });
}

function wireControls() {
    $("#profileSelect").addEventListener("change", async (event) => {
        appState.userId = event.target.value;
        localStorage.setItem("nht:userId", appState.userId);
        await loadState();
    });

    $("#datePicker").addEventListener("change", async (event) => {
        appState.date = event.target.value;
        localStorage.setItem("nht:date", appState.date);
        await loadState();
    });

    $$("[data-view]").forEach((button) => {
        button.addEventListener("click", async () => {
            appState.view = button.dataset.view;
            localStorage.setItem("nht:view", appState.view);
            await loadState();
        });
    });

    $("#darkModeButton").addEventListener("click", () => saveTheme("dark"));
    $("#lightModeButton").addEventListener("click", () => saveTheme("light"));

    $$("[data-accent]").forEach((button) => {
        button.addEventListener("click", () => saveTheme(null, button.dataset.accent));
    });

    $("#workoutTimeline").addEventListener("click", async (event) => {
        const button = event.target.closest("[data-workout-id]");
        if (!button) return;
        try {
            await api("update_workout", {
                id: button.dataset.workoutId,
                status: button.dataset.status,
            });
            await loadState();
            showToast("Workout updated");
        } catch (error) {
            showToast(error.message);
        }
    });

    document.addEventListener("click", (event) => {
        const jump = event.target.closest("[data-jump]");
        if (!jump) return;
        const target = $(jump.dataset.jump);
        if (target) {
            target.scrollIntoView({ behavior: "smooth", block: "start" });
        }
    });

    $("#workoutForm [name='exercise_id']").addEventListener("change", (event) => {
        const exercise = appState.data.exercises.find((item) => String(item.id) === event.target.value);
        const title = $("#workoutForm [name='title']");
        const type = $("#workoutForm [name='workout_type']");
        if (exercise && !title.value) title.value = exercise.name;
        if (exercise) type.value = exercise.category;
    });

    $("#supplementLogForm [name='supplement_id']").addEventListener("change", (event) => {
        const supplement = appState.data.supplements.find((item) => String(item.id) === event.target.value);
        if (!supplement) return;
        $("#supplementLogForm [name='timing']").value = supplement.timing;
        $("#supplementLogForm [name='dose']").value = supplement.default_dose;
    });

    $("#medicationLogForm [name='medication_id']").addEventListener("change", (event) => {
        const medicine = appState.data.medicationCatalog.find((item) => String(item.id) === event.target.value);
        if (!medicine) return;
        $("#medicationLogForm [name='medication_name']").value = medicine.generic_name;
        if (!$("#medicationLogForm [name='notes']").value) {
            $("#medicationLogForm [name='notes']").value = medicine.tracking_note;
        }
    });

    $("#newAdminUserButton").addEventListener("click", () => {
        resetAdminUserForm();
        $("#adminUserForm").scrollIntoView({ behavior: "smooth", block: "start" });
    });

    $("#clearAdminUserFormButton").addEventListener("click", resetAdminUserForm);

    $("#adminUserList").addEventListener("click", async (event) => {
        const button = event.target.closest("[data-admin-action]");
        if (!button) return;

        const user = (appState.data.adminUsers || []).find((item) => String(item.id) === button.dataset.adminUserId);
        if (!user) return;

        if (button.dataset.adminAction === "edit") {
            fillAdminUserForm(user);
            $("#adminUserForm").scrollIntoView({ behavior: "smooth", block: "start" });
            return;
        }

        if (button.dataset.adminAction === "status") {
            try {
                await api("update_user", {
                    acting_user_id: appState.data.currentUser.id,
                    target_user_id: user.id,
                    status: button.dataset.nextStatus,
                });
                await loadState();
                showToast("Profile status updated");
            } catch (error) {
                showToast(error.message);
            }
            return;
        }

        if (button.dataset.adminAction === "delete") {
            const ok = window.confirm(`Delete ${user.name} and all of this profile's tracker data?`);
            if (!ok) return;
            try {
                await api("delete_user", {
                    acting_user_id: appState.data.currentUser.id,
                    target_user_id: user.id,
                });
                await loadState();
                showToast("Profile deleted");
            } catch (error) {
                showToast(error.message);
            }
        }
    });
}

async function saveTheme(mode = null, accent = null) {
    const current = appState.data.currentUser;
    try {
        await api("update_theme", {
            user_id: current.id,
            theme_mode: mode || current.theme_mode || "dark",
            theme_accent: accent || current.theme_accent || "green",
        });
        await loadState();
    } catch (error) {
        showToast(error.message);
    }
}

function wireForms() {
    wireForm("#medicationLogForm", "create_medication_log", "Medication logged");
    wireForm("#vitalLogForm", "create_vital_log", "Vitals logged");
    wireForm("#labResultForm", "create_lab_result", "Lab result logged");
    wireForm("#symptomLogForm", "create_symptom_log", "Symptom logged");
    wireForm("#allergyRecordForm", "create_allergy_record", "Allergy saved");
    wireForm("#appointmentForm", "create_appointment", "Appointment saved");
    wireForm("#immunizationRecordForm", "create_immunization_record", "Immunization saved");
    wireForm("#workoutForm", "create_workout", "Workout saved");
    wireForm("#routineForm", "create_routine", "Routine saved");
    wireForm("#nutritionGoalForm", "create_nutrition_goal", "Nutrition target saved");
    wireForm("#nutritionLogForm", "create_nutrition_log", "Nutrition logged");
    wireForm("#supplementLogForm", "create_supplement_log", "Supplement logged");
    wireForm("#metricForm", "create_body_metric", "Metrics logged");
    wireForm("#exerciseForm", "create_exercise", "Exercise added");
    wireForm("#supplementForm", "create_supplement", "Supplement added");

    $("#adminUserForm").addEventListener("submit", async (event) => {
        event.preventDefault();
        const form = event.currentTarget;
        const payload = adminUserPayload(form);
        const action = payload.target_user_id ? "update_user" : "create_user";
        try {
            await api(action, payload);
            resetAdminUserForm();
            await loadState();
            showToast(action === "create_user" ? "Profile created" : "Profile updated");
        } catch (error) {
            showToast(error.message);
        }
    });
}

document.addEventListener("DOMContentLoaded", async () => {
    wireControls();
    wireForms();
    try {
        await loadState();
    } catch (error) {
        showToast(error.message);
    }
});
