// Domeneflyt: LiveSearch (AI-boks med resultater som faller ut av boksen,
// tier 1 øyeblikkelig + tier 2 async-bekreftelse), diskret hosting-upsell
// (GH30–32 / WP20–22) når et domene legges i vognen, bulk-sjekk og TLD-tabell.
import React, { useState, useEffect, useMemo } from 'react';

const NS = window.STWORDER;

function useDebounced(value, ms) {
  const [v, setV] = useState(value);
  useEffect(() => {
    const id = setTimeout(() => setV(value), ms);
    return () => clearTimeout(id);
  }, [value, ms]);
  return v;
}

// Async tier 1-søk. Forrige resultat står til nytt svar er inne (ingen
// flimring), og svar som er utdatert når de kommer kastes – nettverket
// garanterer ikke rekkefølge.
function useSearch(q) {
  const [results, setResults] = useState(null);
  useEffect(() => {
    let stale = false;
    NS.api.search(q).then((r) => {
      if (!stale) setResults(r);
    });
    return () => { stale = true; };
  }, [q]);
  return results;
}

// Bekreftelses-cache (tier 2) deles mellom komponenter i økten.
const confirmCache = {};
function useConfirmations(results) {
  const [, bump] = useState(0);
  useEffect(() => {
    if (!results) return;
    results.filter((r) => r.status === 'free' && !confirmCache[r.domain]).forEach((r) => {
      confirmCache[r.domain] = { state: 'checking' };
      NS.api.confirm(r.domain).then((v) => {
        confirmCache[r.domain] = Object.assign({ state: 'done' }, v);
        bump((n) => n + 1);
      });
    });
  }, [results]);
  return confirmCache;
}

function statusFor(r, conf) {
  if (r.status === 'taken') return { kind: 'taken' };
  // 'unknown' = backenden har ikke sonen lastet (eller .no-miss): tentativt
  // "Ledig?", ingen tier 2-confirm. Itereres senere (EPP-bekreftelse).
  if (r.status === 'unknown') return { kind: 'maybe', price: r.price, premium: r.premium };
  const c = conf[r.domain];
  if (!c || c.state === 'checking') return { kind: 'checking' };
  return c.available
    ? { kind: 'free', price: c.price, premium: c.premium }
    : { kind: 'taken' };
}

function ResultRow({ r, conf, big }) {
  const { useI18n, useCart, nok, Btn, Spinner, CheckIcon } = NS.ui;
  const { t } = useI18n();
  useCart(); // re-render når vognen endres (inCart-status)
  const st = statusFor(r, conf);
  const inCart = NS.store.hasDomain(r.domain);

  function add() {
    NS.store.add({
      type: 'domain',
      domain: r.domain,
      years: 1,
      pricePerYear: st.price !== undefined ? st.price : r.price,
      premium: !!st.premium,
    });
    NS.bus.emit('domain:added', r.domain);
  }

  return (
    <div className={'flex items-center justify-between gap-3 px-4 transition-colors hover:bg-gray-50 ' + (big ? 'py-4' : 'py-3')}>
      <div className="min-w-0">
        <span
          className={
            'font-semibold ' +
            (big ? 'text-xl ' : 'text-base ') +
            (st.kind === 'taken' ? 'text-gray-400/70' : 'text-navy')
          }
        >
          {r.domain.slice(0, r.domain.indexOf('.'))}
          <span className={st.kind === 'taken' ? '' : 'text-brand'}>
            {r.domain.slice(r.domain.indexOf('.'))}
          </span>
        </span>
        {st.kind === 'free' && st.premium ? (
          <span className="ml-2 rounded-full bg-orange-100 px-2 py-0.5 font-mono text-[10px] uppercase tracking-wider text-orange-700">
            {t('common.premium')}
          </span>
        ) : null}
      </div>
      <div className="flex shrink-0 items-center">
        {st.kind === 'taken' ? (
          <span className="text-sm text-gray-400">{t('common.taken')}</span>
        ) : st.kind === 'checking' ? (
          <Spinner />
        ) : inCart ? (
          <span className="flex items-center gap-1.5 rounded-full bg-emerald-50 px-3.5 py-1.5 text-sm font-medium text-emerald-700">
            <CheckIcon className="h-4 w-4" /> {t('common.inCart')}
          </span>
        ) : (
          <button
            onClick={add}
            className={
              'cursor-pointer rounded-full px-3.5 py-1.5 text-sm font-semibold ring-1 transition-all ' +
              (st.kind === 'maybe'
                ? 'text-amber-700 ring-amber-500/40 hover:bg-amber-500 hover:text-white hover:ring-amber-500'
                : 'text-brand ring-emerald-600/30 hover:bg-brand hover:text-white hover:ring-brand')
            }
          >
            {st.kind === 'maybe' ? (
              <span className="mr-1.5 font-mono text-[11px] uppercase tracking-wider">{t('common.maybeAvailable')}</span>
            ) : null}
            {nok(st.price)}{t('common.perYear')} <span aria-hidden className="ml-0.5">+</span>
          </button>
        )}
      </div>
    </div>
  );
}

