// ---- Identity tab: list of created identities + create wizard ----

class IdentityErrorBoundary extends React.Component {
  constructor(props) { super(props); this.state = { failed: false }; }
  static getDerivedStateFromError() { return { failed: true }; }
  componentDidCatch(err) { try { console.error('Identity render error:', err); } catch (e) {} }
  render() {
    if (this.state.failed) {
      return (
        <div className="view">
          <div className="empty">
            <div className="empty-glyph">✸</div>
            <p>Something went wrong displaying this identity. Try going back and opening it again, or create a new one.</p>
            {this.props.onReset ? <button className="btn-primary" onClick={this.props.onReset}>Back to identities</button> : null}
          </div>
        </div>
      );
    }
    return this.props.children;
  }
}

const GEN_STEPS = [
  'Analyzing brand name…',
  'Selecting a color palette…',
  'Pairing typography…',
  'Designing the logo system…',
  'Composing social templates…',
  'Laying out stationery & merch…',
  'Assembling your brand guide…',
];

function IdentityCard({ brand, onOpen, onDelete }) {
  return (
    <div className="idn-card" onClick={onOpen}>
      <div className="idn-card-preview" style={{ background: brand.paper }}>
        <div className="idn-logo"><BrandLogo brand={brand} size={56} kind="mark" /></div>
        <div className="idn-swatches">
          {[brand.primary, brand.secondary, brand.accent, brand.ink].map((c, i) => (
            <span key={i} style={{ background: c }}></span>
          ))}
        </div>
      </div>
      <div className="idn-card-body">
        <div className="idn-card-name">{brand.businessName}</div>
        <div className="idn-card-meta">{brand.vibe}</div>
      </div>
      <button className="idn-card-del" title="Delete" onClick={(e) => { e.stopPropagation(); onDelete(brand.id); }}>×</button>
    </div>
  );
}

function DomainPick({ favs, selected, onSelect }) {
  if (!favs.length) {
    return (
      <div className="empty">
        <div className="empty-glyph">♡</div>
        <p>You don't have any favorite domains yet. Save a domain from search (tap the heart) to build its identity.</p>
      </div>
    );
  }
  return (
    <div className="pick-grid">
      {favs.map(d => {
        const base = d.display.slice(0, d.display.length - d.ext.length);
        const on = selected && selected.id === d.id;
        return (
          <button key={d.id} className={'pick-card' + (on ? ' pick-on' : '')} onClick={() => onSelect(d)}>
            <span className="pick-name">{base}<span className="domain-ext">{d.ext}</span></span>
            <span className="pick-check" aria-hidden="true">{on ? '✓' : ''}</span>
          </button>
        );
      })}
    </div>
  );
}

function IntakeStep({ domain, loading, questions, answers, notes, onToggle, onNote, onBack, onStart }) {
  if (loading) {
    return (
      <div className="gen-stage">
        <div className="gen-orb"><span className="gen-orb-core"></span></div>
        <div className="gen-title">Reviewing your brief…</div>
        <p className="view-sub">Your designer is preparing a few quick questions about {domain ? titleCaseWords(domain.name) : 'your brand'}.</p>
      </div>
    );
  }
  return (
    <React.Fragment>
      <h1 className="view-title">A few design choices</h1>
      <p className="view-sub">Your designer asked a few questions about <strong>{domain ? titleCaseWords(domain.name) : 'this brand'}</strong>. Pick what feels right and add any detail — it all goes into the brief.</p>
      <div className="intake-list">
        {questions.map((q, qi) => (
          <div key={q.id} className="intake-q">
            <div className="intake-q-head">
              <span className="intake-q-num">{String(qi + 1).padStart(2, '0')}</span>
              <span className="intake-label">{q.label}</span>
              {q.multi ? <span className="intake-hint">pick any</span> : null}
            </div>
            <div className="intake-opts">
              {q.options.map(opt => {
                const sel = (answers[q.id] || []).indexOf(opt) >= 0;
                return (
                  <button key={opt} type="button"
                    className={'intake-chip' + (sel ? ' on' : '')}
                    onClick={() => onToggle(q, opt)}>
                    <span className="intake-tick" aria-hidden="true">{sel ? '✓' : '+'}</span>{opt}
                  </button>
                );
              })}
            </div>
            <input className="intake-note" type="text" maxLength={160}
              placeholder="Add more detail (optional)…"
              value={notes[q.id] || ''}
              onChange={(e) => onNote(q.id, e.target.value)} />
          </div>
        ))}
      </div>
      <div className="wiz-actions">
        <button className="btn-ghost" onClick={onBack}>Back</button>
        <button className="btn-primary" onClick={onStart}>Start designing</button>
      </div>
    </React.Fragment>
  );
}

