// Nordbank — shared components.
// Header, Footer, Logo, LangSwitcher, ProgressBar, BankIdButton, CurrencyInput, RouterLink.

// -----------------------------------------------------------------------------
// Tiny hash router. Avoids react-router dependency in the prototype.
// -----------------------------------------------------------------------------

function _readHash() {
  if (typeof location === 'undefined') return '/';
  let h = (location.hash || '').replace(/^#/, '');
  if (!h.startsWith('/')) h = '/' + h;
  return h || '/';
}

const _routeListeners = new Set();
let _currentRoute = _readHash();
if (typeof window !== 'undefined') {
  window.addEventListener('hashchange', () => {
    _currentRoute = _readHash();
    _routeListeners.forEach(fn => fn());
  });
}

function navigate(to) {
  if (!to.startsWith('/')) to = '/' + to;
  if (location.hash !== '#' + to) {
    location.hash = '#' + to;
  } else {
    // Force scroll-to-top anyway.
    window.scrollTo({ top: 0, behavior: 'instant' });
  }
}

function useRoute() {
  const [, force] = React.useReducer(x => x + 1, 0);
  React.useEffect(() => {
    _routeListeners.add(force);
    return () => { _routeListeners.delete(force); };
  }, []);
  return _currentRoute;
}

// Scroll to top on route change.
function useScrollTop() {
  const route = useRoute();
  React.useEffect(() => {
    try { window.scrollTo({ top: 0, behavior: 'instant' }); } catch (e) { window.scrollTo(0,0); }
  }, [route]);
}

function RouterLink({ to, children, className, onClick, ariaCurrent, ...rest }) {
  const route = useRoute();
  const active = route === to;
  return (
    <a
      href={'#' + to}
      className={className}
      aria-current={ariaCurrent || (active ? 'page' : undefined)}
      onClick={e => {
        if (onClick) onClick(e);
        // Hashchange fires naturally; no preventDefault needed.
      }}
      {...rest}
    >
      {children}
    </a>
  );
}

// -----------------------------------------------------------------------------
// Logo
// -----------------------------------------------------------------------------

function NordbankLogo({ variant = 'navy', className = '', wordmark = true }) {
  const fg = variant === 'light' ? '#FFFFFF' : '#0B2545';
  const ac = variant === 'light' ? '#5BD2CE' : '#13B5B1';
  return (
    <span className={'nb-logo inline-flex items-center gap-2.5 ' + className} aria-label="Nordbank">
      <svg width="28" height="28" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
        <rect x="0.5" y="0.5" width="31" height="31" rx="8" stroke={fg} strokeOpacity="0.18" />
        <g className="nb-peak">
          <path d="M5 24 L12 12 L17 19 L22 11 L27 24 Z" fill={fg}/>
          <circle cx="22" cy="11" r="2.2" fill={ac}/>
        </g>
      </svg>
      {wordmark && (
        <span style={{ color: fg }} className="text-[17px] font-semibold tracking-tight">
          Nordbank
        </span>
      )}
    </span>
  );
}

// -----------------------------------------------------------------------------
// Language switcher — dropdown with flag + ISO code
// -----------------------------------------------------------------------------

function LangSwitcher({ variant = 'navy' }) {
  const lang = useLang();
  const [open, setOpen] = React.useState(false);
  const ref = React.useRef(null);
  React.useEffect(() => {
    if (!open) return;
    const onDoc = e => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', onDoc);
    return () => document.removeEventListener('mousedown', onDoc);
  }, [open]);

  const isLight = variant === 'light';
  const trigger = isLight
    ? 'bg-white/10 hover:bg-white/20 text-white border-white/20'
    : 'bg-white hover:bg-navy-50 text-navy-900 border-navy-100';

  const meta = LANG_META[lang] || LANG_META.en;
  return (
    <div className="relative" ref={ref}>
      <button
        type="button"
        className={'flex items-center gap-2 rounded-full border px-3 py-1.5 text-sm font-medium tnum transition-colors ' + trigger}
        onClick={() => setOpen(o => !o)}
        aria-haspopup="listbox"
        aria-expanded={open}
        aria-label="Change language"
      >
        <span className="text-base leading-none" aria-hidden="true">{meta.flag}</span>
        <span>{meta.code}</span>
        <svg width="10" height="10" viewBox="0 0 10 10" aria-hidden="true"><path d="M2 4 L5 7 L8 4" stroke="currentColor" strokeWidth="1.5" fill="none" strokeLinecap="round" strokeLinejoin="round"/></svg>
      </button>
      {open && (
        <ul role="listbox" className="absolute right-0 mt-2 w-44 rounded-xl border hairline bg-white shadow-card py-1 z-50">
          {Object.entries(LANG_META).map(([code, m]) => (
            <li key={code}>
              <button
                type="button"
                role="option"
                aria-selected={code === lang}
                onClick={() => { setLang(code); setOpen(false); }}
                className={'flex w-full items-center gap-3 px-3 py-2 text-sm text-left hover:bg-surface ' +
                  (code === lang ? 'text-navy-900 font-semibold' : 'text-navy-700')}
              >
                <span className="text-base" aria-hidden="true">{m.flag}</span>
                <span className="flex-1">{m.label}</span>
                <span className="text-xs text-navy-300 tnum">{m.code}</span>
                {code === lang && (
                  <svg width="14" height="14" viewBox="0 0 14 14" aria-hidden="true"><path d="M3 7.5 L6 10.5 L11.5 4" stroke="#13B5B1" strokeWidth="2" fill="none" strokeLinecap="round" strokeLinejoin="round"/></svg>
                )}
              </button>
            </li>
          ))}
        </ul>
      )}
    </div>
  );
}

// -----------------------------------------------------------------------------
// Header / Footer / Layout
// -----------------------------------------------------------------------------

function Header({ banner }) {
  const route = useRoute();
  const user = useCurrentUser();
  const [open, setOpen] = React.useState(false);
  const isApply = route.startsWith('/apply');

  const navLinks = [
    { to: '/loans', label: t('nav.loans') },
    { to: '/savings', label: t('nav.savings'), disabled: true },
    { to: '/cards', label: t('nav.cards'), disabled: true },
  ];

  return (
    <>
      {banner && (
        <div className="nb-slidein bg-success/10 border-b border-success/20 text-success px-4 py-2 text-sm text-center">
          {banner}
        </div>
      )}
      <header className="sticky top-0 z-40 bg-white/85 backdrop-blur border-b hairline">
        <div className="max-w-6xl mx-auto px-4 md:px-6 h-16 flex items-center gap-6">
          <RouterLink to="/" className="shrink-0">
            <NordbankLogo />
          </RouterLink>
          <nav className="hidden md:flex items-center gap-1 flex-1" aria-label="Primary">
            {navLinks.map(l => l.disabled ? (
              <span key={l.to} className="px-3 py-2 text-sm text-navy-200 cursor-not-allowed select-none">{l.label}</span>
            ) : (
              <RouterLink
                key={l.to}
                to={l.to}
                className={'px-3 py-2 text-sm font-medium rounded-lg transition-colors ' +
                  (route === l.to || (l.to !== '/' && route.startsWith(l.to))
                    ? 'text-navy-900 bg-navy-50'
                    : 'text-navy-700 hover:text-navy-900 hover:bg-navy-50')}
              >
                {l.label}
              </RouterLink>
            ))}
          </nav>
          <div className="hidden md:flex items-center gap-3 ml-auto">
            {user ? (
              <>
                <RouterLink to="/portal" className="text-sm font-medium text-navy-700 hover:text-navy-900 px-3 py-2 rounded-lg hover:bg-navy-50">
                  {t('nav.portal')}
                </RouterLink>
                <button
                  type="button"
                  onClick={() => { logoutUser(); navigate('/'); }}
                  className="text-sm font-medium text-navy-700 hover:text-navy-900 px-3 py-2 rounded-lg hover:bg-navy-50"
                >
                  {t('portal.signOut')}
                </button>
              </>
            ) : (
              <>
                <RouterLink to="/login" className="text-sm font-medium text-navy-700 hover:text-navy-900 px-3 py-2 rounded-lg hover:bg-navy-50">
                  {t('nav.login')}
                </RouterLink>
                {!isApply && (
                  <RouterLink to="/apply" className="text-sm font-semibold bg-navy-900 hover:bg-navy-700 text-white px-4 py-2 rounded-full transition-colors">
                    {t('nav.apply')}
                  </RouterLink>
                )}
              </>
            )}
            <LangSwitcher />
          </div>

          {/* Mobile */}
          <div className="md:hidden ml-auto flex items-center gap-2">
            <LangSwitcher />
            <button
              type="button"
              className="p-2 rounded-lg text-navy-900 hover:bg-navy-50"
              onClick={() => setOpen(o => !o)}
              aria-label="Toggle menu"
              aria-expanded={open}
            >
              {open ? (
                <svg width="22" height="22" viewBox="0 0 22 22"><path d="M5 5 L17 17 M17 5 L5 17" stroke="currentColor" strokeWidth="2" strokeLinecap="round"/></svg>
              ) : (
                <svg width="22" height="22" viewBox="0 0 22 22"><path d="M4 7 H18 M4 11 H18 M4 15 H18" stroke="currentColor" strokeWidth="2" strokeLinecap="round"/></svg>
              )}
            </button>
          </div>
        </div>
        {open && (
          <div className="md:hidden border-t hairline bg-white">
            <div className="max-w-6xl mx-auto px-4 py-2 flex flex-col">
              {navLinks.map(l => l.disabled ? (
                <span key={l.to} className="px-3 py-3 text-sm text-navy-200">{l.label}</span>
              ) : (
                <RouterLink
                  key={l.to}
                  to={l.to}
                  onClick={() => setOpen(false)}
                  className="px-3 py-3 text-sm font-medium text-navy-800 hover:bg-navy-50 rounded-lg"
                >
                  {l.label}
                </RouterLink>
              ))}
              <RouterLink to={user ? '/portal' : '/login'} onClick={() => setOpen(false)} className="px-3 py-3 text-sm font-medium text-navy-800 hover:bg-navy-50 rounded-lg">
                {user ? t('nav.portal') : t('nav.login')}
              </RouterLink>
              {user && (
                <button type="button" onClick={() => { setOpen(false); logoutUser(); navigate('/'); }} className="text-left px-3 py-3 text-sm font-medium text-navy-800 hover:bg-navy-50 rounded-lg">
                  {t('portal.signOut')}
                </button>
              )}
              {!isApply && !user && (
                <RouterLink to="/apply" onClick={() => setOpen(false)} className="mt-2 text-center text-sm font-semibold bg-navy-900 text-white px-4 py-3 rounded-full">
                  {t('nav.apply')}
                </RouterLink>
              )}
            </div>
          </div>
        )}
      </header>
    </>
  );
}

function Footer() {
  return (
    <footer className="mt-24 border-t hairline bg-white">
      <div className="max-w-6xl mx-auto px-4 md:px-6 py-12 grid grid-cols-2 md:grid-cols-4 gap-8">
        <div className="col-span-2 md:col-span-1">
          <NordbankLogo />
          <p className="text-sm text-navy-500 mt-3 max-w-xs">{t('footer.tagline')}</p>
        </div>
        <FooterCol title={t('footer.section.products')} links={[
          [t('footer.link.consumer'), '/loans/consumer'],
          [t('footer.link.mortgage'), '/loans'],
          [t('footer.link.car'), '/loans'],
        ]} />
        <FooterCol title={t('footer.section.company')} links={[
          [t('footer.link.about'), '/about'],
          [t('footer.link.press'), '/about'],
          [t('footer.link.careers'), '/about'],
        ]} />
        <FooterCol title={t('footer.section.help')} links={[
          [t('footer.link.help'), '/about'],
          [t('footer.link.contact'), '/about'],
          [t('footer.link.complaints'), '/about'],
        ]} />
      </div>
      <div className="border-t hairline">
        <div className="max-w-6xl mx-auto px-4 md:px-6 py-6 flex flex-wrap items-center gap-x-6 gap-y-3 text-xs text-navy-500">
          <RegBadge label="BankID" />
          <RegBadge label="GDPR" />
          <RegBadge label="Finanstilsynet" />
          <p className="flex-1 min-w-0 text-navy-500/90 leading-relaxed">
            {t('footer.regulated')}
          </p>
        </div>
      </div>
    </footer>
  );
}

function FooterCol({ title, links }) {
  return (
    <div>
      <h3 className="text-xs font-semibold tracking-wider text-navy-900 uppercase">{title}</h3>
      <ul className="mt-3 space-y-2">
        {links.map(([label, to], i) => (
          <li key={i}><RouterLink to={to} className="text-sm text-navy-500 hover:text-navy-900">{label}</RouterLink></li>
        ))}
      </ul>
    </div>
  );
}

function RegBadge({ label }) {
  return (
    <span className="inline-flex items-center gap-1.5 px-2 py-1 rounded-md bg-navy-50 text-navy-700 text-[11px] font-semibold tracking-wide uppercase">
      <svg width="10" height="10" viewBox="0 0 10 10" aria-hidden="true"><path d="M5 1 L8.5 2.5 V5.2 C8.5 7 6.8 8.7 5 9.3 C3.2 8.7 1.5 7 1.5 5.2 V2.5 Z" fill="none" stroke="currentColor" strokeWidth="1.2"/></svg>
      {label}
    </span>
  );
}

function Layout({ children, banner }) {
  useScrollTop();
  return (
    <div className="min-h-screen flex flex-col">
      <Header banner={banner} />
      <main className="flex-1">{children}</main>
      <Footer />
    </div>
  );
}

// -----------------------------------------------------------------------------
// Progress bar (used by Apply wizard)
// -----------------------------------------------------------------------------

function ProgressBar({ step, total }) {
  const pct = (step / total) * 100;
  return (
    <div className="w-full">
      <div className="flex items-center justify-between text-xs font-medium text-navy-500">
        <span className="tnum">{t('apply.progress', { n: step })}</span>
        <span className="tnum">{Math.round(pct)}%</span>
      </div>
      <div className="mt-2 h-1.5 rounded-full bg-navy-50 overflow-hidden" role="progressbar" aria-valuenow={step} aria-valuemin={1} aria-valuemax={total}>
        <div className="h-full bg-navy-900 transition-[width] duration-500 ease-out" style={{ width: pct + '%' }} />
      </div>
    </div>
  );
}

// -----------------------------------------------------------------------------
// BankID button (orange-ish brand colour, but legally distinct mauve "bankid")
// -----------------------------------------------------------------------------

function BankIdButton({ label, busy, success, onClick, variant = 'primary', disabled }) {
  const isPrimary = variant === 'primary';
  const base = 'relative flex items-center justify-center gap-3 w-full rounded-xl font-semibold transition-all px-5 py-4 ';
  const styles = isPrimary
    ? 'bg-bankid hover:brightness-110 text-white shadow-card disabled:opacity-50'
    : 'border hairline bg-white hover:bg-surface text-navy-900 disabled:opacity-40';
  return (
    <button
      type="button"
      onClick={onClick}
      disabled={disabled || busy}
      className={base + styles}
      aria-busy={busy ? 'true' : undefined}
    >
      <BankIdMark variant={isPrimary ? 'light' : 'navy'} />
      <span>{label}</span>
      {busy && <Spinner color={isPrimary ? 'white' : 'navy'} />}
      {success && (
        <span className="text-success" aria-hidden="true">
          <svg width="18" height="18" viewBox="0 0 18 18"><path d="M3 9 L7 13 L15 5" stroke="currentColor" strokeWidth="2.5" fill="none" strokeLinecap="round" strokeLinejoin="round"/></svg>
        </span>
      )}
    </button>
  );
}

function BankIdMark({ variant = 'navy' }) {
  // Stylised "BID" mark, distinct from real BankID logo.
  const color = variant === 'light' ? '#fff' : '#0B2545';
  return (
    <svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true">
      <rect x="2" y="4" width="20" height="16" rx="3" fill={variant === 'light' ? 'rgba(255,255,255,0.18)' : '#13B5B1'} />
      <text x="12" y="15.5" textAnchor="middle" fontSize="9" fontWeight="700" fill={color} fontFamily="Inter, sans-serif" letterSpacing="0.5">BID</text>
    </svg>
  );
}

function Spinner({ color = 'white', size = 18 }) {
  const stroke = color === 'navy' ? '#0B2545' : color === 'teal' ? '#13B5B1' : '#FFFFFF';
  return (
    <svg className="nb-spin" width={size} height={size} viewBox="0 0 24 24" aria-hidden="true">
      <circle cx="12" cy="12" r="9" stroke={stroke} strokeOpacity="0.25" strokeWidth="3" fill="none" />
      <path d="M21 12 A9 9 0 0 0 12 3" stroke={stroke} strokeWidth="3" fill="none" strokeLinecap="round" />
    </svg>
  );
}

// -----------------------------------------------------------------------------
// Form primitives
// -----------------------------------------------------------------------------

function Field({ label, hint, error, required, htmlFor, children, optional }) {
  return (
    <label htmlFor={htmlFor} className="block">
      <div className="flex items-baseline justify-between">
        <span className="text-sm font-medium text-navy-900">
          {label}
          {required && <span className="text-danger ml-1" aria-hidden="true">*</span>}
          {optional && <span className="text-navy-300 ml-1 font-normal">· {t('common.optional')}</span>}
        </span>
        {hint && <Tooltip text={hint} />}
      </div>
      <div className="mt-1.5">{children}</div>
      {error && <p className="mt-1 text-xs text-danger">{error}</p>}
    </label>
  );
}

function TextInput({ id, value, onChange, placeholder, type = 'text', autoComplete, inputMode, ...rest }) {
  return (
    <input
      id={id}
      type={type}
      value={value}
      onChange={e => onChange(e.target.value)}
      placeholder={placeholder}
      autoComplete={autoComplete}
      inputMode={inputMode}
      className="w-full rounded-xl border hairline bg-white px-3.5 py-2.5 text-sm text-navy-900 placeholder-navy-200 shadow-inset focus:border-teal-500 focus:shadow-none transition-colors tnum"
      {...rest}
    />
  );
}

function SelectInput({ id, value, onChange, children, ariaLabel }) {
  return (
    <div className="relative">
      <select
        id={id}
        value={value}
        onChange={e => onChange(e.target.value)}
        aria-label={ariaLabel}
        className="w-full appearance-none rounded-xl border hairline bg-white px-3.5 py-2.5 pr-9 text-sm text-navy-900 shadow-inset focus:border-teal-500 transition-colors"
      >
        {children}
      </select>
      <svg className="pointer-events-none absolute right-3 top-1/2 -translate-y-1/2" width="12" height="12" viewBox="0 0 12 12" aria-hidden="true">
        <path d="M3 4.5 L6 7.5 L9 4.5" stroke="#0B2545" strokeWidth="1.5" fill="none" strokeLinecap="round" strokeLinejoin="round"/>
      </svg>
    </div>
  );
}

function CurrencyInput({ id, value, currency, lang, onChange, placeholder }) {
  // Display formatted number; on focus, allow raw editing.
  const [focused, setFocused] = React.useState(false);
  const [raw, setRaw] = React.useState(String(value || ''));
  React.useEffect(() => { if (!focused) setRaw(value ? String(value) : ''); }, [value, focused]);
  const symbol = (() => {
    try {
      const parts = new Intl.NumberFormat(localeFor(lang), { style: 'currency', currency }).formatToParts(0);
      return (parts.find(p => p.type === 'currency') || {}).value || currency;
    } catch (e) { return currency; }
  })();
  return (
    <div className="relative">
      <span className="absolute left-3.5 top-1/2 -translate-y-1/2 text-sm text-navy-300 pointer-events-none">{symbol}</span>
      <input
        id={id}
        inputMode="numeric"
        value={focused ? raw : (value ? formatNumber(value, lang) : '')}
        placeholder={placeholder}
        onFocus={() => { setFocused(true); }}
        onBlur={() => {
          setFocused(false);
          const n = parseInt(raw.replace(/[^\d]/g, ''), 10);
          onChange(isNaN(n) ? 0 : n);
        }}
        onChange={e => {
          const clean = e.target.value.replace(/[^\d]/g, '');
          setRaw(clean);
          const n = parseInt(clean, 10);
          if (!isNaN(n)) onChange(n);
          else if (clean === '') onChange(0);
        }}
        className="w-full rounded-xl border hairline bg-white pl-12 pr-3.5 py-2.5 text-sm text-navy-900 shadow-inset focus:border-teal-500 transition-colors tnum"
      />
    </div>
  );
}

function Tooltip({ text }) {
  const [open, setOpen] = React.useState(false);
  return (
    <span className="relative inline-flex">
      <button
        type="button"
        onMouseEnter={() => setOpen(true)}
        onMouseLeave={() => setOpen(false)}
        onFocus={() => setOpen(true)}
        onBlur={() => setOpen(false)}
        onClick={() => setOpen(o => !o)}
        className="text-navy-300 hover:text-navy-700 flex items-center"
        aria-label="More information"
      >
        <svg width="14" height="14" viewBox="0 0 14 14"><circle cx="7" cy="7" r="6" stroke="currentColor" strokeWidth="1.2" fill="none"/><path d="M7 6 V10" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/><circle cx="7" cy="4.2" r="0.8" fill="currentColor"/></svg>
      </button>
      {open && (
        <span role="tooltip" className="absolute right-0 top-6 z-30 w-64 rounded-lg bg-navy-900 text-white text-xs leading-relaxed p-3 shadow-card">
          {text}
        </span>
      )}
    </span>
  );
}

// -----------------------------------------------------------------------------
// Card primitives
// -----------------------------------------------------------------------------

function Card({ children, className = '', as: As = 'div', ...rest }) {
  return <As className={'rounded-2xl bg-white border hairline shadow-card ' + className} {...rest}>{children}</As>;
}

function SectionHeading({ eyebrow, title, lede, align = 'left' }) {
  return (
    <div className={align === 'center' ? 'text-center max-w-2xl mx-auto' : 'max-w-2xl'}>
      {eyebrow && <p className="text-xs font-semibold tracking-[0.18em] uppercase text-teal-700">{eyebrow}</p>}
      <h2 className={'mt-2 text-3xl md:text-4xl font-semibold tracking-tight text-navy-900 ' + (align === 'center' ? '' : '')} style={{ textWrap: 'balance' }}>
        {title}
      </h2>
      {lede && <p className="mt-3 text-base text-navy-500 leading-relaxed" style={{ textWrap: 'pretty' }}>{lede}</p>}
    </div>
  );
}

// -----------------------------------------------------------------------------
// Country selector pill group
// -----------------------------------------------------------------------------

function CountryPills({ value, onChange, lang }) {
  return (
    <div className="grid grid-cols-2 sm:grid-cols-4 gap-2" role="radiogroup" aria-label="Country">
      {['NO','DK','SE','FI'].map(c => {
        const meta = COUNTRY_META[c];
        const active = c === value;
        return (
          <button
            key={c}
            type="button"
            role="radio"
            aria-checked={active}
            onClick={() => onChange(c)}
            className={'flex items-center gap-2 px-3 py-2.5 rounded-xl border text-sm font-medium transition-all ' +
              (active
                ? 'bg-navy-900 text-white border-navy-900 shadow-card'
                : 'bg-white text-navy-700 hairline hover:bg-navy-50')}
          >
            <span className="text-base" aria-hidden="true">{meta.flag}</span>
            <span>{meta.label[lang] || meta.label.en}</span>
            <span className={'ml-auto text-[11px] tnum ' + (active ? 'text-white/70' : 'text-navy-300')}>
              {COUNTRY_CURRENCY[c]}
            </span>
          </button>
        );
      })}
    </div>
  );
}

Object.assign(window, {
  // router
  navigate, useRoute, RouterLink, useScrollTop,
  // shell
  Layout, Header, Footer, NordbankLogo, LangSwitcher,
  ProgressBar, BankIdButton, BankIdMark, Spinner,
  // forms
  Field, TextInput, SelectInput, CurrencyInput, Tooltip,
  // primitives
  Card, SectionHeading, CountryPills, RegBadge,
});
