'use strict';

/* ── Utility ── */
function qs(sel, ctx) {
  return (ctx || document).querySelector(sel);
}
function qsa(sel, ctx) {
  return Array.from((ctx || document).querySelectorAll(sel));
}

/* ============================================================
   1. SCROLL REVEAL (.animate → .visible)
   ============================================================ */
(function initScrollReveal() {
  var prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;

  var elements = qsa('.animate');
  if (!elements.length) return;

  if (prefersReducedMotion) {
    elements.forEach(function (el) {
      el.classList.add('visible');
    });
    return;
  }

  var observer = new IntersectionObserver(
    function (entries) {
      entries.forEach(function (entry) {
        if (entry.isIntersecting) {
          entry.target.classList.add('visible');
          observer.unobserve(entry.target);
        }
      });
    },
    { threshold: 0.15 }
  );

  elements.forEach(function (el) {
    observer.observe(el);
  });
})();

/* ============================================================
   2. STAT COUNT-UP
   ============================================================ */
(function initStatCounters() {
  var bands = qsa('.stats-band');
  if (!bands.length) return;

  function easeOutQuart(t) {
    return 1 - Math.pow(1 - t, 4);
  }

  function animateStat(el) {
    var raw = el.getAttribute('data-target');
    if (raw === null) return;

    var target = parseFloat(raw);
    var suffix = el.getAttribute('data-suffix') || '';
    var duration = 1200;
    var startTime = null;

    function step(timestamp) {
      if (!startTime) startTime = timestamp;
      var elapsed = timestamp - startTime;
      var progress = Math.min(elapsed / duration, 1);
      var eased = easeOutQuart(progress);
      var current = Math.round(target * eased);

      el.textContent = current + suffix;

      if (progress < 1) {
        requestAnimationFrame(step);
      } else {
        el.textContent = target + suffix;
      }
    }

    requestAnimationFrame(step);
  }

  bands.forEach(function (band) {
    var nums = band.querySelectorAll('[data-target]');
    if (!nums.length) return;

    var fired = false;
    var observer = new IntersectionObserver(
      function (entries) {
        entries.forEach(function (entry) {
          if (entry.isIntersecting && !fired) {
            fired = true;
            observer.unobserve(entry.target);
            nums.forEach(function (el) {
              animateStat(el);
            });
          }
        });
      },
      { threshold: 0.5 }
    );

    observer.observe(band);
  });
})();

/* ============================================================
   3. TERMINAL TYPING ANIMATION (index.html only)
   ============================================================ */
(function initTerminal() {
  var terminalBody = qs('.terminal-body');
  if (!terminalBody) return;

  var prefersReduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;

  var lines = qsa('.terminal-line', terminalBody);
  if (!lines.length) return;

  /* If reduced motion, ensure everything is visible immediately */
  if (prefersReduced) {
    lines.forEach(function (el) {
      el.style.display = '';
      el.style.visibility = 'visible';
      el.style.opacity = '1';
    });
    var cur = qs('.terminal-cursor', terminalBody);
    if (cur) {
      cur.style.visibility = 'visible';
    }
    return;
  }

  var CHAR_DELAY = 55;
  var LINE_PAUSE = 420;

  /* Hide ALL lines initially — use opacity+visibility so layout is preserved.
     For the success line which has style='display:none' in HTML, we normalise
     it here to the same opacity/visibility mechanism so revealLine can show it. */
  lines.forEach(function (el) {
    el.style.display = '';
    el.style.opacity = '0';
    el.style.visibility = 'hidden';
  });

  var cursor = qs('.terminal-cursor', terminalBody);
  if (cursor) {
    cursor.style.opacity = '0';
    cursor.style.visibility = 'hidden';
  }

  var currentLineIndex = 0;

  function revealLine(el, callback) {
    el.style.display = '';
    el.style.visibility = 'visible';
    el.style.opacity = '1';
    setTimeout(callback, LINE_PAUSE);
  }

  function typePromptLine(el, callback) {
    var promptPart = '$ orchestra build --brief ';
    var strPart = '"Moderne nettside for advokatfirma"';
    var fullText = promptPart + strPart;

    /* Operate on the inner .terminal-prompt span if it exists,
       otherwise fall back to the element itself */
    var target = el.querySelector('.terminal-prompt') || el;

    target.textContent = '';
    el.style.display = '';
    el.style.opacity = '1';
    el.style.visibility = 'visible';

    var charIndex = 0;

    function step() {
      charIndex++;
      var typed = fullText.slice(0, charIndex);

      /* Rebuild the inner content with coloured spans */
      while (target.firstChild) {
        target.removeChild(target.firstChild);
      }

      if (typed.length <= promptPart.length) {
        var promptSpan = document.createElement('span');
        promptSpan.className = 'terminal-prompt-cmd';
        promptSpan.textContent = typed;
        target.appendChild(promptSpan);
      } else {
        var promptSpan2 = document.createElement('span');
        promptSpan2.className = 'terminal-prompt-cmd';
        promptSpan2.textContent = promptPart;
        target.appendChild(promptSpan2);

        var strSpan = document.createElement('span');
        strSpan.className = 'terminal-prompt-str';
        strSpan.textContent = typed.slice(promptPart.length);
        target.appendChild(strSpan);
      }

      if (charIndex < fullText.length) {
        setTimeout(step, CHAR_DELAY);
      } else {
        setTimeout(callback, LINE_PAUSE);
      }
    }

    step();
  }

  function processNextLine() {
    if (currentLineIndex >= lines.length) {
      if (cursor) {
        cursor.style.visibility = 'visible';
        cursor.style.opacity = '1';
      }
      return;
    }

    var el = lines[currentLineIndex];
    currentLineIndex++;

    if (el.classList.contains('terminal-line--prompt')) {
      typePromptLine(el, processNextLine);
    } else {
      revealLine(el, processNextLine);
    }
  }

  /* Small delay before starting so the terminal panel has rendered */
  setTimeout(processNextLine, 600);
})();