function CreateWizard({ favs, seedDomain, onCancel, onDone, identityCost, canAffordIdentity, creditsLeft, onReserveIdentity, onIdentityCharged, onUpgrade }) {
  const [step, setStep] = React.useState(1);
  const initDomain = seedDomain || (favs && favs.length === 1 ? favs[0] : null);
  const [domain, setDomain] = React.useState(initDomain);
  // The brand brief starts empty. A domain's original SEARCH query (e.g. "I'm
  // looking for a domain idea for a business that…") is a request to the name
  // generator, not a usable brand description — and several domains saved from
  // one search all carry that same query, so prefilling from it made every
  // brand show the same brief. The user writes a real description per brand.
  const [desc, setDesc] = React.useState('');
  const editDesc = (v) => setDesc(v);
  // Switching domains in the picker (or relaunching the wizard for a different
  // favorite) starts that brand from a clean brief, so one brand's description
  // never carries over to another. Keyed on the domain id so re-renders that
  // keep the same domain don't wipe what the user is typing.
  const domainId = domain && domain.id;
  React.useEffect(() => {
    setDesc('');
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [domainId]);
  const [loadingQ, setLoadingQ] = React.useState(false);
  const [questions, setQuestions] = React.useState([]);
  const [answers, setAnswers] = React.useState({});
  const [notes, setNotes] = React.useState({});
  const [genIdx, setGenIdx] = React.useState(0);
  const [genErr, setGenErr] = React.useState(null);
  const [attempt, setAttempt] = React.useState(0);

  // Step 2 = AI intake questions. Fetch tailored questions; if none come back
  // (model unavailable / failure) skip straight to generation so the user is
  // never blocked. intakeRun guards against a stale fetch resolving after the
  // user navigated back/cancelled or restarted the intake.
  const intakeRun = React.useRef(0);
  const goToIntake = () => {
    const run = ++intakeRun.current;
    setStep(3);
    setLoadingQ(true);
    setQuestions([]);
    setAnswers({});
    setNotes({});
    (async () => {
      const qs = await fetchIdentityQuestions(domain, desc);
      if (intakeRun.current !== run) return;
      setLoadingQ(false);
      if (!qs.length) { setStep(4); return; }
      setQuestions(qs);
    })();
  };

  const toggleAnswer = (q, opt) => {
    setAnswers(prev => {
      const cur = prev[q.id] || [];
      let next;
      if (q.multi) {
        next = cur.indexOf(opt) >= 0 ? cur.filter(o => o !== opt) : cur.concat(opt);
      } else {
        next = cur.indexOf(opt) >= 0 ? [] : [opt];
      }
      return Object.assign({}, prev, { [q.id]: next });
    });
  };

  const setNote = (id, val) => setNotes(prev => Object.assign({}, prev, { [id]: val }));

  // Fold selected options + the user's free-text note into one answer per
  // question; questions answered ONLY via the note are included too.
  const buildAnswers = () => questions
    .map(q => {
      const sel = answers[q.id] || [];
      const note = (notes[q.id] || '').trim();
      if (!sel.length && !note) return null;
      let answer = sel.join(', ');
      if (note) answer = answer ? (answer + ' — ' + note) : note;
      if (answer.length > 500) answer = answer.slice(0, 500); // backend caps answer at 500
      return { label: q.label, answer };
    })
    .filter(Boolean);

  React.useEffect(() => {
    if (step !== 4) return;
    let alive = true;
    setGenErr(null);
    setGenIdx(0);
    // We charge for an identity ONLY once generation succeeds, never up front.
    // Generation takes several seconds, but the credit sync persists any spend
    // to the (authoritative) server after ~500ms and the server never accepts
    // refunds — so an up-front reservation could not be reversed if generation
    // then failed or was cancelled. Charging on success keeps the accounting
    // exact: one 800-credit charge per finished identity, nothing on failure or
    // cancel, and a retry after a failure simply charges once when it works.
    if (canAffordIdentity === false) {
      setGenErr("Not enough credits to create this identity. Top up and try again.");
      return;
    }
    let i = 0;
    // Cycle through the steps, then hold on the last one until the designer responds.
    const iv = setInterval(() => {
      i += 1;
      if (alive) setGenIdx(Math.min(i, GEN_STEPS.length - 1));
    }, 480);
    (async () => {
      try {
        const brand = await generateIdentity(domain, desc, buildAnswers());
        if (!alive) return;
        clearInterval(iv);
        // Identity is real now — charge the credits and log the spend.
        if (onReserveIdentity) onReserveIdentity();
        if (onIdentityCharged) onIdentityCharged(domain ? domain.display : '');
        setGenIdx(GEN_STEPS.length);
        setTimeout(() => { if (alive) onDone(brand); }, 400);
      } catch (e) {
        if (!alive) return;
        clearInterval(iv);
        setGenErr((e && e.message) || "Couldn't generate this identity. Please try again.");
      }
    })();
    return () => { alive = false; clearInterval(iv); };
  }, [step, attempt]);

  const dotClass = (n) => 'wiz-dot' + (step > n ? ' done' : '') + (step === n ? ' current' : '');

  return (
    <div className="view view-wide">
      <div className="wiz-top">
        <button className="btn-link" onClick={onCancel}>‹ Cancel</button>
        <div className="wiz-steps">
          <span className={dotClass(1)}>{step > 1 ? '✓' : '1'}</span>
          <span className={'wiz-line' + (step > 1 ? ' on' : '')}></span>
          <span className={dotClass(2)}>{step > 2 ? '✓' : '2'}</span>
          <span className={'wiz-line' + (step > 2 ? ' on' : '')}></span>
          <span className={dotClass(3)}>{step > 3 ? '✓' : '3'}</span>
          <span className={'wiz-line' + (step > 3 ? ' on' : '')}></span>
          <span className={dotClass(4)}>4</span>
        </div>
      </div>

      {step === 1 ? (
        <React.Fragment>
          <h1 className="view-title">Choose a domain</h1>
          <p className="view-sub">Pick one of your favorite domains — its name becomes the brand.</p>
          <DomainPick favs={favs} selected={domain} onSelect={(d) => setDomain(d)} />
          <div className="wiz-actions">
            <button className="btn-primary" disabled={!domain} onClick={() => setStep(2)}>Continue</button>
          </div>
        </React.Fragment>
      ) : null}

      {step === 2 ? (
        <React.Fragment>
          <h1 className="view-title">Describe the brand</h1>
          <p className="view-sub">Tell us what <strong>{domain ? titleCaseWords(domain.name) : 'this brand'}</strong> is about — the more specific, the better the identity.</p>
          <div className="prompt-card">
            <textarea className="prompt-input" rows={4}
              placeholder="e.g. A specialty coffee subscription for people who work from home. Warm, friendly, a little playful. Sustainability matters."
              value={desc} onChange={(e) => editDesc(e.target.value)} autoFocus></textarea>
          </div>
          <div className="wiz-examples">
            {['Modern fintech for freelancers', 'Organic skincare, minimal and calm', 'Indie game studio, bold and fun'].map(ex => (
              <button key={ex} className="chip" onClick={() => editDesc(ex)}>{ex}</button>
            ))}
          </div>
          <div className="idn-cost-note">
            <span className="credit-coin" aria-hidden="true"></span>
            {canAffordIdentity
              ? <span>Creating this identity uses <strong>{identityCost} credits</strong>{Number.isFinite(creditsLeft) ? ' — ' + creditsLeft.toLocaleString() + ' left' : ''}.</span>
              : <span>This identity needs <strong>{identityCost} credits</strong>{Number.isFinite(creditsLeft) ? ', but you only have ' + creditsLeft.toLocaleString() : ''}. Top up to continue.</span>}
          </div>
          <div className="wiz-actions">
            <button className="btn-ghost" onClick={() => setStep(1)}>Back</button>
            {canAffordIdentity
              ? <button className="btn-primary" disabled={!desc.trim()} onClick={goToIntake}>Continue</button>
              : <button className="btn-primary" onClick={() => onUpgrade && onUpgrade()}>Top up credits</button>}
          </div>
        </React.Fragment>
      ) : null}

      {step === 3 ? (
        <IntakeStep domain={domain} loading={loadingQ} questions={questions}
          answers={answers} notes={notes} onToggle={toggleAnswer} onNote={setNote}
          onBack={() => setStep(2)} onStart={() => setStep(4)} />
      ) : null}

      {step === 4 ? (
        genErr ? (
          <div className="gen-stage">
            <div className="gen-fail" aria-hidden="true">!</div>
            <div className="gen-title">Couldn't finish your brand</div>
            <p className="view-sub gen-fail-msg">{genErr}</p>
            <div className="wiz-actions wiz-actions-center">
              <button className="btn-ghost" onClick={() => setStep(1)}>Edit brief</button>
              <button className="btn-primary" onClick={() => setAttempt(a => a + 1)}>Try again</button>
            </div>
          </div>
        ) : (
          <div className="gen-stage">
            <div className="gen-orb"><span className="gen-orb-core"></span></div>
            <div className="gen-title">Designing {domain ? titleCaseWords(domain.name) : 'your brand'}…</div>
            <div className="gen-steps">
              {GEN_STEPS.map((s, i) => (
                <div key={i} className={'gen-step' + (i < genIdx ? ' done' : '') + (i === genIdx ? ' active' : '')}>
                  <span className="gen-mark">{i < genIdx ? '✓' : (i === genIdx ? '' : '')}</span>{s}
                </div>
              ))}
            </div>
          </div>
        )
      ) : null}
    </div>
  );
}

function IdentityView({ hasIdentity, onUpgrade, favs, seedDomain, onConsumeSeed, identityCost, canAffordIdentity, creditsLeft, onReserveIdentity, onIdentityCharged }) {
  const [identities, setIdentities] = React.useState(() => loadIdentities());
  const [mode, setMode] = React.useState('list'); // list | wizard | board
  const [activeBrand, setActiveBrand] = React.useState(null);

  const persist = (next) => {
    setIdentities(next);
    localStorage.setItem('domino-identities', JSON.stringify(next));
    if (window.__onIdentityPersist) window.__onIdentityPersist(next);
  };

  // Re-read identities when the account layer hydrates them from the backend.
  React.useEffect(() => {
    const reload = () => setIdentities(loadIdentities());
    window.addEventListener('namit-identities-updated', reload);
    return () => window.removeEventListener('namit-identities-updated', reload);
  }, []);

  React.useEffect(() => {
    if (seedDomain && hasIdentity) { setMode('wizard'); }
  }, [seedDomain, hasIdentity]);

  if (!hasIdentity) {
    return (
      <div className="view">
        <h1 className="view-title">Identity</h1>
        <p className="view-sub">Generate a complete brand identity from your domain.</p>
        <div className="lock-card">
          <div className="lock-badge">Pro feature</div>
          <div className="lock-glyph" aria-hidden="true">⚿</div>
          <h2 className="lock-title">Create a full brand identity</h2>
          <p className="lock-text">Turn any favorite domain into a complete identity — logo, colors, typography, social templates, stationery and merch — as a downloadable brand guide. Available on the Pro plan.</p>
          <button className="btn-primary" onClick={onUpgrade}>Upgrade to Pro</button>
        </div>
      </div>
    );
  }

  if (mode === 'board' && activeBrand) {
    const back = () => { setActiveBrand(null); setMode('list'); };
    return (
      <IdentityErrorBoundary onReset={back}>
        <BrandBoard brand={activeBrand} onBack={back} />
      </IdentityErrorBoundary>
    );
  }

  if (mode === 'wizard') {
    return (
      <CreateWizard favs={favs} seedDomain={seedDomain}
        identityCost={identityCost} canAffordIdentity={canAffordIdentity} creditsLeft={creditsLeft}
        onReserveIdentity={onReserveIdentity}
        onIdentityCharged={onIdentityCharged} onUpgrade={onUpgrade}
        onCancel={() => { setMode('list'); onConsumeSeed && onConsumeSeed(); }}
        onDone={(raw) => {
          const brand = normalizeBrand(raw);
          const next = [brand, ...identities.filter(b => b.id !== brand.id)];
          persist(next);
          setActiveBrand(brand); setMode('board');
          onConsumeSeed && onConsumeSeed();
        }} />
    );
  }

  // list
  return (
    <div className="view view-wide">
      <div className="idn-head">
        <div>
          <h1 className="view-title">Identity</h1>
          <p className="view-sub">{identities.length ? identities.length + ' brand ' + (identities.length > 1 ? 'identities' : 'identity') + ' created.' : 'Generate a complete brand identity from your domain.'}</p>
        </div>
        <button className="btn-primary idn-create" onClick={() => setMode('wizard')}>+ Create identity</button>
      </div>

      {identities.length === 0 ? (
        <div className="empty idn-empty">
          <div className="empty-glyph">✸</div>
          <p>No identities yet. Create one from a favorite domain — we'll generate logos, colors, type, social templates and a downloadable brand guide.</p>
          <button className="btn-primary" onClick={() => setMode('wizard')}>Create your first identity</button>
        </div>
      ) : (
        <div className="idn-grid">
          {identities.map(b => (
            <IdentityCard key={b.id} brand={b}
              onOpen={() => { setActiveBrand(b); setMode('board'); }}
              onDelete={(id) => persist(identities.filter(x => x.id !== id))} />
          ))}
        </div>
      )}
    </div>
  );
}

Object.assign(window, { IdentityView });
