/* brand-review.jsx — post-scan AI critique of the user's site vs top competitors.
 *
 * Calls Claude with the full discovered brand context + inferred competitors,
 * asks for a structured review covering:
 *   - identity (brand presentation, visual differentiation)
 *   - feature_gaps (what competitors have that user doesn't)
 *   - elements (specific UI/content pieces to add)
 *   - quick_wins (immediate UX improvements)
 *   - bold_moves (one ambitious "2027" idea — generative, spatial, novel)
 *
 * Renders as a layered card stack with depth, glow, and the editorial
 * vocabulary the rest of the prototype uses.
 */

const { useState, useEffect, useRef } = React;

async function runBrandReview(brand, { anthropicKey } = {}) {
  if (!brand?.domain) return null;
  const managed = window.getManagedProviders && window.getManagedProviders();
  const hasAnthropic = !!anthropicKey || managed?.has('anthropic');

  let claude;
  if (hasAnthropic && window.callModel) {
    // managed mode or BYO — callModel ignores the key arg in managed mode
    // Sonnet 4.6 — now that api/llm.js runs on the Node runtime (60s) it no longer hits
    // the edge function's ~25s 504. Full token budget so the JSON doesn't truncate.
    claude = (p) => window.callModel('anthropic', anthropicKey, p, { maxTokens: 3000, model: 'claude-opus-4-7', timeoutMs: 58000 }).then(r => r.text);
  } else if (window.claude?.complete) {
    // sandbox fallback
    claude = (p) => window.claude.complete(p);
  } else {
    return null;
  }

  // If the live site couldn't be read (blocked / degraded discovery), the scan signals
  // are absence-of-DATA, not absence-of-FEATURE — feeding has_og_image:false etc. makes
  // the review fabricate "missing og:image / JSON-LD / social" as if they were facts.
  const blind = !!brand.degraded;
  const summary = {
    name: brand.name, domain: brand.domain, industry: brand.industry,
    location: brand.location, tagline: brand.tagline, description: brand.description,
    audience: brand.audience, vertical: brand.vertical,
    competitors: (brand.competitors || []).slice(0, 10).map(c => c.name || c),
    site_readable: !blind,
    // Only include scan-derived technical signals when we actually read the site.
    ...(blind ? {} : {
      has_jsonld: (brand.jsonld?.types?.length || 0) > 0,
      has_og_image: !!brand.meta?.ogImage,
      has_address: !!brand.address,
      sitemap_urls: brand.sitemap?.urls || 0,
      social_count: Object.keys(brand.social || {}).length,
    }),
  };

  const blindNote = blind
    ? `\nIMPORTANT: the live site could NOT be read (it blocked automated fetching), so there are NO reliable technical signals. Do NOT claim the site is missing og:image, JSON-LD, sitemap, social links, or that it is "degraded" — those are UNKNOWN, not absent. Base identity and feature-gap commentary ONLY on your training knowledge of ${brand.name} vs its competitors, and open the thesis with a one-line caveat that the live site couldn't be scanned.\n`
    : '';

  const prompt = `You are a senior product designer doing a post-audit creative review.

Brand context (${blind ? 'the live site could NOT be read — signals are limited to what is known' : 'real, from a recent scan'}):
\`\`\`json
${JSON.stringify(summary, null, 2)}
\`\`\`
${blindNote}

Compare ${brand.name} against the listed competitors using your training knowledge. Be specific, opinionated, and concrete — not generic. Reference real things competitors actually do where you can.

Return ONLY a JSON object (no markdown):

{
  "thesis": "One-sentence diagnosis of where this brand sits vs the competitive set",
  "identity": {
    "verdict": "<=15 words on visual / brand identity gap vs competitors",
    "observations": ["3-4 specific observations about logo, OG, palette, tone"]
  },
  "feature_gaps": [
    {"feature": "Specific feature", "competitors_with_it": ["Comp A", "Comp B"], "why_it_matters": "1 sentence"},
    ... (3-5 items)
  ],
  "elements": [
    {"element": "Specific UI/content element (e.g. 'Bento-grid case study wall')", "where": "page section", "why": "1 sentence"},
    ... (4-6 items, lean toward novel 2027 patterns: spatial, layered, generative, conversational, no-form, etc.)
  ],
  "quick_wins": [
    {"win": "Action verb + object", "effort": "low|medium", "impact": "low|medium|high"},
    ... (4-6 items, immediately shippable)
  ],
  "bold_move": {
    "title": "One ambitious 2027-shaped idea",
    "description": "2-3 sentences. Should feel like a near-future product moment, not a buzzword salad.",
    "inspiration": ["1-2 reference points from real products that hint at this direction"]
  }
}

Tone: confident, plain-spoken, no marketing fluff. Treat the reader as someone who already knows the basics.`;

  try {
    const text = await Promise.race([
      claude(prompt),
      new Promise((_, r) => setTimeout(() => r(new Error('review timeout')), 58000)),
    ]);
    const m = text.match(/(\{[\s\S]*\})/);
    if (!m) return null;
    const cleaned = m[1].replace(/,(\s*[}\]])/g, '$1');
    return JSON.parse(cleaned);
  } catch (e) {
    return { error: e.message || 'review failed' };
  }
}