/* ============================================================
   4. CONTACT FORM
   ============================================================ */
(function initContactForm() {
  var form = qs('.contact-form');
  if (!form) return;

  /* Leave real-endpoint path open */
  if (form.getAttribute('action')) return;

  var successPanel = qs('#contact-form-success');
  var resetBtn = qs('.contact-reset');
  var submitBtn = qs('#contact-submit', form) || qs('.form-submit', form);

  var nameInput = qs('#contact-name');
  var nameError = qs('#contact-name-error');
  var emailInput = qs('#contact-email');
  var emailError = qs('#contact-email-error');
  var messageInput = qs('#contact-message');
  var messageError = qs('#contact-message-error');

  if (!nameInput || !emailInput || !messageInput) return;

  function showError(input, errorEl, msg) {
    if (!errorEl) return;
    input.classList.add('form-input--error');
    errorEl.textContent = msg;
    errorEl.style.display = 'block';
  }

  function clearError(input, errorEl) {
    if (!errorEl) return;
    input.classList.remove('form-input--error');
    errorEl.textContent = '';
    errorEl.style.display = 'none';
  }

  function validateForm() {
    var valid = true;
    var firstInvalid = null;

    /* Name */
    if (!nameInput.value.trim()) {
      showError(nameInput, nameError, 'Navn er påkrevd.');
      if (!firstInvalid) firstInvalid = nameInput;
      valid = false;
    } else {
      clearError(nameInput, nameError);
    }

    /* Email */
    var emailVal = emailInput.value.trim();
    var emailRe = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    if (!emailVal) {
      showError(emailInput, emailError, 'E-post er påkrevd.');
      if (!firstInvalid) firstInvalid = emailInput;
      valid = false;
    } else if (!emailRe.test(emailVal)) {
      showError(emailInput, emailError, 'Skriv inn en gyldig e-postadresse.');
      if (!firstInvalid) firstInvalid = emailInput;
      valid = false;
    } else {
      clearError(emailInput, emailError);
    }

    /* Message */
    if (!messageInput.value.trim()) {
      showError(messageInput, messageError, 'Melding er påkrevd.');
      if (!firstInvalid) firstInvalid = messageInput;
      valid = false;
    } else {
      clearError(messageInput, messageError);
    }

    if (firstInvalid) {
      firstInvalid.focus();
    }
    return valid;
  }

  /* Clear errors on user input */
  [
    { input: nameInput, error: nameError },
    { input: emailInput, error: emailError },
    { input: messageInput, error: messageError },
  ].forEach(function (pair) {
    if (!pair.input) return;
    pair.input.addEventListener('input', function () {
      clearError(pair.input, pair.error);
    });
  });

  form.addEventListener('submit', function (e) {
    e.preventDefault();

    if (!validateForm()) return;

    if (submitBtn) {
      submitBtn.disabled = true;
      submitBtn.textContent = 'Sender...';
      submitBtn.style.opacity = '0.7';
      submitBtn.style.cursor = 'wait';
    }

    setTimeout(function () {
      form.style.display = 'none';

      if (successPanel) {
        successPanel.removeAttribute('hidden');
        successPanel.focus();
      }

      if (submitBtn) {
        submitBtn.disabled = false;
        submitBtn.textContent = 'Send melding';
        submitBtn.style.opacity = '';
        submitBtn.style.cursor = '';
      }
    }, 800);
  });

  if (resetBtn) {
    resetBtn.addEventListener('click', function () {
      form.style.display = '';
      form.reset();

      clearError(nameInput, nameError);
      clearError(emailInput, emailError);
      clearError(messageInput, messageError);

      if (successPanel) {
        successPanel.setAttribute('hidden', '');
      }

      nameInput.focus();
    });
  }
})();

