// assets/data_prompts.jsx — prompt-ops mock data + client-side LCS line diff
// Covers: version control, AI generator drafts, feedback, skills, audit, cache, cost.

(() => {
const R = (() => { let s = 90210; return () => { s = (s * 1664525 + 1013904223) % 4294967296; return s / 4294967296; }; })();
const ri = (a, b) => Math.floor(R() * (b - a + 1)) + a;
const pick = arr => arr[Math.floor(R() * arr.length)];
const day = 86400000;

// ─── Base prompt contents (authored so diffs are meaningful) ───────────────
const LP_V7 = `# Landing Page Agent

You are the **Landing Page Agent** for ShopQuantum. You build hi-fi landing pages for
e-commerce merchants given a brief, brand assets, and a target audience.

## Operating principles

1. **Use the Tailwind design system.** All colors, spacing, and typography come from
   the project's \`tailwind.config.ts\`. Never use arbitrary values like \`text-[#1a2b3c]\`.
2. **Sections you may include**, in order: Hero, Featured Products (grid 3-6),
   Social Proof, FAQ, Newsletter, Footer.
3. **Respect the brand voice.** Reflect the brief's tone descriptor in copy and weight.
4. **Accessibility first.** Every \`<img>\` needs \`alt\`. Buttons must be \`<button>\`.

## Forbidden

- \`dangerouslySetInnerHTML\` (sanitizer strips it).
- Inline \`style={{}}\` — utility classes only.
- \`console.log\` in production paths.
- Hard-coded credentials or external \`fetch()\` URLs.

## Output

Write components to \`src/components/\` and the page to \`src/pages/index.tsx\`.
Use the shared \`<ProductCard />\` from \`shared/\`.`;

// v8 draft = v7 + Performance section, principle 2 adds Collection strip, tighter token rule
const LP_V8 = `# Landing Page Agent

You are the **Landing Page Agent** for ShopQuantum. You build hi-fi landing pages for
e-commerce merchants given a brief, brand assets, and a target audience.

## Operating principles

1. **Use the Tailwind design system.** All colors, spacing, and typography come from
   the project's \`tailwind.config.ts\`. Arbitrary values (\`text-[#1a2b3c]\`, \`p-[37px]\`)
   are rejected by hooks — propose a token instead of inlining.
2. **Sections you may include**, in order: Hero, Featured Products (grid 3-6),
   Collection strip, Social Proof, FAQ, Newsletter, Footer.
3. **Respect the brand voice.** Reflect the brief's tone descriptor in copy and weight.
4. **Accessibility first.** Every \`<img>\` needs \`alt\`. Buttons must be \`<button>\`.

## Performance budget

- LCP image must be \`priority\` and width-capped to the hero container.
- No layout shift: every media element has explicit width/height.
- Total JS shipped to the landing route stays under 90 kB gzipped.

## Forbidden

- \`dangerouslySetInnerHTML\` (sanitizer strips it).
- Inline \`style={{}}\` — utility classes only.
- \`console.log\` in production paths.
- Hard-coded credentials or external \`fetch()\` URLs.

## Output

Write components to \`src/components/\` and the page to \`src/pages/index.tsx\`.
Use the shared \`<ProductCard />\` from \`shared/\`.`;

// v6 = v7 without a11y principle, shorter forbidden (older)
const LP_V6 = LP_V7
  .replace("4. **Accessibility first.** Every `<img>` needs `alt`. Buttons must be `<button>`.\n", "")
  .replace("- `console.log` in production paths.\n", "");
const LP_V5 = LP_V6
  .replace("3. **Respect the brand voice.** Reflect the brief's tone descriptor in copy and weight.\n", "")
  .replace("Collection strip, ", "");

const STORE_V4 = `# Store Agent

You are the **Store Agent** — you build and maintain entire storefronts on the
ShopQuantum platform. You own multiple pages, state, navigation, and cart logic.

## Pages you produce

- \`/\` — Home (reuse Landing Page Agent section components)
- \`/collections/[handle]\` — Collection grid with filters (price, vendor, type)
- \`/products/[handle]\` — Product detail with variant picker, qty, gallery
- \`/cart\` — Cart drawer + standalone page
- \`/pages/[handle]\` — CMS pages (about, FAQ, policy)

## State & data

- Cart state lives in \`zustand\`, persisted to \`localStorage\` (\`sq_cart_v1\`).
- Product data comes from \`/api/storefront/products\` (typed via \`shared/types\`).
- Use \`useSWR\` for fetching; never call \`fetch\` directly in components.

## Multi-tenant rules

- \`storeDomain\` is read from \`headers.x-sq-store\` server-side.
- Never hard-code a domain. Theme tokens resolve from \`store.theme_tokens\`.

## Hooks

Common denials: \`block_inline_styles\`, \`enforce_tailwind_tokens\`,
\`block_dangerous_html\`. Fix by moving to utility classes and sanitizing server-side.`;

// v5 draft = v4 + checkout route + Stripe section
const STORE_V5 = STORE_V4
  .replace("- `/pages/[handle]` — CMS pages (about, FAQ, policy)",
    "- `/checkout` — Lightweight wrapper around Stripe Checkout\n- `/pages/[handle]` — CMS pages (about, FAQ, policy)")
  .replace("## Hooks",
    "## Checkout\n\n- Never collect card data directly. Redirect to Stripe Checkout via\n  `/api/checkout/session`. Read the publishable key from server context.\n- On return, verify the session server-side before showing confirmation.\n\n## Hooks");
const STORE_V3 = STORE_V4.replace("## Multi-tenant rules\n\n- `storeDomain` is read from `headers.x-sq-store` server-side.\n- Never hard-code a domain. Theme tokens resolve from `store.theme_tokens`.\n\n", "");
const STORE_V2 = STORE_V3.replace("- Use `useSWR` for fetching; never call `fetch` directly in components.\n", "");
const STORE_V1 = STORE_V2.replace(/## Hooks[\s\S]*$/, "## Hooks\n\nRespect platform hooks. Fix denials before retrying.");

const AUTHORS = ['huy', 'phong', 'mai', 'huy', 'phong'];
const LP_NOTES = {
  8: 'Add performance budget; allow Collection strip; tighten arbitrary-value rule after FP loop spike',
  7: 'Tighten Tailwind token enforcement + add accessibility principle',
  6: 'Add Social Proof to allowed sections; structured forbidden list',
  5: 'Initial structured rewrite from freeform prompt',
};
const STORE_NOTES = {
  5: 'Add /checkout Stripe wrapper + checkout safety rules',
  4: 'Add multi-tenant domain resolution rules',
  3: 'Expand pages list with CMS routes',
  2: 'Add zustand cart state + SWR fetching rule',
  1: 'Initial store agent prompt',
};

function mkVersions(agent, defs) {
  // defs: [{ v, status, content }] newest-first
  return defs.map((d, i) => {
    const created = Date.now() - (i * ri(4, 12) + ri(0, 3)) * day - ri(0, day);
    const notes = agent === 'landing_page' ? LP_NOTES : STORE_NOTES;
    const sessions = d.status === 'active' ? ri(900, 2400) : d.status === 'draft' ? 0 : ri(40, 1400);
    return {
      id: `${agent}_v${d.v}`,
      agent,
      v: d.v,
      status: d.status, // active | draft | archived
      content: d.content,
      author: AUTHORS[i % AUTHORS.length],
      created_at: created,
      note: notes[d.v] || 'Update prompt',
      impact: {
        sessions,
        projects: Math.round(sessions * (0.3 + R() * 0.2)),
        stores: Math.round(sessions * (0.08 + R() * 0.05)),
      },
      cost: {
        avg_tokens: ri(3200, 9800),
        avg_cost_cents: ri(28, 92),
      },
      feedback: { up: 0, down: 0 }, // filled after feedback generated
    };
  });
}

const PROMPT_VERSIONS = {
  landing_page: mkVersions('landing_page', [
    { v: 8, status: 'draft',    content: LP_V8 },
    { v: 7, status: 'active',   content: LP_V7 },
    { v: 6, status: 'archived', content: LP_V6 },
    { v: 5, status: 'archived', content: LP_V5 },
  ]),
  store: mkVersions('store', [
    { v: 5, status: 'draft',    content: STORE_V5 },
    { v: 4, status: 'active',   content: STORE_V4 },
    { v: 3, status: 'archived', content: STORE_V3 },
    { v: 2, status: 'archived', content: STORE_V2 },
    { v: 1, status: 'archived', content: STORE_V1 },
  ]),
};

const AGENT_META = {
  landing_page: { name: 'landing_page', title: 'Landing Page Agent', icon: 'globe', file: 'prompts/agents/landing_page.md' },
  store:        { name: 'store',        title: 'Store Agent',        icon: 'package', file: 'prompts/agents/store.md' },
};

// ─── Feedback ──────────────────────────────────────────────────────────────
const FB_TAGS = ['format', 'tone', 'hallucination', 'accuracy', 'verbosity', 'a11y', 'tokens'];
const FB_REASONS_DOWN = [
  'Used arbitrary Tailwind value instead of design token',
  'Hero copy too verbose, ignored "concise" brief',
  'Missing alt text on product images',
  'Invented a product feature not in the brief',
  'Inline style slipped through, got hook-denied 5×',
  'Footer layout shifted on load (no width/height)',
  'Tone too formal for a playful brand',
  'Generated a Newsletter section that was not requested',
  'Cart state lost on refresh — localStorage key wrong',
  'Checkout redirect used client-side key',
];
const FB_REASONS_UP = [
  'Clean token usage, zero hook denials',
  'Hero nailed the brand voice on first try',
  'Great accessibility — all images labelled',
  'Concise, on-brief copy',
  'Collection filters worked perfectly',
  'Fast — under 8 min, low token count',
  'Variant picker logic was correct',
  'Followed the section order exactly',
];

function mkFeedback() {
  const out = [];
  const SESS = window.SESSIONS || [];
  let id = 1;
  for (const agent of ['landing_page', 'store']) {
    const versions = PROMPT_VERSIONS[agent];
    for (const ver of versions) {
      if (ver.status === 'draft') continue;
      // active version gets more feedback
      const n = ver.status === 'active' ? ri(22, 34) : ri(4, 14);
      for (let i = 0; i < n; i++) {
        const up = R() < (ver.v >= 7 || (agent === 'store' && ver.v >= 4) ? 0.78 : 0.58);
        const sess = SESS.length ? pick(SESS) : null;
        out.push({
          id: 'fb-' + (id++),
          agent,
          version_id: ver.id,
          v: ver.v,
          rating: up ? 'up' : 'down',
          reason: up ? pick(FB_REASONS_UP) : pick(FB_REASONS_DOWN),
          tags: up ? [] : (R() < 0.8 ? [pick(FB_TAGS)] : [pick(FB_TAGS), pick(FB_TAGS)]),
          session_id: sess ? sess.id : null,
          merchant: sess ? sess.merchant : 'unknown@merchant.io',
          created_at: ver.created_at + ri(1, 20) * 3600000 + i * 1800000,
        });
      }
    }
  }
  // tally onto versions
  for (const agent of ['landing_page', 'store']) {
    for (const ver of PROMPT_VERSIONS[agent]) {
      const items = out.filter(f => f.version_id === ver.id);
      ver.feedback = { up: items.filter(f => f.rating === 'up').length, down: items.filter(f => f.rating === 'down').length };
    }
  }
  return out.sort((a, b) => b.created_at - a.created_at);
}
const PROMPT_FEEDBACK = mkFeedback();

// ─── Skills (base + composition) ───────────────────────────────────────────
const PROMPT_SKILLS = {
  landing_page: [
    { id: 'sk-lp-clone',    name: 'clone-from-url',  type: 'clone',    enabled: true,  desc: 'Reconstruct a reference site layout from a URL screenshot.', tokens: 1840 },
    { id: 'sk-lp-brief',    name: 'brief-expander',  type: 'brief',    enabled: true,  desc: 'Turn a 1-line brief into a full section plan.',            tokens: 920 },
    { id: 'sk-lp-localize', name: 'localize-vi',     type: 'localize', enabled: false, desc: 'Generate Vietnamese copy variants for VN merchants.',       tokens: 1240 },
    { id: 'sk-lp-seo',      name: 'seo-meta',        type: 'brief',    enabled: true,  desc: 'Add OpenGraph + meta description from product data.',       tokens: 640 },
  ],
  store: [
    { id: 'sk-st-clone',    name: 'clone-shopify',   type: 'clone',    enabled: true,  desc: 'Map a Shopify theme structure to SQ components.',           tokens: 2480 },
    { id: 'sk-st-transfer', name: 'transfer-catalog',type: 'transfer', enabled: true,  desc: 'Import product catalog + collections from a source store.', tokens: 2100 },
    { id: 'sk-st-localize', name: 'localize-vi',     type: 'localize', enabled: false, desc: 'Localize storefront copy + currency to VND.',               tokens: 1320 },
    { id: 'sk-st-brief',    name: 'brief-expander',  type: 'brief',    enabled: false, desc: 'Expand a store brief into a page/route plan.',              tokens: 980 },
  ],
};
// per-store skill overrides (a couple of examples)
const SKILL_STORE_OVERRIDES = [
  { store: 'Bloom Cosmetics Vietnam', agent: 'landing_page', skill: 'localize-vi', enabled: true },
  { store: 'TryBlossom', agent: 'store', skill: 'transfer-catalog', enabled: false },
  { store: 'Saigon Spice', agent: 'store', skill: 'localize-vi', enabled: true },
];

// ─── Audit log ─────────────────────────────────────────────────────────────
const AUDIT = [
  { ts: Date.now() - 2 * 3600000,   actor: 'huy',   action: 'created',   target: 'landing_page v8', note: 'draft from refine', kind: 'create' },
  { ts: Date.now() - 5 * 3600000,   actor: 'phong', action: 'cleared cache', target: 'landing_page', note: 'after v7 hotfix', kind: 'cache' },
  { ts: Date.now() - 28 * 3600000,  actor: 'mai',   action: 'activated', target: 'store v4', note: 'multi-tenant rules live', kind: 'activate' },
  { ts: Date.now() - 30 * 3600000,  actor: 'mai',   action: 'created',   target: 'store v4', note: 'multi-tenant domain rules', kind: 'create' },
  { ts: Date.now() - 4 * day,       actor: 'huy',   action: 'activated', target: 'landing_page v7', note: 'token enforcement', kind: 'activate' },
  { ts: Date.now() - 4 * day - 3600000, actor: 'huy', action: 'rolled back', target: 'landing_page v6 → v5', note: 'v6 regressed a11y', kind: 'rollback' },
  { ts: Date.now() - 6 * day,       actor: 'phong', action: 'archived',  target: 'landing_page v5', note: 'superseded', kind: 'archive' },
  { ts: Date.now() - 9 * day,       actor: 'mai',   action: 'created',   target: 'store v3', note: 'CMS routes', kind: 'create' },
];

// ─── Cache status ──────────────────────────────────────────────────────────
const CACHE = [
  { key: 'prompt:landing_page:active', version: 'landing_page v7', ttl: '∞ (active)', size_kb: 1.8, hits_24h: 2143, status: 'fresh' },
  { key: 'prompt:store:active',        version: 'store v4',        ttl: '∞ (active)', size_kb: 1.6, hits_24h: 1872, status: 'fresh' },
  { key: 'prompt:landing_page:v6',     version: 'landing_page v6', ttl: '4m 12s',     size_kb: 1.5, hits_24h: 12,   status: 'stale' },
  { key: 'skill:clone-shopify',        version: 'store · clone',   ttl: '18m 40s',    size_kb: 2.4, hits_24h: 308,  status: 'fresh' },
];

// ─── Generator presets (canned "AI" output) ───────────────────────────────
const GEN_MODELS = [
  { id: 'sonnet-4.5', name: 'claude-sonnet-4-5', note: 'balanced · default' },
  { id: 'opus-4',     name: 'claude-opus-4',     note: 'highest quality · slow · $$$' },
  { id: 'haiku-4.5',  name: 'claude-haiku-4-5',  note: 'fast · cheap · short prompts' },
];

// Produce a plausible generated prompt from a description
function generatePrompt(agent, description, variantSeed = 0) {
  const title = AGENT_META[agent].title;
  const flavor = [
    '- Keep copy concise and skimmable; lead with the value proposition.',
    '- Favor a single strong CTA above the fold over multiple competing buttons.',
    '- Use real product data; never invent SKUs, prices, or reviews.',
  ];
  const v = flavor[variantSeed % flavor.length];
  const desc = (description || 'Build conversion-focused pages that match the brand.').trim();
  return `# ${title} — generated draft

You are the **${title}** for ShopQuantum.

## Goal

${desc}

## Operating principles

1. **Use the Tailwind design system.** No arbitrary values — propose tokens.
2. **Match the brief's tone** in copy weight and imagery.
3. **Accessibility first.** Alt text on all media; semantic buttons and headings.
${v}

## Forbidden

- Inline \`style={{}}\`, \`dangerouslySetInnerHTML\`, \`console.log\`, external \`fetch()\`.

## Output

Write to \`src/components/\` and the page entry; reuse shared components.`;
}

// ─── LCS line diff ─────────────────────────────────────────────────────────
function lineDiff(aText, bText) {
  const a = (aText || '').split('\n'), b = (bText || '').split('\n');
  const m = a.length, n = b.length;
  const dp = Array.from({ length: m + 1 }, () => new Int32Array(n + 1));
  for (let i = m - 1; i >= 0; i--)
    for (let j = n - 1; j >= 0; j--)
      dp[i][j] = a[i] === b[j] ? dp[i + 1][j + 1] + 1 : Math.max(dp[i + 1][j], dp[i][j + 1]);
  const out = [];
  let i = 0, j = 0, la = 1, lb = 1;
  while (i < m && j < n) {
    if (a[i] === b[j]) { out.push({ type: 'eq', text: a[i], la: la++, lb: lb++ }); i++; j++; }
    else if (dp[i + 1][j] >= dp[i][j + 1]) { out.push({ type: 'del', text: a[i], la: la++, lb: null }); i++; }
    else { out.push({ type: 'add', text: b[j], la: null, lb: lb++ }); j++; }
  }
  while (i < m) { out.push({ type: 'del', text: a[i], la: la++, lb: null }); i++; }
  while (j < n) { out.push({ type: 'add', text: b[j], la: null, lb: lb++ }); j++; }
  return out;
}

Object.assign(window, {
  PROMPT_VERSIONS, AGENT_META, PROMPT_FEEDBACK, PROMPT_SKILLS, SKILL_STORE_OVERRIDES,
  AUDIT, CACHE, GEN_MODELS, FB_TAGS, generatePrompt, lineDiff,
});
})();
