/** The live UI and real tests import this same module. Broken branches are teaching fixtures. */
export function createLab(variant = 'fixed') {
  if (!['fixed', 'broken'].includes(variant)) throw new Error('Unknown implementation');
  const broken = variant === 'broken';
  return {
    total(priceCents, quantity, discountPercent = 0) {
      if (!Number.isSafeInteger(priceCents) || priceCents < 0 || !Number.isInteger(quantity) || quantity < 1 || quantity > 100 || !Number.isSafeInteger(priceCents * quantity) || !Number.isFinite(discountPercent) || discountPercent < 0 || discountPercent > 100) throw new RangeError('Некорректная цена, количество или скидка');
      if (broken) return Math.round(priceCents * quantity * (1 - discountPercent / 100)) - 1;
      return Math.round(priceCents * quantity * (1 - discountPercent / 100));
    },
    validateEmail(value) {
      if (typeof value !== 'string') return false;
      const email = broken ? value : value.trim();
      return broken ? email.includes('@') : /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
    },
    async loadCustomer(fetcher, url, signal) {
      const response = await fetcher(url, { signal });
      if (!broken && !response.ok) throw new Error(`HTTP ${response.status}`);
      const customer = await response.json();
      if (!broken && (typeof customer.name !== 'string' || typeof customer.id !== 'number')) throw new TypeError('Некорректный клиент');
      return customer;
    },
    async saveOrder(client, email, cents) {
      if (!this.validateEmail(email)) throw new TypeError('Укажите корректный email');
      return client.post('/orders', { email: broken ? email : email.trim(), totalCents: broken ? cents / 100 : cents });
    },
    debounceSearch(callback, delay = 300) {
      let timer = null;
      const pending = new Set();
      const run = (query) => {
        if (!broken && timer !== null) { clearTimeout(timer); pending.delete(timer); }
        const id = setTimeout(() => { pending.delete(id); callback(query); }, delay);
        timer = id;
        pending.add(id);
      };
      run.cancel = () => { for (const id of pending) clearTimeout(id); pending.clear(); timer = null; };
      return run;
    },
    mountContactForm(root) {
      root.innerHTML = '<form novalidate><label for="contact-email">Email клиента</label><input id="contact-email" name="email" type="email" autocomplete="off" aria-describedby="contact-status"><button type="submit">Сохранить контакт</button><p id="contact-status" role="status" aria-live="polite"></p></form>';
      const form = root.querySelector('form'), input = root.querySelector('input'), status = root.querySelector('[role=status]');
      const submit = (event) => {
        event.preventDefault(); const valid = this.validateEmail(input.value);
        if (!valid && !broken) { status.textContent = 'Укажите корректный email'; input.setAttribute('aria-invalid', 'true'); input.focus(); return; }
        input.removeAttribute('aria-invalid'); status.textContent = 'Сохранено: ' + input.value.trim();
      };
      form.addEventListener('submit', submit);
      return () => { form.removeEventListener('submit', submit); root.replaceChildren(); };
    },
    mountDisclosure(root) {
      root.innerHTML = '<div class="disclosure"><button type="button" id="details-toggle" aria-expanded="false" aria-controls="details-panel">Параметры заказа</button><section id="details-panel" hidden><label for="details-note">Заметка</label><input id="details-note" type="text"><button type="button" id="details-close">Закрыть параметры</button></section></div>';
      const toggle = root.querySelector('#details-toggle'), panel = root.querySelector('#details-panel'), input = root.querySelector('input'), close = root.querySelector('#details-close');
      const openPanel = () => { panel.hidden = !panel.hidden; if (!broken) toggle.setAttribute('aria-expanded', String(!panel.hidden)); if (!panel.hidden) input.focus(); };
      const closePanel = () => { panel.hidden = true; if (!broken) { toggle.setAttribute('aria-expanded', 'false'); toggle.focus(); } };
      const key = e => { if(e.key === 'Escape' && !panel.hidden) closePanel(); };
      toggle.addEventListener('click', openPanel); close.addEventListener('click', closePanel); root.addEventListener('keydown', key);
      return () => { toggle.removeEventListener('click', openPanel); close.removeEventListener('click', closePanel); root.removeEventListener('keydown', key); root.replaceChildren(); };
    },
    summary(order) {
      return { id: order.id, customer: order.customer, amount: (order.cents / 100).toFixed(2), currency: broken ? 'USD' : 'RUB', state: order.paid ? 'paid' : 'pending' };
    },
    canPublish(checks) {
      if (!Array.isArray(checks) || checks.length === 0) return false;
      return broken ? checks.some(Boolean) : checks.every(Boolean);
    },
    // Deliberately only partly covered in the small course: percentages are not proof of requirements.
    deliveryFee(zone) {
      if(zone === 'pickup') return 0;
      if(zone === 'city') return 500;
      if(zone === 'regional') return 1500;
      throw new RangeError('Unknown delivery zone');
    }
  };
}
