// ArtisanFlow — design tokens & shared primitives
// "Chantier assumé" : bleu industriel profond, orange sécurité, gris béton chaud

const afTokens = {
  light: {
    // Backgrounds
    bg:          '#F1EFEB',      // gris béton chaud très clair
    bgElevated:  '#FFFFFF',
    bgSunken:    '#E7E4DE',
    // Text
    text:        '#15202B',      // presque noir, teinté bleu
    textMuted:   '#5A6772',
    textDim:     '#8A94A0',
    // Brand
    primary:     '#0B3D5C',      // bleu industriel profond
    primaryHover:'#0A324C',
    primaryTint: 'rgba(11,61,92,0.08)',
    // Accents
    safety:      '#FF6B00',      // orange sécurité (alertes, CTA haute prio)
    safetyTint:  'rgba(255,107,0,0.12)',
    success:     '#0F766E',
    warn:        '#B45309',
    danger:      '#B91C1C',
    // Borders
    border:      'rgba(21,32,43,0.12)',
    borderStrong:'rgba(21,32,43,0.22)',
    // Shadows
    shadowSm:    '0 1px 2px rgba(21,32,43,0.08)',
    shadowMd:    '0 2px 8px rgba(21,32,43,0.08), 0 0 0 1px rgba(21,32,43,0.04)',
  },
  dark: {
    bg:          '#0D1520',      // bleu nuit profond
    bgElevated:  '#172230',
    bgSunken:    '#060B13',
    text:        '#F3F5F7',
    textMuted:   '#9CA8B5',
    textDim:     '#6B7887',
    primary:     '#3AA8E8',      // bleu plus clair en sombre
    primaryHover:'#5ABAF0',
    primaryTint: 'rgba(58,168,232,0.12)',
    safety:      '#FF8A3D',      // orange plus chaud en sombre
    safetyTint:  'rgba(255,138,61,0.15)',
    success:     '#34D399',
    warn:        '#FBBF24',
    danger:      '#F87171',
    border:      'rgba(255,255,255,0.08)',
    borderStrong:'rgba(255,255,255,0.16)',
    shadowSm:    '0 1px 2px rgba(0,0,0,0.4)',
    shadowMd:    '0 2px 8px rgba(0,0,0,0.4), 0 0 0 1px rgba(255,255,255,0.04)',
  }
};

const AF_FONTS = `
@import url('https://fonts.googleapis.com/css2?family=Inter+Tight:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;700&display=swap');

.af-app, .af-app * {
  font-family: 'Inter Tight', system-ui, -apple-system, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  box-sizing: border-box;
}
.af-mono { font-family: 'JetBrains Mono', ui-monospace, monospace; font-feature-settings: 'tnum'; }
.af-app button { cursor: pointer; border: none; background: none; color: inherit; font: inherit; padding: 0; }
.af-app input, .af-app textarea { font: inherit; color: inherit; }
.af-app ::-webkit-scrollbar { width: 6px; height: 6px; }
.af-app ::-webkit-scrollbar-thumb { background: rgba(127,127,127,0.3); border-radius: 3px; }

/* Texture chantier: diagonales hachurées */
.af-hazard {
  background-image: repeating-linear-gradient(
    -45deg,
    currentColor 0, currentColor 2px,
    transparent 2px, transparent 8px
  );
}

/* Tape bandeau sécurité */
.af-tape {
  background: repeating-linear-gradient(
    -45deg,
    #FF6B00 0, #FF6B00 14px,
    #15202B 14px, #15202B 28px
  );
}

/* Animations */
@keyframes af-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.4; }
}
@keyframes af-wave {
  0%, 100% { transform: scaleY(0.3); }
  50% { transform: scaleY(1); }
}
@keyframes af-slide-up {
  from { transform: translateY(12px); opacity: 0; }
  to { transform: translateY(0); opacity: 1; }
}
@keyframes af-count {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: translateY(0); }
}
.af-slide-up { animation: af-slide-up 0.28s cubic-bezier(0.2, 0.8, 0.2, 1) both; }

/* PWA / mobile : plein écran, pas de scroll horizontal */
@media (max-width: 768px) {
  html, body { max-width: 100%; overflow-x: hidden; }
  #root { min-height: 100dvh; display: flex; flex-direction: column; }
}

/* Signature canvas */
.af-sig-canvas { cursor: crosshair; touch-action: none; }
`;

