/* GEO-AGRO.AI · shared primitives, i18n, mock data, hooks */

// ── i18n dictionary ────────────────────────────────────────────
const I18N = {
  en: {
    // headers
    fieldCommand: 'Field Command',
    macroAnalytics: 'Macro-Analytics Portal',
    soilPassport: 'Verified Digital Soil Passport',
    aiAgronomist: 'AI Agronomist',
    sensorFleet: 'Sensor Fleet',
    yieldLedger: 'Predictive Yield Ledger',
    riskHeatmap: 'Geospatial Risk Heatmap',
    underwriting: 'Underwriting Console',
    fieldMap: 'Field Map',
    // labels
    fieldHealth: 'Field Health Score',
    soilMatrix: 'Soil Matrix',
    canopyClimate: 'Canopy Climate',
    moisture: 'Volumetric Moisture',
    temperature: 'Ambient Temperature',
    humidity: 'Relative Humidity',
    uvRadiation: 'Solar UV Index',
    frostRisk: 'Frost risk',
    droughtRisk: 'Drought stress',
    nominal: 'All zones nominal',
    zone: 'Zone',
    sensors: 'sensors',
    online: 'Online',
    battery: 'Battery',
    signal: 'Signal',
    lastSync: 'Last sync',
    nodes: 'Nodes',
    yield: 'Forecast yield',
    quality: 'Quality grade',
    harvestWindow: 'Harvest window',
    interestRate: 'Indicative rate',
    collateralValue: 'Collateral value',
    defaultRisk: 'Default risk',
    acknowledge: 'Acknowledge',
    actNow: 'Execute action',
    dismiss: 'Snooze 15m',
    // actions
    irrigate: 'Trigger drip-irrigation',
    activate: 'Activate frost shield',
    chat: 'Ask the agronomist',
    // alert lines
    alertFrostTitle: 'Frost risk detected',
    alertDroughtTitle: 'Drought stress projected',
    alertCalmTitle: 'All systems nominal',
  },
  ka: {
    fieldCommand: 'საველე ცენტრი',
    macroAnalytics: 'მაკრო-ანალიტიკის პორტალი',
    soilPassport: 'ნიადაგის ციფრული პასპორტი',
    aiAgronomist: 'AI აგრონომი',
    sensorFleet: 'სენსორების ფლოტი',
    yieldLedger: 'მოსავლის პროგნოზი',
    riskHeatmap: 'რისკის რუკა',
    underwriting: 'საბანკო კონსოლი',
    fieldMap: 'ნაკვეთის რუკა',
    fieldHealth: 'ნაკვეთის ჯანმრთელობა',
    soilMatrix: 'ნიადაგი',
    canopyClimate: 'კლიმატი',
    moisture: 'ტენიანობა',
    temperature: 'ტემპერატურა',
    humidity: 'ფარდობითი ტენი',
    uvRadiation: 'მზის UV ინდექსი',
    frostRisk: 'ყინვის რისკი',
    droughtRisk: 'გვალვის სტრესი',
    nominal: 'ყველა ზონა ნორმაშია',
    zone: 'ზონა',
    sensors: 'სენსორი',
    online: 'ჩართული',
    battery: 'ბატარეა',
    signal: 'სიგნალი',
    lastSync: 'ბოლო სინქრ.',
    nodes: 'კვანძი',
    yield: 'პროგნოზი',
    quality: 'ხარისხი',
    harvestWindow: 'მოსავლის ფანჯარა',
    interestRate: 'საპროცენტო განაკვ.',
    collateralValue: 'უზრუნველყოფა',
    defaultRisk: 'დეფოლტის რისკი',
    acknowledge: 'დადასტურება',
    actNow: 'მოქმედება',
    dismiss: 'გადადება 15წთ',
    irrigate: 'წვეთოვანი მორწყვა',
    activate: 'ყინვის ფარის ჩართვა',
    chat: 'აგრონომისთან საუბარი',
    alertFrostTitle: 'ყინვის რისკი დაფიქსირდა',
    alertDroughtTitle: 'გვალვის სტრესი მოსალოდნელია',
    alertCalmTitle: 'ყველაფერი ნორმაშია',
  },
  ru: {
    fieldCommand: 'Командный центр поля',
    macroAnalytics: 'Макроаналитика',
    soilPassport: 'Цифровой паспорт почвы',
    aiAgronomist: 'AI агроном',
    sensorFleet: 'Парк датчиков',
    yieldLedger: 'Прогноз урожая',
    riskHeatmap: 'Карта рисков',
    underwriting: 'Андеррайтинг',
    fieldMap: 'Карта поля',
    fieldHealth: 'Индекс здоровья поля',
    soilMatrix: 'Почва',
    canopyClimate: 'Климат',
    moisture: 'Объёмная влажность',
    temperature: 'Температура',
    humidity: 'Влажность',
    uvRadiation: 'УФ-индекс',
    frostRisk: 'Риск заморозков',
    droughtRisk: 'Засушливый стресс',
    nominal: 'Все зоны в норме',
    zone: 'Зона',
    sensors: 'датчики',
    online: 'Онлайн',
    battery: 'Батарея',
    signal: 'Сигнал',
    lastSync: 'Синхр.',
    nodes: 'Узлы',
    yield: 'Прогноз урожая',
    quality: 'Класс качества',
    harvestWindow: 'Окно сбора',
    interestRate: 'Ставка',
    collateralValue: 'Залог',
    defaultRisk: 'Риск дефолта',
    acknowledge: 'Принять',
    actNow: 'Действие',
    dismiss: 'Отложить 15м',
    irrigate: 'Запустить капельный полив',
    activate: 'Активировать защиту',
    chat: 'Спросить агронома',
    alertFrostTitle: 'Обнаружен риск заморозков',
    alertDroughtTitle: 'Прогнозируется засуха',
    alertCalmTitle: 'Все системы в норме',
  },
};