/* Hosting-upsell som dialog: dukker opp når et domene legges i vognen.
   WordPress er standardfane; full plan-info så valget blir informert.
   Rendres på App-nivå (lytter selv på 'domain:added'). */
function UpsellDialog() {
  const { useI18n, nok, Btn, CheckIcon, MonoLabel, localName } = NS.ui;
  const { t, lang } = useI18n();
  const [domain, setDomain] = useState(null);
  const [group, setGroup] = useState('wordpress');
  const [addedId, setAddedId] = useState(null);

  useEffect(() => {
    const open = (d) => {
      setDomain(d);
      setGroup('wordpress');
      setAddedId(null);
    };
    const off1 = NS.bus.on('domain:added', open);
    const off2 = NS.bus.on('upsell:open', open); // fra "Legg til webhotell" i vognen
    return () => { off1(); off2(); };
  }, []);

  // Lukk uten hosting-kjøp → nudge for domenet som nettopp ble lagt til.
  function dismiss() {
    setDomain((d) => {
      if (d) NS.bus.emit('checkout:nudge', { name: d });
      return null;
    });
  }

  useEffect(() => {
    if (!domain) return;
    const onKey = (e) => { if (e.key === 'Escape') dismiss(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [domain]);

  if (!domain) return null;

  const tabs = [
    NS.data.productGroups.find((g) => g.id === 'wordpress'),
    NS.data.productGroups.find((g) => g.id === 'webhotell'),
  ];
  const products = NS.data.products.filter((p) => p.group === group);

  function add(p) {
    NS.store.add({
      type: 'product',
      productId: p.id,
      name: p.name,
      group: p.group,
      cycle: 'monthly',
      monthly: p.monthly,
      domain: { mode: 'cart', name: domain },
    });
    setAddedId(p.id);
    setTimeout(() => {
      setDomain(null);
      NS.bus.emit('checkout:nudge', { name: p.name });
    }, 900);
  }

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center p-4">
      <div className="absolute inset-0 bg-navy/30 backdrop-blur-sm" onClick={dismiss} />
      <div className="fade-up relative max-h-[90vh] w-full max-w-3xl overflow-y-auto rounded-2xl bg-white/95 p-6 shadow-[0_24px_80px_-20px_rgba(16,185,129,0.4)] ring-1 ring-gray-200 backdrop-blur-md">
        <div className="flex items-start justify-between gap-4">
          <div>
            <h2 className="text-xl font-bold text-navy">{t('domains.upsell', { domain })}</h2>
            <p className="mt-1 text-sm text-gray-500">{t('upsell.hint')}</p>
          </div>
          <button
            onClick={dismiss}
            className="cursor-pointer rounded-md p-1 text-gray-400 hover:text-navy"
            aria-label="Close"
          >
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" className="h-6 w-6">
              <path strokeLinecap="round" strokeLinejoin="round" d="M6 18 18 6M6 6l12 12" />
            </svg>
          </button>
        </div>

        <div className="mt-4 inline-flex gap-1 rounded-full bg-gray-100 p-1 ring-1 ring-gray-200">
          {tabs.map((g) => (
            <button
              key={g.id}
              onClick={() => setGroup(g.id)}
              className={
                'cursor-pointer rounded-full px-4 py-1.5 text-sm font-semibold transition-colors ' +
                (group === g.id ? 'bg-white text-navy shadow-sm' : 'text-gray-500 hover:text-navy')
              }
            >
              {t(g.labelKey)}
            </button>
          ))}
        </div>

        <div className="mt-5 grid gap-3 sm:grid-cols-3">
          {products.map((p) => {
            const hot = !!p.badge;
            return (
              <div
                key={p.id}
                className={
                  'relative flex flex-col rounded-xl p-4 pt-5 ring-1 transition-all ' +
                  (addedId === p.id || hot
                    ? 'bg-emerald-50/70 ring-emerald-500/40 shadow-[0_12px_40px_-14px_rgba(16,185,129,0.45)]'
                    : 'bg-white ring-gray-200 hover:ring-gray-300')
                }
              >
                {p.badge ? (
                  <div className="absolute -top-2.5 left-4 rounded-full bg-brand px-2.5 py-0.5">
                    <MonoLabel className="text-[9px] text-white">{localName(p.badge, lang)}</MonoLabel>
                  </div>
                ) : null}
                <div className="text-lg font-bold text-navy">{p.name}</div>
                <MonoLabel className="mt-0.5 text-[9px] text-gray-400">{p.sub}</MonoLabel>
                <div className="mt-2 flex items-baseline gap-1">
                  <span className="text-2xl font-bold tracking-tight text-navy">{nok(p.monthly)}</span>
                  <span className="text-sm text-gray-500">{t('common.perMonth')}</span>
                </div>
                <ul className="mt-3 flex-1 space-y-1.5">
                  {(p.features[lang] || p.features.no).map((f, i) => (
                    <li key={i} className="flex items-start gap-1.5 text-xs text-gray-700">
                      <CheckIcon className="mt-px h-3.5 w-3.5 shrink-0 text-brand" />
                      {f}
                    </li>
                  ))}
                </ul>
                <button
                  onClick={() => add(p)}
                  disabled={!!addedId}
                  className={
                    'mt-4 w-full cursor-pointer rounded-full px-3 py-2 text-sm font-semibold transition-all disabled:cursor-default ' +
                    (addedId === p.id
                      ? 'bg-emerald-100 text-emerald-700'
                      : hot
                      ? 'bg-brand text-white hover:bg-emerald-700'
                      : 'text-brand ring-1 ring-emerald-600/30 hover:bg-brand hover:text-white hover:ring-brand')
                  }
                >
                  {addedId === p.id ? t('upsell.added') : t('common.select')}
                </button>
              </div>
            );
          })}
        </div>

        <div className="mt-5 text-center">
          <button
            onClick={dismiss}
            className="cursor-pointer text-sm text-gray-500 underline-offset-2 transition-colors hover:text-navy hover:underline"
          >
            {t('upsell.skip')}
          </button>
        </div>
      </div>
    </div>
  );
}

/* Hovedsøket – brukes både på forsiden (hero) og på domenesiden. */
function LiveSearch({ initialQuery }) {
  const { useI18n, AISearchBox, MailIcon } = NS.ui;
  const { t, lang } = useI18n();
  const [q, setQ] = useState(initialQuery || '');
  const dq = useDebounced(q, 200);
  const results = useSearch(dq);
  const conf = useConfirmations(results ? results.results : null);

  const chips = ['minbedrift', 'kaffebar-oslo', 'fjellhytte'];

  return (
    <AISearchBox
      value={q}
      onChange={setQ}
      placeholder={t('home.searchPlaceholder')}
      chips={chips}
      onChip={setQ}
      label={t('common.search')}
    >
      {results ? (
        <div>
          {/* Konverteringsdetalj: vis den faktiske adressen kunden får. */}
          <div className="flex items-center gap-2 border-b border-emerald-100 bg-emerald-50 px-4 py-2.5 text-sm font-medium text-emerald-800">
            <MailIcon className="h-4 w-4 shrink-0" />
            <span className="min-w-0 truncate">
              {t('domains.emailStrip1')}{' '}
              <span className="font-bold">
                {(lang === 'no' ? 'post@' : 'you@') + results.results[0].domain}
              </span>{' '}
              {t('domains.emailStrip2')}
            </span>
          </div>
          <div className="divide-y divide-gray-100">
            {results.results.map((r, i) => (
              <ResultRow key={r.domain} r={r} conf={conf} big={i === 0} />
            ))}
          </div>
        </div>
      ) : null}
    </AISearchBox>
  );
}

function BulkChecker() {
  const { useI18n, useCart, nok, Btn, Spinner, CheckIcon } = NS.ui;
  const { t } = useI18n();
  useCart();
  const [text, setText] = useState('');
  const [busy, setBusy] = useState(false);
  const [rows, setRows] = useState(null);

  async function check() {
    setBusy(true);
    setRows(await NS.api.bulkCheck(text));
    setBusy(false);
  }

  function addAll() {
    rows.filter((r) => r.available && !NS.store.hasDomain(r.domain)).forEach((r) => {
      NS.store.add({ type: 'domain', domain: r.domain, years: 1, pricePerYear: r.price, premium: !!r.premium });
    });
    NS.bus.emit('cart:open');
  }

  const availableCount = rows ? rows.filter((r) => r.available).length : 0;

  return (
    <div>
      <p className="mb-2 text-sm text-gray-600">{t('domains.bulkHint')}</p>
      <textarea
        value={text}
        onChange={(e) => setText(e.target.value)}
        rows={6}
        placeholder={'mittdomene.no\nmittdomene.com\nminbedrift.no'}
        className="w-full rounded-xl border border-gray-300 bg-white p-3 font-mono text-sm text-navy outline-none focus:border-brand"
      />
      <div className="mt-2 flex gap-2">
        <Btn variant="brand" onClick={check} disabled={busy || !text.trim()}>
          {busy ? <Spinner className="border-white/40 border-t-white" /> : null} {t('domains.bulkCheck')}
        </Btn>
        {rows && availableCount > 0 ? (
          <Btn variant="navy" onClick={addAll}>
            {t('domains.addAvailable')} ({availableCount})
          </Btn>
        ) : null}
      </div>
      {rows ? (
        <div className="mt-4 divide-y divide-gray-100 rounded-xl border border-gray-200 bg-white shadow-sm">
          {rows.map((r) => (
            <div key={r.domain} className="flex items-center justify-between px-4 py-2.5">
              <span className="text-sm font-semibold text-navy">{r.domain}</span>
              {r.available ? (
                <span className="flex items-center gap-2 text-sm">
                  <span className="flex items-center gap-1 font-medium text-brand">
                    <CheckIcon className="h-4 w-4" /> {t('common.available')}
                  </span>
                  <span className="font-bold text-navy">{nok(r.price)}{t('common.perYear')}</span>
                </span>
              ) : (
                <span className="text-sm font-medium text-gray-400">{t('common.taken')}</span>
              )}
            </div>
          ))}
        </div>
      ) : null}
    </div>
  );
}

function TldTable() {
  const { useI18n, nok } = NS.ui;
  const { t } = useI18n();
  const [filter, setFilter] = useState('');
  const rows = NS.data.tlds.filter((r) => ('.' + r.tld).includes(filter.toLowerCase()));
  return (
    <div className="overflow-hidden rounded-2xl border border-gray-200 bg-white shadow-sm">
      <div className="flex items-center justify-between gap-4 border-b border-gray-100 p-4">
        <h3 className="text-lg font-bold text-navy">{t('domains.pricesTitle')}</h3>
        <input
          value={filter}
          onChange={(e) => setFilter(e.target.value)}
          placeholder={t('domains.filter')}
          className="w-40 rounded-lg border border-gray-300 px-3 py-1.5 text-sm outline-none focus:border-brand"
        />
      </div>
      <table className="w-full text-sm">
        <thead>
          <tr className="border-b border-gray-100 text-left text-xs text-gray-500">
            <th className="px-4 py-2 font-medium">{t('domains.colDomain')}</th>
            <th className="px-4 py-2 font-medium">{t('domains.colRegister')}</th>
            <th className="px-4 py-2 font-medium">{t('domains.colTransfer')}</th>
            <th className="px-4 py-2 font-medium">{t('domains.colRenew')}</th>
          </tr>
        </thead>
        <tbody className="divide-y divide-gray-50">
          {rows.map((r) => (
            <tr key={r.tld}>
              <td className="px-4 py-2.5 font-bold text-navy">.{r.tld}</td>
              <td className="px-4 py-2.5">{nok(r.register)}{t('common.perYear')}</td>
              <td className="px-4 py-2.5">
                {r.transfer === 0
                  ? <span className="font-semibold text-brand">{nok(0)}</span>
                  : nok(r.transfer) + t('common.perYear')}
              </td>
              <td className="px-4 py-2.5">{nok(r.renew)}{t('common.perYear')}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

// Gjenbrukbar enkelt-domene-velger for hosting-flyten ("registrer nytt").
function DomainPicker({ onPick, picked }) {
  const { useI18n, nok, Btn, Spinner, CheckIcon } = NS.ui;
  const { t } = useI18n();
  const [q, setQ] = useState('');
  const dq = useDebounced(q, 250);
  const results = useSearch(dq);
  const conf = useConfirmations(results ? results.results : null);

  if (picked) {
    return (
      <div className="flex items-center justify-between rounded-lg border border-brand bg-emerald-50 px-3 py-2.5">
        <span className="flex items-center gap-2 text-sm font-semibold text-navy">
          <CheckIcon className="h-4 w-4 text-brand" /> {picked.name}
          <span className="font-normal text-gray-500">{nok(picked.price)}{t('common.perYear')}</span>
        </span>
        <button onClick={() => onPick(null)} className="cursor-pointer text-xs text-gray-500 hover:text-navy">
          {t('checkout.change')}
        </button>
      </div>
    );
  }

  return (
    <div>
      <input
        value={q}
        onChange={(e) => setQ(e.target.value)}
        placeholder={t('domains.searchPlaceholder')}
        autoCapitalize="none"
        spellCheck="false"
        className="w-full rounded-lg border border-gray-300 px-3 py-2.5 text-sm text-navy outline-none focus:border-brand"
      />
      {results ? (
        <div className="mt-2 max-h-56 divide-y divide-gray-50 overflow-y-auto rounded-lg border border-gray-200 bg-white">
          {results.results.map((r) => {
            const st = statusFor(r, conf);
            return (
              <div key={r.domain} className="flex items-center justify-between px-3 py-2">
                <span className="text-sm font-semibold text-navy">{r.domain}</span>
                {st.kind === 'taken' ? (
                  <span className="text-xs text-gray-400">{t('common.taken')}</span>
                ) : st.kind === 'checking' ? (
                  <Spinner />
                ) : (
                  <span className="flex items-center gap-2">
                    <span className="text-xs font-bold text-navy">{nok(st.price)}{t('common.perYear')}</span>
                    <Btn
                      variant="brand"
                      className="px-2.5 py-1 text-xs"
                      onClick={() => onPick({ name: r.domain, price: st.price })}
                    >
                      {t('common.select')}
                    </Btn>
                  </span>
                )}
              </div>
            );
          })}
        </div>
      ) : null}
    </div>
  );
}

function DomainsFlow() {
  const { useI18n, PageHero, SectionTitle } = NS.ui;
  const { t } = useI18n();
  const [showBulk, setShowBulk] = useState(false);
  const initialQuery = useMemo(() => {
    const v = sessionStorage.getItem('stworder.q') || '';
    sessionStorage.removeItem('stworder.q');
    return v;
  }, []);

  return (
    <div>
      <PageHero title={t('domains.title')} sub={t('domains.subtitle')}>
        <div className="max-w-2xl">
          <LiveSearch initialQuery={initialQuery} />
        </div>
      </PageHero>

      <div className="mx-auto max-w-6xl px-4 py-12">
        <section className="mb-12">
          <button
            onClick={() => setShowBulk((v) => !v)}
            className="cursor-pointer text-sm font-semibold text-brand hover:text-emerald-700"
          >
            {showBulk ? '–' : '+'} {t('domains.bulkToggle')}
          </button>
          {showBulk ? (
            <div className="fade-up mt-4 rounded-2xl border border-gray-200 bg-white p-5 shadow-sm">
              <BulkChecker />
            </div>
          ) : null}
        </section>

        <section>
          <SectionTitle title={t('domains.pricesTitle')} />
          <TldTable />
        </section>
      </div>
    </div>
  );
}

NS.flows = NS.flows || {};
NS.flows.Domains = DomainsFlow;
NS.flows.DomainPicker = DomainPicker;
NS.flows.LiveSearch = LiveSearch;
NS.flows.UpsellDialog = UpsellDialog;
