import { apiPatch, apiPost, invalidateSessionCheck } from './api.js';
import { getRole, getUser, showToast, formatRoleLabel } from './app.js';

/** @typedef {'admin_reset' | 'self'} PasswordModalMode */

/** @type {{ mode: PasswordModalMode, userID?: string, username?: string, role?: string } | null} */
let modalContext = null;

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

function roleLabel(role) {
    return formatRoleLabel(role);
}

function signInHintForRole(role) {
    if (role === 'coach') {
        return 'Counselors sign in through the mobile app and will be prompted to choose a new password there.';
    }
    return 'Supervisors sign in through this website and will be prompted to choose a new password at login.';
}

function ensurePasswordModal() {
    let modal = document.getElementById('passwordModal');
    if (modal) return modal;

    modal = document.createElement('div');
    modal.id = 'passwordModal';
    modal.className = 'modal-overlay';
    modal.hidden = true;
    modal.setAttribute('role', 'dialog');
    modal.setAttribute('aria-modal', 'true');
    modal.setAttribute('aria-labelledby', 'passwordModalTitle');
    modal.innerHTML = `
        <div class="modal-dialog">
            <h2 id="passwordModalTitle">Password</h2>
            <p class="modal-subtitle" id="passwordModalSubtitle"></p>
            <p class="modal-hint" id="passwordModalHint"></p>
            <p class="modal-hint" id="passwordModalTempHint" style="display:none">
                They sign in with the password below, then must choose their own password before they can continue.
            </p>
            <div class="form-group" id="passwordModalOldGroup" style="display:none">
                <label for="pw_old_password">Current password</label>
                <input type="password" id="pw_old_password" autocomplete="current-password" placeholder="Your current password">
            </div>
            <div class="form-group">
                <label for="pw_new_password">New password</label>
                <input type="password" id="pw_new_password" autocomplete="new-password" placeholder="At least 6 characters">
            </div>
            <div class="form-group">
                <label for="pw_new_password_confirm">Confirm new password</label>
                <input type="password" id="pw_new_password_confirm" autocomplete="new-password" placeholder="Repeat password">
            </div>
            <p id="passwordModalError" class="error-text" style="display:none"></p>
            <div class="modal-actions">
                <button type="button" class="btn btn-sm" data-password-cancel>Cancel</button>
                <button type="button" class="btn btn-primary btn-sm" data-password-submit>Save</button>
            </div>
        </div>
    `;
    document.body.appendChild(modal);

    modal.addEventListener('click', (e) => {
        if (e.target === modal) closePasswordModal();
    });
    modal.querySelector('[data-password-cancel]').addEventListener('click', closePasswordModal);
    modal.querySelector('[data-password-submit]').addEventListener('click', submitPasswordModal);
    modal.querySelector('#pw_new_password_confirm').addEventListener('keydown', (e) => {
        if (e.key === 'Enter') submitPasswordModal();
    });

    document.addEventListener('keydown', (e) => {
        const el = document.getElementById('passwordModal');
        if (!el || el.hidden) return;
        if (e.key === 'Escape') closePasswordModal();
    });

    return modal;
}

/**
 * @param {{ mode: PasswordModalMode, userID?: string, username?: string, role?: string }} options
 */
function openPasswordModal(options) {
    modalContext = options;
    const modal = ensurePasswordModal();
    const isSelf = options.mode === 'self';
    const username = options.username || getUser();
    const role = options.role || getRole();

    modal.querySelector('#passwordModalTitle').textContent = isSelf ? 'Change your password' : 'Reset password';
    modal.querySelector('#passwordModalSubtitle').innerHTML = isSelf
        ? `Choose a new password for <strong>${esc(username)}</strong> (${esc(roleLabel(role))}).`
        : `Set a new password for <strong>${esc(username)}</strong> (${esc(roleLabel(role))}).`;
    modal.querySelector('#passwordModalHint').textContent = isSelf
        ? 'You will stay signed in after saving. Use this password on your next login.'
        : signInHintForRole(role);

    modal.querySelector('#passwordModalTempHint').style.display = isSelf ? 'none' : '';
    modal.querySelector('#passwordModalOldGroup').style.display = isSelf ? '' : 'none';

    modal.querySelector('#pw_old_password').value = '';
    modal.querySelector('#pw_new_password').value = '';
    modal.querySelector('#pw_new_password_confirm').value = '';
    const errEl = modal.querySelector('#passwordModalError');
    errEl.style.display = 'none';
    errEl.textContent = '';

    modal.querySelector('[data-password-submit]').textContent = isSelf ? 'Change password' : 'Set password';

    modal.hidden = false;
    document.body.classList.add('modal-open');
    (isSelf ? modal.querySelector('#pw_old_password') : modal.querySelector('#pw_new_password')).focus();
}

export function closePasswordModal() {
    const modal = document.getElementById('passwordModal');
    if (modal) modal.hidden = true;
    document.body.classList.remove('modal-open');
    modalContext = null;
}

export function openAdminResetPasswordModal({ userID, username, role }) {
    openPasswordModal({ mode: 'admin_reset', userID, username, role });
}

export function openChangeOwnPasswordModal() {
    openPasswordModal({ mode: 'self' });
}

function showModalError(el, msg) {
    el.textContent = msg;
    el.style.display = '';
}

async function submitPasswordModal() {
    if (!modalContext) return;
    const modal = document.getElementById('passwordModal');
    const errEl = modal.querySelector('#passwordModalError');
    errEl.style.display = 'none';

    const newPassword = modal.querySelector('#pw_new_password').value;
    const confirm = modal.querySelector('#pw_new_password_confirm').value;

    if (newPassword.length < 6) {
        showModalError(errEl, 'Password must be at least 6 characters');
        return;
    }
    if (newPassword !== confirm) {
        showModalError(errEl, 'Passwords do not match');
        return;
    }

    const submitBtn = modal.querySelector('[data-password-submit]');
    submitBtn.disabled = true;
    const prevLabel = submitBtn.textContent;
    submitBtn.textContent = 'Saving…';

    try {
        if (modalContext.mode === 'self') {
            const oldPassword = modal.querySelector('#pw_old_password').value;
            if (!oldPassword) {
                showModalError(errEl, 'Current password is required');
                return;
            }
            const data = await apiPost('auth/change-password', {
                username: getUser(),
                old_password: oldPassword,
                new_password: newPassword,
            });
            if (!data.success) throw new Error(data.error || 'Failed to change password');
            if (data.token) localStorage.setItem('qdb_token', data.token);
            if (data.user) localStorage.setItem('qdb_user', data.user);
            if (data.role) localStorage.setItem('qdb_role', data.role);
            invalidateSessionCheck();
            closePasswordModal();
            showToast('Your password was changed', 'success');
            return;
        }

        const { userID, username } = modalContext;

        const data = await apiPatch('users.php', {
            userID,
            password: newPassword,
            mustChangePassword: 1,
        });
        if (!data.success) throw new Error(data.error || 'Failed to reset password');

        closePasswordModal();
        showToast(
            `Temporary password set for "${username}" — they must change it on next sign-in`,
            'success'
        );

        document.dispatchEvent(new CustomEvent('qdb:password-reset', {
            detail: { userID, mustChangePassword: data.mustChangePassword ?? 1 },
        }));
    } catch (e) {
        showModalError(errEl, e.message);
    } finally {
        submitBtn.disabled = false;
        submitBtn.textContent = prevLabel;
    }
}