// ── runtime tweak context ─────────────────────────────────────
// shared across all artboards so the floating Tweaks panel drives
// every screen at once.
const GACtx = React.createContext({
  lang: 'en', alertState: 'frost', live: true,
  t: I18N.en,
});

function useGA() { return React.useContext(GACtx); }

// ── mock farm data ────────────────────────────────────────────
const FARM = {
  name: 'Saperavi · Plot K-3',
  region: 'Kvareli, Kakheti',
  owner: 'Giorgi M.',
  acreage: '4.8 ha',
  crop: 'Saperavi vines',
  zones: [
    { id: 'A', name: 'North Slope',   nodes: 4, soil: 38.2, temp: 11.4, hum: 72, uv: 2.1, health: 91, status: 'ok' },
    { id: 'B', name: 'Lower Ridge',   nodes: 5, soil: 31.8, temp:  8.7, hum: 86, uv: 1.6, health: 64, status: 'warn' },
    { id: 'C', name: 'South Terrace', nodes: 3, soil: 42.7, temp: 13.1, hum: 65, uv: 2.8, health: 88, status: 'ok' },
    { id: 'D', name: 'Eastern Block', nodes: 4, soil: 27.3, temp: 12.5, hum: 58, uv: 2.4, health: 71, status: 'warn' },
  ],
  totalNodes: 16,
  online: 16,
};

const SENSORS = [
  { id: 'GA-K3-014', zone: 'B', kind: 'Soil',   bat: 0.92, sig: 0.84, depth: '30 cm', sync: '4 min',  status: 'ok'   },
  { id: 'GA-K3-015', zone: 'B', kind: 'Canopy', bat: 0.88, sig: 0.79, depth: '+2.0 m', sync: '3 min',  status: 'ok'   },
  { id: 'GA-K3-016', zone: 'C', kind: 'Soil',   bat: 0.81, sig: 0.91, depth: '30 cm', sync: '6 min',  status: 'ok'   },
  { id: 'GA-K3-017', zone: 'A', kind: 'Soil',   bat: 0.73, sig: 0.62, depth: '30 cm', sync: '12 min', status: 'low'  },
  { id: 'GA-K3-018', zone: 'D', kind: 'Soil',   bat: 0.94, sig: 0.86, depth: '45 cm', sync: '2 min',  status: 'ok'   },
  { id: 'GA-K3-019', zone: 'D', kind: 'Canopy', bat: 0.89, sig: 0.77, depth: '+1.8 m', sync: '5 min',  status: 'ok'   },
  { id: 'GA-K3-020', zone: 'A', kind: 'UV',     bat: 0.96, sig: 0.92, depth: '+2.4 m', sync: '1 min',  status: 'ok'   },
  { id: 'GA-K3-021', zone: 'C', kind: 'Canopy', bat: 0.68, sig: 0.58, depth: '+2.0 m', sync: '14 min', status: 'low'  },
  { id: 'GA-K3-022', zone: 'B', kind: 'UV',     bat: 0.45, sig: 0.81, depth: '+2.4 m', sync: '3 min',  status: 'low'  },
  { id: 'GA-K3-023', zone: 'D', kind: 'Soil',   bat: 0.82, sig: 0.71, depth: '30 cm', sync: '8 min',  status: 'ok'   },
];

// ── primitive UI components ───────────────────────────────────

