"""JavaScript Generator for LandingForge."""


class JSGenerator:
    """Generates all JavaScript files for the landing page."""

    def __init__(self, config: dict):
        self.config = config
        self.content = config.get("content", {})
        self.languages = config.get("languages", {})

    def generate_main_js(self) -> str:
        return r"""// =====================================================
// LandingForge — main.js
// =====================================================
(function () {
  'use strict';

  // ── Nav scroll shrink ──────────────────────────────
  var navbar = document.querySelector('.navbar');
  if (navbar) {
    window.addEventListener('scroll', function () {
      navbar.classList.toggle('scrolled', window.scrollY > 50);
    }, { passive: true });
  }

  // ── Mobile menu toggle ────────────────────────────
  var hamburger = document.querySelector('.hamburger');
  var mobileNav = document.querySelector('.mobile-nav');
  if (hamburger && mobileNav) {
    hamburger.addEventListener('click', function () {
      hamburger.classList.toggle('open');
      mobileNav.classList.toggle('open');
      document.body.style.overflow = mobileNav.classList.contains('open') ? 'hidden' : '';
    });
    mobileNav.querySelectorAll('a').forEach(function (link) {
      link.addEventListener('click', function () {
        hamburger.classList.remove('open');
        mobileNav.classList.remove('open');
        document.body.style.overflow = '';
      });
    });
  }

  // ── Active section highlighting ───────────────────
  var sections = document.querySelectorAll('section[id]');
  var navLinks = document.querySelectorAll('.navbar-links a[href^="#"]');
  if (sections.length && navLinks.length && 'IntersectionObserver' in window) {
    var sectionObserver = new IntersectionObserver(function (entries) {
      entries.forEach(function (entry) {
        if (entry.isIntersecting) {
          var id = entry.target.getAttribute('id');
          navLinks.forEach(function (link) {
            link.classList.toggle('active', link.getAttribute('href') === '#' + id);
          });
        }
      });
    }, { threshold: 0.4 });
    sections.forEach(function (section) { sectionObserver.observe(section); });
  }

  // ── Smooth scroll for anchor links ────────────────
  document.querySelectorAll('a[href^="#"]').forEach(function (anchor) {
    anchor.addEventListener('click', function (e) {
      var targetId = anchor.getAttribute('href').slice(1);
      if (!targetId) return;
      var target = document.getElementById(targetId);
      if (target) {
        e.preventDefault();
        var navbarHeight = navbar ? navbar.offsetHeight : 0;
        var top = target.getBoundingClientRect().top + window.pageYOffset - navbarHeight - 16;
        window.scrollTo({ top: top, behavior: 'smooth' });
      }
    });
  });

  // ── Lazy loading sections ─────────────────────────
  if ('IntersectionObserver' in window) {
    var lazyObserver = new IntersectionObserver(function (entries, obs) {
      entries.forEach(function (entry) {
        if (entry.isIntersecting) {
          entry.target.classList.add('loaded');
          obs.unobserve(entry.target);
        }
      });
    }, { threshold: 0.15 });
    document.querySelectorAll('.lazy').forEach(function (el) { lazyObserver.observe(el); });
  } else {
    document.querySelectorAll('.lazy').forEach(function (el) { el.classList.add('loaded'); });
  }

  // ── Feature tab click handler ─────────────────────
  var featureTabs = document.querySelectorAll('.feature-tab');
  var featurePanels = document.querySelectorAll('.feature-panel');
  featureTabs.forEach(function (tab) {
    tab.addEventListener('click', function () {
      var index = tab.getAttribute('data-tab');
      featureTabs.forEach(function (t) { t.classList.remove('active'); });
      featurePanels.forEach(function (p) { p.classList.remove('active'); });
      tab.classList.add('active');
      var panel = document.querySelector('.feature-panel[data-tab="' + index + '"]');
      if (panel) panel.classList.add('active');
    });
  });

  // ── FAQ accordion ─────────────────────────────────
  var faqItems = document.querySelectorAll('.faq-item');
  faqItems.forEach(function (item) {
    var question = item.querySelector('.faq-question');
    if (question) {
      question.addEventListener('click', function () {
        var isActive = item.classList.contains('active');
        // Single-open: close all others
        faqItems.forEach(function (other) { other.classList.remove('active'); });
        if (!isActive) { item.classList.add('active'); }
      });
    }
  });

  // ── Back to top ───────────────────────────────────
  var backToTop = document.querySelector('.back-to-top');
  if (backToTop) {
    window.addEventListener('scroll', function () {
      backToTop.classList.toggle('visible', window.scrollY > 300);
    }, { passive: true });
    backToTop.addEventListener('click', function () {
      window.scrollTo({ top: 0, behavior: 'smooth' });
    });
  }

  // ── Image lazy loading (data-src swap) ────────────
  if ('IntersectionObserver' in window) {
    var imgObserver = new IntersectionObserver(function (entries, obs) {
      entries.forEach(function (entry) {
        if (entry.isIntersecting) {
          var img = entry.target;
          var src = img.getAttribute('data-src');
          if (src) {
            img.src = src;
            img.removeAttribute('data-src');
            img.addEventListener('load', function () { img.classList.add('loaded'); });
          }
          obs.unobserve(img);
        }
      });
    }, { threshold: 0.1 });
    document.querySelectorAll('img[data-src]').forEach(function (img) { imgObserver.observe(img); });
  } else {
    document.querySelectorAll('img[data-src]').forEach(function (img) {
      img.src = img.getAttribute('data-src');
      img.removeAttribute('data-src');
      img.classList.add('loaded');
    });
  }

})();
"""

    def generate_hero_js(self) -> str:
        rotating_texts = self.content.get("hero", {}).get("rotating_texts", ["Content"])
        texts_json = str(rotating_texts).replace("'", '"')
        return f"""// =====================================================
// LandingForge — hero-animations.js
// =====================================================
(function () {{
  'use strict';

  // ── Rotating Text ────────────────────────────────
  var rotatingEl = document.querySelector('.rotating-text');
  var texts = {texts_json};
  var current = 0;

  function rotateText() {{
    if (!rotatingEl || texts.length < 2) return;
    rotatingEl.classList.add('fade-out');
    setTimeout(function () {{
      current = (current + 1) % texts.length;
      rotatingEl.textContent = texts[current];
      rotatingEl.classList.remove('fade-out');
      rotatingEl.classList.add('fade-in');
      setTimeout(function () {{
        rotatingEl.classList.remove('fade-in');
      }}, 400);
    }}, 400);
  }}

  if (rotatingEl && texts.length > 0) {{
    rotatingEl.textContent = texts[0];
    setInterval(rotateText, 3000);
  }}

  // ── Typing Effect ─────────────────────────────────
  var typingEl = document.querySelector('.hero-prompt-input');
  if (typingEl) {{
    var phrases = [
      'Write a blog post about AI trends in 2026...',
      'Create a product description for my SaaS tool...',
      'Generate 5 email subject lines for my campaign...',
    ];
    var phraseIndex = 0;
    var charIndex = 0;
    var isDeleting = false;
    var typeDelay = 50;

    function typeLoop() {{
      var phrase = phrases[phraseIndex];
      if (isDeleting) {{
        charIndex--;
        typingEl.placeholder = phrase.substring(0, charIndex) + '|';
        if (charIndex === 0) {{
          isDeleting = false;
          phraseIndex = (phraseIndex + 1) % phrases.length;
          setTimeout(typeLoop, 500);
          return;
        }}
        setTimeout(typeLoop, 30);
      }} else {{
        charIndex++;
        typingEl.placeholder = phrase.substring(0, charIndex) + '|';
        if (charIndex === phrase.length) {{
          isDeleting = true;
          setTimeout(typeLoop, 2000);
          return;
        }}
        setTimeout(typeLoop, typeDelay);
      }}
    }}
    typeLoop();
  }}

  // ── Gradient Background Animation ────────────────
  var hero = document.querySelector('.hero');
  if (hero) {{
    var angle = 0;
    setInterval(function () {{
      angle = (angle + 0.3) % 360;
      hero.style.backgroundPosition = angle + '% 50%';
    }}, 50);
  }}

}})();
"""

    def generate_language_switcher_js(self) -> str:
        supported = self.languages.get("supported", [])
        default_lang = self.languages.get("default", "en")
        auto_detect = self.languages.get("auto_detect", True)
        codes_json = str([l["code"] for l in supported]).replace("'", '"')
        return f"""// =====================================================
// LandingForge — language-switcher.js
// =====================================================
(function () {{
  'use strict';

  var SUPPORTED = {codes_json};
  var DEFAULT   = '{default_lang}';
  var AUTO_DETECT = {'true' if auto_detect else 'false'};

  // ── Dropdown toggle ───────────────────────────────
  document.querySelectorAll('.lang-switcher-btn').forEach(function (btn) {{
    btn.addEventListener('click', function (e) {{
      e.stopPropagation();
      var dropdown = btn.parentElement.querySelector('.lang-dropdown');
      if (dropdown) dropdown.classList.toggle('open');
    }});
  }});

  document.addEventListener('click', function () {{
    document.querySelectorAll('.lang-dropdown.open').forEach(function (d) {{
      d.classList.remove('open');
    }});
  }});

  // ── Set language preference ───────────────────────
  function setLanguagePref(code) {{
    localStorage.setItem('lf_lang', code);
    document.cookie = 'lf_lang=' + code + '; path=/; max-age=' + (365 * 86400) + '; SameSite=Lax';
  }}

  // ── Redirect to language version ─────────────────
  function redirectToLang(code) {{
    setLanguagePref(code);
    if (code === DEFAULT) {{
      window.location.href = '/';
    }} else {{
      window.location.href = '/lang/' + code + '/';
    }}
  }}

  // ── Wire up lang links ────────────────────────────
  document.querySelectorAll('[data-lang]').forEach(function (el) {{
    el.addEventListener('click', function (e) {{
      e.preventDefault();
      var code = el.getAttribute('data-lang');
      if (SUPPORTED.indexOf(code) !== -1) {{
        redirectToLang(code);
      }}
    }});
  }});

  // ── Auto-detect on first visit ────────────────────
  if (AUTO_DETECT) {{
    var stored = localStorage.getItem('lf_lang');
    if (!stored) {{
      var browserLang = (navigator.language || navigator.userLanguage || 'en').split('-')[0].toLowerCase();
      if (SUPPORTED.indexOf(browserLang) !== -1 && browserLang !== DEFAULT) {{
        var currentPath = window.location.pathname;
        var isRoot = currentPath === '/' || currentPath === '/index.html';
        if (isRoot) {{
          redirectToLang(browserLang);
        }}
      }}
    }}
  }}

}})();
"""

    def generate_cookie_consent_js(self) -> str:
        gdpr = self.config.get("gdpr", {})
        categories = gdpr.get("cookie_categories", [])
        cats_json = str([c["name"] for c in categories]).replace("'", '"')
        return f"""// =====================================================
// LandingForge — cookie-consent.js
// =====================================================
(function () {{
  'use strict';

  var CATEGORIES = {cats_json};
  var COOKIE_NAME = 'lf_consent';
  var EXPIRY_DAYS = 365;

  // ── Read cookie ───────────────────────────────────
  function getCookie(name) {{
    var match = document.cookie.match(new RegExp('(?:^|; )' + name + '=([^;]*)'));
    return match ? decodeURIComponent(match[1]) : null;
  }}

  // ── Set cookie ────────────────────────────────────
  function setCookie(name, value, days) {{
    var expires = new Date(Date.now() + days * 864e5).toUTCString();
    document.cookie = name + '=' + encodeURIComponent(value) + '; expires=' + expires + '; path=/; SameSite=Lax';
  }}

  // ── Show/hide banner ──────────────────────────────
  var banner = document.getElementById('cookie-banner');
  function showBanner() {{ if (banner) banner.classList.add('visible'); }}
  function hideBanner() {{ if (banner) banner.classList.remove('visible'); }}

  // ── Save preferences ─────────────────────────────
  function saveConsent(accepted) {{
    var prefs = {{ timestamp: new Date().toISOString(), categories: {{}} }};
    CATEGORIES.forEach(function (cat) {{
      var el = document.getElementById('cookie-cat-' + cat);
      prefs.categories[cat] = el ? el.checked : accepted;
    }});
    setCookie(COOKIE_NAME, JSON.stringify(prefs), EXPIRY_DAYS);
    hideBanner();
  }}

  // ── Accept all ────────────────────────────────────
  var btnAccept = document.getElementById('cookie-accept');
  if (btnAccept) {{
    btnAccept.addEventListener('click', function () {{
      CATEGORIES.forEach(function (cat) {{
        var el = document.getElementById('cookie-cat-' + cat);
        if (el) el.checked = true;
      }});
      saveConsent(true);
    }});
  }}

  // ── Reject (necessary only) ───────────────────────
  var btnReject = document.getElementById('cookie-reject');
  if (btnReject) {{
    btnReject.addEventListener('click', function () {{
      CATEGORIES.forEach(function (cat) {{
        var el = document.getElementById('cookie-cat-' + cat);
        if (el && !el.disabled) el.checked = false;
      }});
      saveConsent(false);
    }});
  }}

  // ── Customize ────────────────────────────────────
  var btnCustomize = document.getElementById('cookie-customize');
  var catsDiv = document.getElementById('cookie-categories');
  if (btnCustomize && catsDiv) {{
    btnCustomize.addEventListener('click', function () {{
      catsDiv.classList.toggle('visible');
    }});
  }}

  // ── Save Preferences ─────────────────────────────
  var btnSave = document.getElementById('cookie-save');
  if (btnSave) {{
    btnSave.addEventListener('click', function () {{ saveConsent(false); }});
  }}

  // ── Init: show after 1s if no consent ────────────
  var existing = getCookie(COOKIE_NAME);
  if (!existing) {{
    setTimeout(showBanner, 1000);
  }}

}})();
"""

    def generate_wow_js(self) -> str:
        return r"""/*! WOW.js v1.3.0 | MIT License | github.com/matthieua/WOW */
(function (root, factory) {
  if (typeof define === 'function' && define.amd) {
    define(['undefined'], factory);
  } else if (typeof exports === 'object') {
    module.exports = factory(require('undefined'));
  } else {
    root.WOW = factory(root);
  }
}(this, function (window) {
  'use strict';

  function getComputedStyle(el, prop) {
    var cs = window.getComputedStyle(el);
    return cs ? cs.getPropertyValue(prop) : null;
  }

  function extend(dst, src) {
    if (dst && src) {
      for (var key in src) {
        if (src.hasOwnProperty(key)) { dst[key] = src[key]; }
      }
    }
    return dst;
  }

  function WOW(options) {
    this.defaults = {
      boxClass:        'wow',
      animateClass:    'animated',
      offset:          0,
      mobile:          true,
      live:            true,
      callback:        function (box) {},
      scrollContainer: null,
      resetAnimation:  true
    };
    this.options = extend({}, this.defaults);
    if (options) { extend(this.options, options); }
    this.scrolled   = true;
    this.scrollCallback = this._scrollCallback.bind(this);
    this.boxes      = [];
    this.all        = [];
    this.disabled   = false;
  }

  WOW.prototype.init = function () {
    this.element = (this.options.scrollContainer && document.querySelector(this.options.scrollContainer)) || window.document;
    this.disabled = (this.disabled || this.isDisabled());
    if (!this.disabled) {
      this.boxes = Array.prototype.slice.call(document.querySelectorAll('.' + this.options.boxClass));
      this.all   = this.boxes.slice(0);
      this.start();
    }
  };

  WOW.prototype.start = function () {
    var that = this;
    if (this.boxes.length) {
      if (document.readyState === 'complete') {
        this.setup();
      } else {
        window.addEventListener('load', function () { that.setup(); });
      }
    }
    if (this.options.live) {
      (new MutationObserver(function (mutations) {
        mutations.forEach(function (mutation) {
          Array.prototype.slice.call(mutation.addedNodes).forEach(function (node) {
            that.doSync(node);
          });
        });
      })).observe(document.body, { childList: true, subtree: true });
    }
  };

  WOW.prototype.stop = function () {
    this.stopped = true;
    var scrollEl = this.options.scrollContainer ? document.querySelector(this.options.scrollContainer) : window;
    if (scrollEl) { scrollEl.removeEventListener('scroll', this.scrollCallback); }
  };

  WOW.prototype.setup = function () {
    var scrollEl = this.options.scrollContainer ? document.querySelector(this.options.scrollContainer) : window;
    this.applyStyle(document.body, 'transition', 'none 0s ease 0s');
    this.boxes.forEach(function (box) {
      var style = window.getComputedStyle(box);
      if (style && style.visibility === 'visible') { return; }
      box.setAttribute('data-wow-init', 'true');
    });
    scrollEl.addEventListener('scroll', this.scrollCallback, false);
    window.addEventListener('resize', this.scrollCallback, false);
    this._scrollCallback();
  };

  WOW.prototype.doSync = function (element) {
    var that = this;
    if (element && element.nodeType === 1) {
      if (element.classList && element.classList.contains(this.options.boxClass)) {
        this.boxes.push(element);
        this.all.push(element);
        this._scrollCallback();
      }
      element.querySelectorAll('.' + this.options.boxClass).forEach(function (el) {
        that.boxes.push(el);
        that.all.push(el);
      });
      this._scrollCallback();
    }
  };

  WOW.prototype.show = function (box) {
    this.applyStyle(box, 'visibility', 'visible');
    box.classList.add(this.options.animateClass);
    if (this.options.callback) { this.options.callback(box); }
  };

  WOW.prototype.applyStyle = function (el, prop, val) {
    try { el.style[prop] = val; } catch (e) {}
  };

  WOW.prototype.isDisabled = function () {
    var mobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
    return (!this.options.mobile && mobile);
  };

  WOW.prototype._scrollCallback = function () {
    var that = this;
    if (this.scrolled) {
      this.scrolled = false;
      requestAnimationFrame(function () {
        that.boxes = that.boxes.filter(function (box) {
          if (that.isVisible(box)) {
            that.show(box);
            return false;
          }
          return true;
        });
        that.scrolled = true;
      });
    } else {
      this.scrolled = true;
    }
  };

  WOW.prototype.offsetTop = function (element) {
    var top = 0;
    while (element) {
      top += element.offsetTop || 0;
      element = element.offsetParent;
    }
    return top;
  };

  WOW.prototype.isVisible = function (box) {
    var offset    = parseInt(box.getAttribute('data-wow-offset') || this.options.offset) || 0;
    var viewTop   = (this.options.scrollContainer ? document.querySelector(this.options.scrollContainer).scrollTop : window.pageYOffset);
    var viewBottom = viewTop + (window.innerHeight || document.documentElement.clientHeight) - offset;
    var top    = this.offsetTop(box);
    var bottom = top + box.offsetHeight;
    return top <= viewBottom && bottom >= viewTop;
  };

  return WOW;
}));
"""
