import { h } from '../core/dom';

let host: HTMLElement | null = null;
function getHost(): HTMLElement {
  if (!host) {
    host = h('div.toast-host');
    document.body.appendChild(host);
  }
  return host;
}

let topHost: HTMLElement | null = null;
function getTopHost(): HTMLElement {
  if (!topHost) {
    topHost = h('div.toast-host.top');
    document.body.appendChild(topHost);
  }
  return topHost;
}

export type ToastType = 'info' | 'success' | 'error' | 'progress';
export type ToastPosition = 'bottom' | 'top';

export interface Toast {
  update(msg: string): void;
  progress(fraction: number): void;
  close(): void;
}

export function toast(
  message: string,
  opts: { type?: ToastType; duration?: number; position?: ToastPosition } = {},
): Toast {
  const type = opts.type ?? 'info';
  const msgEl = h('div.toast-msg', message);
  const bar = h('div.toast-bar');
  const el = h(
    `div.toast.toast-${type}`,
    { role: 'status' },
    type === 'progress' ? h('div.spinner spinner-ink') : dotFor(type),
    msgEl,
    type === 'progress' ? h('div.toast-progress-track', bar) : null,
  );
  (opts.position === 'top' ? getTopHost() : getHost()).appendChild(el);
  requestAnimationFrame(() => el.classList.add('in'));

  let closed = false;
  const close = () => {
    if (closed) return;
    closed = true;
    el.classList.remove('in');
    setTimeout(() => el.remove(), 260);
  };
  if (type !== 'progress') {
    const dur = opts.duration ?? 3600;
    setTimeout(close, dur);
  }
  return {
    update: (m: string) => { msgEl.textContent = m; },
    progress: (f: number) => { bar.style.width = `${Math.round(f * 100)}%`; },
    close,
  };
}

function dotFor(type: ToastType): HTMLElement {
  const color = type === 'success' ? 'var(--ok)' : type === 'error' ? 'var(--danger)' : 'var(--accent)';
  return h('span.toast-dot', { style: { background: color } });
}

/**
 * The post-export "support us" moment. Shown after any successful save/export —
 * reinforces the privacy promise and offers an optional tip link.
 */
let lastCelebrate = 0;
export function celebrateExport(filename: string) {
  const now = Date.now();
  if (now - lastCelebrate < 1500) return; // avoid double-fire on multi-file exports
  lastCelebrate = now;

  const card = h(
    'div.celebrate glass',
    { role: 'dialog' },
    h('button.celebrate-x', { onclick: () => close(), 'aria-label': 'Dismiss' }, '×'),
    h('div.celebrate-check', checkSvg()),
    h('h3.celebrate-title', 'Done — saved to your device'),
    h(
      'p.celebrate-body',
      `“${filename}” was created entirely in your browser. It never touched a server, and there's nothing for us to see.`,
    ),
    h(
      'div.celebrate-actions',
      h(
        'a.btn btn-primary btn-sm',
        { href: 'https://buymeacoffee.com/formulational', target: '_blank', rel: 'noopener' },
        '☕ Support free software',
      ),
      h('button.btn btn-soft btn-sm', { onclick: () => close() }, 'No thanks'),
    ),
  );
  getHost().appendChild(card);
  requestAnimationFrame(() => card.classList.add('in'));
  let done = false;
  const close = () => {
    if (done) return;
    done = true;
    card.classList.remove('in');
    setTimeout(() => card.remove(), 260);
  };
  setTimeout(close, 9000);
}

function checkSvg(): SVGElement {
  const el = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
  el.setAttribute('viewBox', '0 0 24 24');
  el.setAttribute('width', '22');
  el.setAttribute('height', '22');
  el.innerHTML =
    '<path d="M4 12.5l5 5 11-12" fill="none" stroke="#fff" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round"/>';
  return el;
}
