// shared.jsx — atoms used across screens

const DEMO_ASSET_BASE = (() => {
  if (typeof document === 'undefined') return '';
  const scripts = Array.from(document.scripts || []);
  const script = scripts.reverse().find((s) => /shared\.jsx(?:\?|$)/.test(s.getAttribute('src') || s.src || ''));
  const src = script && (script.getAttribute('src') || script.src);
  if (!src) return location.pathname.includes('/demo') ? '/demo/' : '/';
  try {
    return new URL(src, window.location.href).pathname.replace(/[^/]*$/, '');
  } catch (e) {
    return src.replace(/[^/]*$/, '');
  }
})();

function demoAssetSrc(path) {
  return DEMO_ASSET_BASE + String(path || '').replace(/^\/+/, '');
}

function normalizeSpeciesIconKey(value) {
  return String(value || '')
    .toLowerCase()
    .replace(/['’]/g, '')
    .replace(/[^a-z0-9]+/g, '_')
    .replace(/^_+|_+$/g, '');
}

function speciesIconKey(folk) {
  const alias = {
    corydoras_catfish: 'corydoras',
    freshwater_angelfish: 'angelfish',
    red_cherry_shrimp: 'cherry_shrimp',
    siamese_fighting_fish: 'betta',
    mongolian_gerbil: 'gerbil',
    land_hermit_crab: 'hermit_crab',
    pacific_parrotlet: 'parrotlet',
    ringneck_dove: 'dove',
    domestic_duck: 'duck',
    domestic_goose: 'goose',
    domestic_pigeon: 'pigeon',
    common_garter_snake: 'garter_snake',
    common_musk_turtle: 'musk_turtle',
    regal_jumping_spider: 'jumping_spider',
    golden_pothos: 'pothos',
    moth_orchid: 'orchid',
    dwarf_umbrella_tree: 'schefflera',
    chinese_money_plant: 'pilea_peperomioides',
    wax_plant: 'hoya',
    arrowhead_vine: 'syngonium',
    cilantro_coriander: 'cilantro',
    spring_crocus: 'crocus',
    purple_coneflower: 'coneflower',
    bearded_iris: 'iris',
    tropical_hibiscus: 'hibiscus',
    fountain_grass_verify_exact_species: 'fountain_grass',
    bamboo_verify_exact_species: 'bamboo',
  };
  const fromAlias = (key) => alias[key] || key;
  if (folk?.iconKey) {
    return fromAlias(normalizeSpeciesIconKey(folk.iconKey));
  }
  const raw = String(folk?.species || folk?.lbl || '').toLowerCase();
  const explicit = {
    'cat': 'cat',
    'dog': 'dog',
    'guinea pig': 'guinea_pig',
    'betta fish': 'betta',
    'fish': 'betta',
    'rabbit': 'rabbit',
    'hamster': 'syrian_hamster',
    'bird': 'canary',
    'parrot': 'amazon_parrot',
    'turtle': 'red_eared_slider',
    'lizard': 'leopard_gecko',
    'snake': 'corn_snake',
    'frog': 'whites_tree_frog',
    'invertebrate': 'jumping_spider',
    'fern': 'boston_fern',
    'maidenhair fern': 'maidenhair_fern',
    'cactus': 'christmas_cactus',
    'palm': 'parlor_palm',
    'fiddle leaf': 'fiddle_leaf_fig',
    'flower': 'rose',
    'vegetable': 'tomato',
    'herb': 'basil',
    'other': 'zz_plant',
  }[raw];
  if (explicit) return explicit;
  const libraryMatch = []
    .concat(window.FULL_PET_LIBRARY || [], window.FULL_PLANT_LIBRARY || [])
    .find((s) => String(s.lbl || '').toLowerCase() === raw);
  if (libraryMatch?.iconKey) return fromAlias(normalizeSpeciesIconKey(libraryMatch.iconKey));
  return fromAlias(normalizeSpeciesIconKey(raw));
}

function speciesIconSrc(folk) {
  const key = speciesIconKey(folk);
  if (!key) return null;
  return demoAssetSrc(`ios-assets/icon-${key}.imageset/${key}.png`);
}

function useRetryingIconSrc(src) {
  const [iconFailed, setIconFailed] = React.useState(false);
  const [retry, setRetry] = React.useState(0);

  React.useEffect(() => {
    setIconFailed(false);
    setRetry(0);
  }, [src]);

  React.useEffect(() => {
    if (!src || !iconFailed || retry >= 2) return;
    const timer = window.setTimeout(() => {
      setRetry((value) => value + 1);
      setIconFailed(false);
    }, 700 + retry * 500);
    return () => window.clearTimeout(timer);
  }, [src, iconFailed, retry]);

  const displaySrc = src && retry > 0
    ? `${src}${src.includes('?') ? '&' : '?'}retry=${retry}`
    : src;

  return { displaySrc, iconFailed, setIconFailed };
}

// Avatar — prefers the actual app species icons from Assets.xcassets.
function FolkAvatar({ folk, size = 'md' }) {
  const cls = size === 'xl' ? 'avatar xl' : size === 'lg' ? 'avatar lg' : 'avatar';
  const iconSrc = speciesIconSrc(folk);
  const icon = useRetryingIconSrc(iconSrc);
  if (folk?.photoUrl) {
    return (
      <div className={cls + ' has-photo'} data-tint={folk.tint}>
        <img src={folk.photoUrl} alt={folk.name} />
      </div>
    );
  }
  return (
    <div className={cls} data-tint={folk.tint}>
      {iconSrc && !icon.iconFailed
        ? <img className="species-icon-img" src={icon.displaySrc} alt="" onError={() => icon.setIconFailed(true)} />
        : <span className="glyph">{folk.emoji}</span>}
    </div>
  );
}

function SpeciesIcon({ folk, species, kind, className = 'species-icon-img', fallbackClassName = 'glyph', fallback }) {
  const source = folk || { species: species?.lbl || species?.species || species, kind, iconKey: species?.iconKey };
  const iconSrc = speciesIconSrc(source);
  const icon = useRetryingIconSrc(iconSrc);
  if (iconSrc && !icon.iconFailed) {
    return <img className={className} src={icon.displaySrc} alt="" onError={() => icon.setIconFailed(true)} />;
  }
  return <span className={fallbackClassName}>{fallback || source?.emoji || species?.em || '•'}</span>;
}

// Task row with swipe-to-complete
function TaskRow({ task, folk, onToggle, completing }) {
  const [dx, setDx] = React.useState(0);
  const startX = React.useRef(null);
  const swiping = Math.abs(dx) > 6;

  const onDown = (e) => {
    if (completing) return;
    const x = e.touches ? e.touches[0].clientX : e.clientX;
    startX.current = x;
    const move = (ev) => {
      const cx = ev.touches ? ev.touches[0].clientX : ev.clientX;
      const d = cx - startX.current;
      if (d > 0) setDx(Math.min(120, d));
    };
    const up = (ev) => {
      const cx = (ev.changedTouches ? ev.changedTouches[0].clientX : ev.clientX);
      const d = cx - startX.current;
      if (d > 70 && !task.done) onToggle();
      setDx(0);
      window.removeEventListener('mousemove', move);
      window.removeEventListener('mouseup', up);
      window.removeEventListener('touchmove', move);
      window.removeEventListener('touchend', up);
    };
    window.addEventListener('mousemove', move);
    window.addEventListener('mouseup', up);
    window.addEventListener('touchmove', move, { passive: true });
    window.addEventListener('touchend', up);
  };

  const KIcon = window.I.kind[task.kind] || window.I.bowl;

  return (
    <div className={'task' + (task.done ? ' done' : '') + (swiping ? ' swiping' : '') + (completing ? ' completing' : '')}
         onMouseDown={onDown} onTouchStart={onDown}
         style={{ transform: completing ? undefined : `translateX(${dx}px)` }}>
      <div className="swipe-track">
        <window.I.check size={18} sw={2.2} /> &nbsp; Mark done
      </div>
      <div className="time h-mono">{task.time}</div>
      <button className="check" aria-label={task.done ? 'Mark not done' : 'Mark done'}
              onClick={(e) => { e.stopPropagation(); onToggle(); }}>
        <window.I.check size={14} sw={2.5} />
      </button>
      <FolkAvatar folk={folk} />
      <div className="body">
        <div className="title">{task.verb}</div>
        {task.detail && <div className="det">{task.detail}</div>}
      </div>
      <div style={{ color: 'var(--ink-3)', display: 'flex', alignItems: 'center', paddingRight: 4 }}>
        <KIcon size={16} sw={1.6} />
      </div>
    </div>
  );
}

// Bottom tab bar — mirrors the native iOS root tabs.
function TabBar({ tab, setTab }) {
  const tabs = [
    { id: 'today',    icon: window.I.sun,       lbl: 'Today' },
    { id: 'folk',     icon: window.I.leaf,      lbl: 'Folk'  },
    { id: 'meals',    icon: window.I.forkKnife, lbl: 'Meals' },
    { id: 'profile',  icon: window.I.user,      lbl: 'You'   },
  ];
  return (
    <div className="tabbar-shell">
      <div className="tabbar">
        {tabs.slice(0, 2).map((t) => {
          const Icn = t.icon;
          const on = tab === t.id;
          return (
            <button key={t.id} data-on={on ? '1' : '0'} onClick={() => setTab(t.id)}>
              <Icn size={24} />
              <span className="lbl">{t.lbl}</span>
            </button>
          );
        })}
        <button className="tabbar-center" onClick={() => setTab('add')} aria-label="Add">
          <window.I.plus size={26} sw={2.35} />
        </button>
        {tabs.slice(2).map((t) => {
          const Icn = t.icon;
          const on = tab === t.id;
          return (
            <button key={t.id} data-on={on ? '1' : '0'} onClick={() => setTab(t.id)}>
              <Icn size={24} />
              <span className="lbl">{t.lbl}</span>
            </button>
          );
        })}
      </div>
    </div>
  );
}

// Section header with serif title + mono kicker + optional count
function SectionHeader({ kicker, title, count, accent }) {
  return (
    <div className="section-hd">
      <div>
        <div className="lbl">{kicker}</div>
        <h2>{title}{accent && <i> {accent}</i>}</h2>
      </div>
      {count != null && <div className="count">{count}</div>}
    </div>
  );
}

// In-phone nav bar (back arrow + ellipsis pills)
function MiniNav({ onBack, title }) {
  return (
    <div className="mini-nav">
      <button className="mini-nav-btn" onClick={onBack} aria-label="Back">
        <window.I.back size={20} sw={1.8} />
      </button>
      {title && <div className="h-mono mini-nav-title">{title}</div>}
      <button className="mini-nav-btn" aria-label="More">
        <window.I.more size={20} sw={1.8} />
      </button>
    </div>
  );
}

Object.assign(window, { FolkAvatar, SpeciesIcon, TaskRow, TabBar, SectionHeader, MiniNav, speciesIconSrc });