function BrandReview({ brand, anthropicKey, onSettings }) {
  const [state, setState] = useState({ loading: true, review: null, error: null });
  const lastBrandRef = useRef(null);

  useEffect(() => {
    if (!brand?.domain) return;
    if (lastBrandRef.current === brand.domain + (brand.discoveredAt || '')) return;
    lastBrandRef.current = brand.domain + (brand.discoveredAt || '');

    setState({ loading: true, review: null, error: null });
    let cancelled = false;
    (async () => {
      const review = await runBrandReview(brand, { anthropicKey });
      if (cancelled) return;
      if (!review || review.error) {
        setState({
          loading: false, review: null,
          error: review?.error || 'Creative review is temporarily unavailable — try re-running the scan.',
        });
      } else {
        setState({ loading: false, review, error: null });
      }
    })();
    return () => { cancelled = true; };
  }, [brand?.domain, brand?.discoveredAt, anthropicKey]);

  if (state.loading) {
    return (
      <div className="br-section">
        <div className="br-head">
          <div className="eyebrow"><span className="pulse" /> Generating creative review…</div>
          <h3>Reviewing {brand?.name || 'your brand'} against {(brand?.competitors || []).slice(0, 5).map(c => c.name || c).join(' · ') || 'the top 5'}</h3>
        </div>
        <div className="br-skeleton">
          <div className="br-card-skel" style={{ animationDelay: '0ms' }} />
          <div className="br-card-skel" style={{ animationDelay: '120ms' }} />
          <div className="br-card-skel" style={{ animationDelay: '240ms' }} />
          <div className="br-card-skel" style={{ animationDelay: '360ms' }} />
        </div>
      </div>
    );
  }

  if (state.error) {
    return (
      <div className="br-section br-error">
        <div className="br-head">
          <div className="eyebrow"><span className="db-dot warn-pulse" /> Review unavailable</div>
          <h3>{state.error}</h3>
        </div>
      </div>
    );
  }

  const r = state.review;
  if (!r) return null;

  return (
    <div className="br-section">
      <div className="br-head">
        <div className="eyebrow">
          <span className="db-dot live-pulse" /> Creative review · Claude Opus 4.7 · {(brand.competitors || []).length} competitors considered
        </div>
        <h3 className="br-thesis"><span className="br-quote">“</span>{r.thesis}<span className="br-quote">”</span></h3>
      </div>

      <div className="br-stack">
        {/* IDENTITY */}
        {r.identity && (
          <article className="br-card br-card-identity">
            <div className="br-card-num">01</div>
            <div className="br-card-tag">Identity</div>
            <h4>{r.identity.verdict}</h4>
            <ul className="br-list">
              {(r.identity.observations || []).map((o, i) => (
                <li key={i}>{o}</li>
              ))}
            </ul>
            <div className="br-card-edge" />
          </article>
        )}

        {/* FEATURE GAPS */}
        {(r.feature_gaps || []).length > 0 && (
          <article className="br-card br-card-gaps">
            <div className="br-card-num">02</div>
            <div className="br-card-tag">Feature gaps</div>
            <h4>What top competitors have that {brand.name} doesn't.</h4>
            <div className="br-gaps">
              {r.feature_gaps.map((g, i) => (
                <div key={i} className="br-gap">
                  <div className="br-gap-name">{g.feature}</div>
                  <div className="br-gap-why">{g.why_it_matters}</div>
                  {g.competitors_with_it && g.competitors_with_it.length > 0 && (
                    <div className="br-gap-who">
                      {g.competitors_with_it.map((c, j) => (
                        <span key={j} className="br-gap-tag">{c}</span>
                      ))}
                    </div>
                  )}
                </div>
              ))}
            </div>
            <div className="br-card-edge" />
          </article>
        )}

        {/* ELEMENTS */}
        {(r.elements || []).length > 0 && (
          <article className="br-card br-card-elements">
            <div className="br-card-num">03</div>
            <div className="br-card-tag">Elements to add</div>
            <h4>Specific page elements that would lift your story.</h4>
            <div className="br-elements">
              {r.elements.map((e, i) => (
                <div key={i} className="br-element">
                  <div className="br-element-icon">·</div>
                  <div className="br-element-body">
                    <div className="br-element-name">{e.element}</div>
                    {e.where && <div className="br-element-where">on {e.where}</div>}
                    {e.why && <div className="br-element-why">{e.why}</div>}
                  </div>
                </div>
              ))}
            </div>
            <div className="br-card-edge" />
          </article>
        )}

        {/* QUICK WINS */}
        {(r.quick_wins || []).length > 0 && (
          <article className="br-card br-card-wins">
            <div className="br-card-num">04</div>
            <div className="br-card-tag">Quick wins</div>
            <h4>Ship this week. Nothing fancy required.</h4>
            <ol className="br-wins">
              {r.quick_wins.map((w, i) => (
                <li key={i}>
                  <span className="br-win-text">{w.win}</span>
                  <span className="br-win-meta">
                    <span className={`br-pill effort-${w.effort}`}>{w.effort}</span>
                    <span className={`br-pill impact-${w.impact}`}>{w.impact} impact</span>
                  </span>
                </li>
              ))}
            </ol>
            <div className="br-card-edge" />
          </article>
        )}

        {/* BOLD MOVE */}
        {r.bold_move && (
          <article className="br-card br-card-bold">
            <div className="br-card-num">05</div>
            <div className="br-card-tag">The bold move</div>
            <h4 className="br-bold-title">{r.bold_move.title}</h4>
            <p className="br-bold-desc">{r.bold_move.description}</p>
            {r.bold_move.inspiration && r.bold_move.inspiration.length > 0 && (
              <div className="br-inspiration">
                <span className="br-inspiration-label">In the lineage of</span>
                <div className="br-inspiration-list">
                  {r.bold_move.inspiration.map((s, i) => <span key={i} className="br-insp-tag">{s}</span>)}
                </div>
              </div>
            )}
            <div className="br-card-edge br-edge-bright" />
          </article>
        )}
      </div>
    </div>
  );
}

Object.assign(window, { BrandReview, runBrandReview });