// ─── Primitives ─────────────────────────────────────────────

function AfBadge({ status, t, size = 'sm' }) {
  const s = AF_STATUS[status] || AF_STATUS.brouillon;
  const pad = size === 'lg' ? '6px 10px' : '3px 8px';
  const fs = size === 'lg' ? 13 : 11;
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 6,
      padding: pad, borderRadius: 4, fontSize: fs,
      fontWeight: 700, letterSpacing: 0.2,
      textTransform: 'uppercase',
      background: s.bg, color: s.color,
      border: `1px solid ${s.color}33`,
    }}>
      <span style={{
        width: 6, height: 6, borderRadius: 1, background: s.color,
        ...(status === 'retard' ? { animation: 'af-pulse 1.2s infinite' } : {}),
      }} />
      {s.label}
    </span>
  );
}

function AfButton({ children, onClick, variant = 'primary', size = 'md', t, icon, full, style = {}, disabled }) {
  const sizes = {
    sm: { p: '8px 14px', fs: 13, h: 36 },
    md: { p: '12px 18px', fs: 15, h: 48 },
    lg: { p: '16px 22px', fs: 17, h: 58 },  // gros doigts
    xl: { p: '20px 24px', fs: 18, h: 68 },
  };
  const sz = sizes[size];
  const variants = {
    primary: { bg: t.primary, color: '#fff', border: 'transparent' },
    safety:  { bg: t.safety, color: '#0D1520', border: 'transparent' },
    ghost:   { bg: 'transparent', color: t.text, border: t.border },
    danger:  { bg: t.danger, color: '#fff', border: 'transparent' },
    sunken:  { bg: t.bgSunken, color: t.text, border: t.border },
  };
  const v = variants[variant];
  return (
    <button
      onClick={onClick}
      disabled={disabled}
      style={{
        display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 8,
        padding: sz.p, height: sz.h, width: full ? '100%' : 'auto',
        background: v.bg, color: v.color,
        border: `1.5px solid ${v.border}`,
        borderRadius: 6, fontSize: sz.fs, fontWeight: 700,
        letterSpacing: 0.1, transition: 'transform 0.08s, filter 0.15s',
        opacity: disabled ? 0.5 : 1,
        ...style,
      }}
      onMouseDown={(e) => e.currentTarget.style.transform = 'scale(0.98)'}
      onMouseUp={(e) => e.currentTarget.style.transform = 'scale(1)'}
      onMouseLeave={(e) => e.currentTarget.style.transform = 'scale(1)'}
    >
      {icon}
      {children}
    </button>
  );
}

function AfCard({ children, t, style = {}, onClick, flat }) {
  return (
    <div
      onClick={onClick}
      style={{
        background: t.bgElevated,
        border: `1px solid ${t.border}`,
        borderRadius: 8,
        boxShadow: flat ? 'none' : t.shadowSm,
        cursor: onClick ? 'pointer' : 'default',
        ...style,
      }}
    >
      {children}
    </div>
  );
}

// Montant formaté avec devise
function AfAmount({ value, currency = 'EUR', size = 'md', muted, t, decimals = 0 }) {
  const sym = currency === 'CHF' ? 'CHF' : '€';
  const sizes = { xs: 12, sm: 14, md: 18, lg: 24, xl: 34, xxl: 48 };
  const fs = sizes[size] || 18;
  const formatted = Number(value).toLocaleString('fr-FR', {
    minimumFractionDigits: decimals, maximumFractionDigits: decimals,
  });
  return (
    <span className="af-mono" style={{
      fontSize: fs, fontWeight: 700, color: muted ? t.textMuted : t.text,
      letterSpacing: -0.5, fontVariantNumeric: 'tabular-nums',
    }}>
      {currency === 'CHF' ? `${formatted} ${sym}` : `${formatted} ${sym}`}
    </span>
  );
}