// Pill — kicker pill used everywhere
function Pill({ children, color = 'amber', solid = false, size = 'sm', style = {} }) {
  const colors = {
    amber:  { fg: '#FFA500', bg: 'rgba(255,165,0,0.10)', bd: 'rgba(255,165,0,0.32)' },
    yellow: { fg: '#FFD60A', bg: 'rgba(255,214,10,0.10)', bd: 'rgba(255,214,10,0.32)' },
    red:    { fg: '#FF453A', bg: 'rgba(255,69,58,0.10)', bd: 'rgba(255,69,58,0.32)' },
    green:  { fg: '#43D67A', bg: 'rgba(67,214,122,0.10)', bd: 'rgba(67,214,122,0.32)' },
    blue:   { fg: '#4FC3FF', bg: 'rgba(79,195,255,0.10)', bd: 'rgba(79,195,255,0.32)' },
    ghost:  { fg: 'rgba(250,250,250,0.7)', bg: 'rgba(255,255,255,0.04)', bd: 'rgba(255,255,255,0.12)' },
  }[color] || {};
  const sz = size === 'sm' ? { fs: 9.5, py: 3, px: 7, lh: 1, ls: '0.14em' }
                           : { fs: 10.5, py: 5, px: 9, lh: 1, ls: '0.16em' };
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 5,
      padding: `${sz.py}px ${sz.px}px`,
      fontFamily: 'var(--f-mono)', fontSize: sz.fs, fontWeight: 600,
      letterSpacing: sz.ls, textTransform: 'uppercase', lineHeight: sz.lh,
      color: solid ? '#0A0A0B' : colors.fg,
      background: solid ? colors.fg : colors.bg,
      border: `1px solid ${solid ? colors.fg : colors.bd}`,
      borderRadius: 4,
      ...style,
    }}>{children}</span>
  );
}

// LiveDot — pulsing status indicator
function LiveDot({ color = 'green', size = 7 }) {
  const c = { green: '#43D67A', amber: '#FFA500', red: '#FF453A', yellow: '#FFD60A' }[color] || color;
  return (
    <span style={{ position: 'relative', display: 'inline-block', width: size, height: size }}>
      <span style={{ position: 'absolute', inset: 0, borderRadius: '50%', background: c }} />
      <span style={{ position: 'absolute', inset: -2, borderRadius: '50%', background: c, opacity: 0.4,
        animation: 'ga-pulse 1.8s ease-in-out infinite' }} />
    </span>
  );
}

// Metric — big number with kicker + unit (mono)
function Metric({ kicker, value, unit, color = 'ink', tnum = true, style = {}, big = false }) {
  const c = { ink: 'var(--ink)', yellow: 'var(--yellow)', amber: 'var(--amber)',
             green: 'var(--green)', red: 'var(--red)' }[color] || color;
  return (
    <div style={style}>
      {kicker && <div className="ga-kicker" style={{ marginBottom: 6 }}>{kicker}</div>}
      <div style={{ display: 'flex', alignItems: 'baseline', gap: 4, fontFamily: 'var(--f-mono)',
        fontWeight: 500, color: c }}>
        <span className={tnum ? 'ga-tnum' : ''} style={{ fontSize: big ? 44 : 24, letterSpacing: '-0.03em', fontWeight: 600 }}>
          {value}
        </span>
        {unit && <span style={{ fontSize: big ? 14 : 11, color: 'var(--ink-3)', letterSpacing: '0.04em' }}>{unit}</span>}
      </div>
    </div>
  );
}

// BilingualHeader — small block: EN headline + KA/RU subtitle when lang toggled
function BilingualHeader({ kicker, en, ka, ru, size = 'md', style = {} }) {
  const { lang } = useGA();
  const sz = { sm: { p: 13, s: 10 }, md: { p: 18, s: 11 }, lg: { p: 26, s: 13 } }[size];
  const primary = lang === 'en' ? en : (lang === 'ka' ? ka : ru);
  const secondary = lang === 'en' ? ka : (lang === 'ka' ? en : en);
  return (
    <div style={style}>
      {kicker && <div className="ga-kicker" style={{ marginBottom: 6 }}>{kicker}</div>}
      <div className="ga-disp" style={{ fontSize: sz.p, fontWeight: 600, color: 'var(--ink)', lineHeight: 1.15 }}>{primary}</div>
      {secondary && secondary !== primary && (
        <div style={{ fontFamily: 'var(--f-body)', fontSize: sz.s, color: 'var(--ink-3)',
          marginTop: 4, lineHeight: 1.2 }}>{secondary}</div>
      )}
    </div>
  );
}