/* ============================================================
   5. ACTIVE NAV LINK HIGHLIGHT
   ============================================================ */
(function initActiveNavLink() {
  var current = window.location.pathname.split('/').pop() || 'index.html';
  if (current === '') current = 'index.html';

  var links = document.querySelectorAll('.ns-links a');
  links.forEach(function (link) {
    var href = (link.getAttribute('href') || '').split('/').pop();
    if (href === current || (current === 'index.html' && (href === '' || href === 'index.html'))) {
      link.classList.add('active');
    }
  });
})();

/* ============================================================
   6. SCROLL TO TOP
   ============================================================ */
(function initScrollToTop() {
  var btn = qs('.scroll-to-top');
  if (!btn) return;

  window.addEventListener(
    'scroll',
    function () {
      btn.classList.toggle('visible', window.scrollY > 600);
    },
    { passive: true }
  );

  btn.addEventListener('click', function () {
    window.scrollTo({ top: 0, behavior: 'smooth' });
  });
})();

/* ============================================================
   7. FOOTER YEAR
   ============================================================ */
(function initFooterYear() {
  var yearEl = document.getElementById('footer-year');
  if (!yearEl) return;
  yearEl.textContent = new Date().getFullYear();
})();

/* ============================================================
   NAVIGATION SCAFFOLD — DO NOT EDIT (managed by Orchestra)
   ============================================================ */
(function () {
  var nav = document.getElementById('ns-nav');
  var linksContainer = document.getElementById('ns-links');
  var burger = document.getElementById('ns-hamburger');
  var overlay = document.getElementById('ns-overlay');
  if (!nav || !linksContainer || !burger) return;

  var isOpen = false;

  function openMenu() {
    isOpen = true;
    linksContainer.classList.add('open');
    if (overlay) {
      overlay.classList.add('open');
      overlay.setAttribute('aria-hidden', 'false');
    }
    burger.setAttribute('aria-expanded', 'true');
    document.body.style.overflow = 'hidden';
  }

  function closeMenu() {
    isOpen = false;
    linksContainer.classList.remove('open');
    if (overlay) {
      overlay.classList.remove('open');
      overlay.setAttribute('aria-hidden', 'true');
    }
    burger.setAttribute('aria-expanded', 'false');
    document.body.style.overflow = '';
  }

  function toggleMenu() {
    if (isOpen) closeMenu();
    else openMenu();
  }

  // Event listeners
  burger.addEventListener('click', toggleMenu);
  if (overlay) overlay.addEventListener('click', closeMenu);

  linksContainer.querySelectorAll('a').forEach(function (link) {
    link.addEventListener('click', function () {
      if (window.innerWidth <= 768) closeMenu();
    });
  });

  // Keyboard — Escape closes menu
  document.addEventListener('keydown', function (e) {
    if (e.key === 'Escape' && isOpen) {
      closeMenu();
      burger.focus();
    }
  });

  // Resize safety — prevents double nav when resizing from mobile to desktop
  window.addEventListener(
    'resize',
    function () {
      if (window.innerWidth > 768 && isOpen) {
        closeMenu();
      }
    },
    { passive: true }
  );

  // Scroll effect — transparent to solid background
  window.addEventListener(
    'scroll',
    function () {
      nav.classList.toggle('scrolled', window.scrollY > 80);
    },
    { passive: true }
  );

  // Active link highlighting via IntersectionObserver
  var sections = [];
  linksContainer.querySelectorAll('a[href^="#"]').forEach(function (a) {
    var id = a.getAttribute('href').slice(1);
    var el = document.getElementById(id);
    if (el) sections.push({ el: el, link: a });
  });
  if (sections.length && 'IntersectionObserver' in window) {
    var obs = new IntersectionObserver(
      function (entries) {
        entries.forEach(function (entry) {
          if (entry.isIntersecting) {
            linksContainer.querySelectorAll('a').forEach(function (a) {
              a.classList.remove('active');
            });
            sections.forEach(function (s) {
              if (s.el === entry.target) s.link.classList.add('active');
            });
          }
        });
      },
      { rootMargin: '-20% 0px -70% 0px', threshold: 0 }
    );
    sections.forEach(function (s) {
      obs.observe(s.el);
    });
  }
})();