// Bouton de nav tab (bottom nav)
function AfTab({ icon, label, active, onClick, t }) {
  return (
    <button
      onClick={onClick}
      role="tab"
      aria-selected={active}
      aria-label={label}
      style={{
        flex: 1, height: '100%', display: 'flex', flexDirection: 'column',
        alignItems: 'center', justifyContent: 'center', gap: 3,
        color: active ? t.primary : t.textMuted,
        position: 'relative', padding: '6px 0',
      }}
    >
      {active && (
        <div style={{
          position: 'absolute', top: 0, left: '25%', right: '25%',
          height: 3, background: t.safety, borderRadius: '0 0 3px 3px',
        }} />
      )}
      <div style={{ opacity: active ? 1 : 0.7 }}>{icon}</div>
      <span style={{ fontSize: 10.5, fontWeight: active ? 700 : 600, letterSpacing: 0.3 }}>
        {label.toUpperCase()}
      </span>
    </button>
  );
}

// Bandeau hazard (orange/noir) — décoratif
function AfHazardBand({ height = 8, style = {} }) {
  return <div className="af-tape" style={{ height, width: '100%', ...style }} />;
}

// Placeholder image avec striures
function AfPlaceholder({ label, h = 120, t }) {
  return (
    <div style={{
      height: h, width: '100%', borderRadius: 6,
      background: `repeating-linear-gradient(135deg, ${t.bgSunken} 0, ${t.bgSunken} 10px, ${t.bg} 10px, ${t.bg} 20px)`,
      border: `1px dashed ${t.border}`,
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      fontFamily: 'JetBrains Mono, monospace', fontSize: 11, color: t.textMuted,
      textTransform: 'uppercase', letterSpacing: 1,
    }}>
      [ {label} ]
    </div>
  );
}

// Hook pratique pour theme
function useAfTheme(dark) {
  return React.useMemo(() => dark ? afTokens.dark : afTokens.light, [dark]);
}

// Intégration Workers Cloudflare (aucun secret : uniquement des URL publiques et identifiant optionnel non sensible).
// Déploiement type : front Vercel (ex. https://instantdevis.vercel.app) + ce Worker (URL *.workers.dev ou domaine custom).
// Renseignez ici l’URL publique du Worker (GET /health pour vérifier), ou l’onglet Profil → Cloud : « URL Worker unifié »
// (même effet, stocké en local) — jamais de clé API / secret dans ce fichier.
const AF_INTEGRATION = {
  /**
   * Base HTTPS unique d’un Worker qui expose /v1/agents/* (et idéalement les routes legacy en alias).
   * Exemple après déploiement : 'https://instantdevis-agents.votre-compte.workers.dev' (sans slash final requis, normalisé côté client).
   * Si renseignée, elle sert en priorité pour l’acoustique, le flux, le sourcing et le gardien.
   * Laisser '' pour s’appuyer sur le profil (`workersBaseUrl`) ou `vocalWorkerBase` + `mailWorkerBase` (comportement historique).
   */
  workersBase: 'https://instantdevis-agents.sciencezvousyt.workers.dev',
  /** Repli intégration (tokens) : dictée, si le profil n’a pas d’URL dédiée. */
  vocalWorkerBase: '',
  /** Repli intégration (tokens) : envoi e-mail, si `workersBase` est vide. */
  mailWorkerBase: '',
  /**
   * Optionnel : identifiant d’app / d’installation (non secret) — filtrage côté Worker sur liste autorisée.
   * Le secret de contrôle (handshake) reste exclusivement côté Cloudflare (variable d’environnement / secret Wrangler).
   */
  appClientId: '',
  /**
   * Nom d’en-tête HTTP pour `appClientId` (défaut : X-Instant-Devis-Client-Id). Ne pas y coller de clé API.
   */
  appClientIdHeader: '',
  /**
   * Si true, le client tente d’abord /v1/vocal-ingest puis l’agent /v1/agents/acoustic en cas de 404.
   * Si false (défaut) : /v1/agents/acoustic puis repli /v1/vocal-ingest.
   */
  preferLegacyVocalPath: false,
  /**
   * Si true : /v1/send-devis d’abord, puis /v1/agents/flux en 404.
   * Si false (défaut) : /v1/agents/flux puis /v1/send-devis.
   */
  preferLegacySendPath: false,
  /**
   * Timeout des fetch Workers en ms (5000..300000). Hors plage = repli 45000.
   */
  workerTimeoutMs: 0,
};

Object.assign(window, {
  afTokens, AF_FONTS, useAfTheme, AF_INTEGRATION,
  AfBadge, AfButton, AfCard, AfAmount, AfTab, AfHazardBand, AfPlaceholder,
});