// Sparkline — tiny svg line
function Sparkline({ data, color = '#FFD60A', width = 60, height = 18, area = true }) {
  const n = data.length;
  const min = Math.min(...data), max = Math.max(...data);
  const rng = max - min || 1;
  const points = data.map((v, i) => [
    (i / (n - 1)) * width,
    height - ((v - min) / rng) * (height - 2) - 1,
  ]);
  const d = points.map((p, i) => `${i === 0 ? 'M' : 'L'}${p[0].toFixed(1)},${p[1].toFixed(1)}`).join(' ');
  const da = `${d} L${width},${height} L0,${height} Z`;
  return (
    <svg width={width} height={height} viewBox={`0 0 ${width} ${height}`} style={{ display: 'block' }}>
      {area && <path d={da} fill={color} fillOpacity="0.15" />}
      <path d={d} stroke={color} strokeWidth="1.2" fill="none" strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  );
}

// GhostButton — outline button
function GhostButton({ children, onClick, color = 'amber', size = 'md', icon, style = {}, solid = false }) {
  const colors = {
    amber:  '#FFA500', yellow: '#FFD60A', red: '#FF453A',
    green: '#43D67A', ghost: 'rgba(255,255,255,0.75)',
  };
  const c = colors[color] || color;
  const sz = size === 'sm' ? { py: 8, px: 12, fs: 11 }
           : size === 'lg' ? { py: 14, px: 22, fs: 13 }
           : { py: 11, px: 16, fs: 12 };
  return (
    <button onClick={onClick} style={{
      display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 8,
      padding: `${sz.py}px ${sz.px}px`,
      fontFamily: 'var(--f-mono)', fontSize: sz.fs, fontWeight: 600,
      letterSpacing: '0.08em', textTransform: 'uppercase',
      color: solid ? '#0A0A0B' : c,
      background: solid ? c : 'transparent',
      border: `1px solid ${solid ? c : c + '66'}`,
      borderRadius: 6, cursor: 'pointer',
      transition: 'all .15s',
      ...style,
    }}
    onMouseEnter={(e) => { if (!solid) e.currentTarget.style.background = c + '14'; }}
    onMouseLeave={(e) => { if (!solid) e.currentTarget.style.background = 'transparent'; }}
    >
      {icon}
      {children}
    </button>
  );
}

// Panel — bordered dark card
function Panel({ children, style = {}, pad = 16, hoverable = false }) {
  return (
    <div style={{
      background: 'var(--bg-2)',
      border: '1px solid var(--line-2)',
      borderRadius: 'var(--r-md)',
      padding: pad,
      position: 'relative',
      ...style,
    }}>{children}</div>
  );
}

// CrossHair — corner crosshair decoration for an "instrument" feel
function CornerTicks({ color = 'rgba(255,255,255,0.2)', size = 8, offset = 0 }) {
  const stroke = { stroke: color, strokeWidth: 1, fill: 'none' };
  const o = offset;
  return (
    <svg style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }} width="100%" height="100%">
      <path d={`M${o},${o+size} L${o},${o} L${o+size},${o}`} {...stroke} />
      <path d={`M${o},calc(100% - ${o+size}px) L${o},calc(100% - ${o}px) L${o+size},calc(100% - ${o}px)`} {...stroke} />
      <path d={`M calc(100% - ${o+size}px) ${o} L calc(100% - ${o}px) ${o} L calc(100% - ${o}px) ${o+size}`} {...stroke} />
      <path d={`M calc(100% - ${o+size}px) calc(100% - ${o}px) L calc(100% - ${o}px) calc(100% - ${o}px) L calc(100% - ${o}px) calc(100% - ${o+size}px)`} {...stroke} />
    </svg>
  );
}

// useTickingValue — bounces a value around its baseline when live is on
function useTickingValue(initial, { jitter = 0.4, interval = 1500, enabled = true } = {}) {
  const [v, setV] = React.useState(initial);
  React.useEffect(() => {
    if (!enabled) { setV(initial); return; }
    const tk = setInterval(() => {
      setV((p) => {
        const delta = (Math.random() - 0.5) * jitter * 2;
        const next = +(initial + delta).toFixed(initial < 10 ? 2 : 1);
        return next;
      });
    }, interval + Math.random() * 800);
    return () => clearInterval(tk);
  }, [initial, jitter, interval, enabled]);
  return v;
}

// Brand mark — GA logo
function BrandMark({ size = 22, color = 'var(--yellow)' }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" style={{ display: 'block' }}>
      <rect x="0.5" y="0.5" width="23" height="23" rx="3" stroke={color} strokeWidth="1.25"/>
      <path d="M7 7 L7 17 L13 17 L13 12 L10 12" stroke={color} strokeWidth="1.75" strokeLinecap="square" fill="none"/>
      <circle cx="17" cy="7" r="1.5" fill={color}/>
    </svg>
  );
}

// expose to other babel scripts
Object.assign(window, {
  I18N, GACtx, useGA, FARM, SENSORS,
  Pill, LiveDot, Metric, BilingualHeader, Sparkline,
  GhostButton, Panel, CornerTicks, useTickingValue, BrandMark,
});