/* ============================================================
   NAV CONTROLS SCAFFOLD — DO NOT EDIT (managed by Orchestra)
   ------------------------------------------------------------
   Wires the optional right-slot controls (search trigger, theme
   toggle) to their behaviour. Both branches are guarded by an
   element-existence check, so this block is inert on builds that
   don't opt in to controls.

   TRIGGERED-COMPONENT INVARIANT (see core/nav_scaffold.py docstring):
   • #ns-search-modal defaults to `hidden` + CSS `display:none`.
   • Open state is set ONLY here, in response to a user click.
   • Close paths: backdrop click, close button, Escape key.
   • Re-opening focus returns to the trigger for keyboard users.

   Do not duplicate this logic in script.js. Do not pre-open the
   modal in markup. Open state belongs to the user, not the template.
   ============================================================ */
(function () {
  // ── Search modal ───────────────────────────────────────────────────────
  var trigger = document.getElementById('ns-search-trigger');
  var modal = document.getElementById('ns-search-modal');
  if (trigger && modal) {
    var input = modal.querySelector('#ns-search-input');
    var closers = modal.querySelectorAll('[data-ns-search-close]');

    var openSearch = function () {
      modal.removeAttribute('hidden');
      modal.classList.add('open');
      modal.setAttribute('aria-hidden', 'false');
      trigger.setAttribute('aria-expanded', 'true');
      document.body.style.overflow = 'hidden';
      if (input)
        setTimeout(function () {
          input.focus();
        }, 30);
    };
    var closeSearch = function () {
      modal.classList.remove('open');
      modal.setAttribute('hidden', '');
      modal.setAttribute('aria-hidden', 'true');
      trigger.setAttribute('aria-expanded', 'false');
      document.body.style.overflow = '';
      trigger.focus();
    };

    trigger.addEventListener('click', openSearch);
    closers.forEach(function (el) {
      el.addEventListener('click', closeSearch);
    });
    document.addEventListener('keydown', function (e) {
      if (e.key === 'Escape' && modal.classList.contains('open')) closeSearch();
    });
  }

  // ── Theme toggle ───────────────────────────────────────────────────────
  var themeBtn = document.getElementById('ns-theme-toggle');
  if (themeBtn) {
    var STORAGE_KEY = 'orch-theme';

    var applyTheme = function (t) {
      document.documentElement.setAttribute('data-theme', t);
      themeBtn.setAttribute('aria-pressed', t === 'light' ? 'true' : 'false');
    };

    var stored = null;
    try {
      stored = localStorage.getItem(STORAGE_KEY);
    } catch (_) {
      /* storage blocked (private mode / 3rd-party cookies off) */
    }
    applyTheme(stored === 'light' ? 'light' : 'dark');

    themeBtn.addEventListener('click', function () {
      var current = document.documentElement.getAttribute('data-theme');
      var next = current === 'light' ? 'dark' : 'light';
      try {
        localStorage.setItem(STORAGE_KEY, next);
      } catch (_) {
        /* storage blocked: the theme still applies for this page */
      }
      applyTheme(next);
    });
  }
})();
/* END NAVIGATION SCAFFOLD */

/* ============================================================
   NAV PAGE-ACTIVE SCAFFOLD — DO NOT EDIT (managed by Orchestra)
   Multi-page builds: mark the current page's nav link .active by
   matching normalised pathnames. Works under file://, http(s)://,
   index/root, trailing slash, and extension-less routes.
   ============================================================ */
(function () {
  var links = document.getElementById('ns-links');
  if (!links) return;
  function pageKey(p) {
    try {
      p = decodeURIComponent(p || '');
    } catch (_) {
      /* malformed %-escape: fall through with the raw path */
    }
    p = p.split('#')[0].split('?')[0].replace(/\\/g, '/');
    var seg = p.substring(p.lastIndexOf('/') + 1).toLowerCase();
    if (seg === '' || seg === 'index.html' || seg === 'home.html') return 'index.html';
    if (seg.indexOf('.') === -1) seg += '.html';
    return seg;
  }
  var current = pageKey(window.location.pathname || window.location.href);
  links.querySelectorAll('a').forEach(function (a) {
    var href = a.getAttribute('href') || '';
    if (href.charAt(0) === '#') return; // in-page anchor, not a page link
    if (pageKey(href) === current) {
      a.classList.add('active');
      a.setAttribute('aria-current', 'page');
    } else {
      a.classList.remove('active');
      a.removeAttribute('aria-current');
    }
  });
})();
/* END NAV PAGE-ACTIVE SCAFFOLD */