// ProposeModal.jsx — §9.1.
//
// Title (required) and pitch (required textarea), with a slug field
// that auto-fills from the title via the same deterministic kebab-case
// the backend uses. Tags are chip-input (free-form), with the §9.1
// Slice 2 AI-suggested chips (roadmap #27) wired in: as the draft fills
// in, the backend asks Claude Haiku for tags drawn from the corpus's
// existing tag set, surfaced as clickable suggestion chips. The assist
// is best-effort — it stays silent when unavailable.
//
// The submit button drives the §17 POST /api/rfcs/propose endpoint;
// success navigates the proposer to the pending-idea view per §9.3.

import { useEffect, useRef, useState } from 'react'
import { proposeRFC, suggestTags, getCollection } from '../api'
import { EVENTS, track } from '../lib/analytics'

// How long the draft must sit unchanged before we ask for suggestions —
// long enough to fire on typing pauses / field-blur, not on every
// keystroke (the backend is also per-user rate-limited as a backstop).
const SUGGEST_DEBOUNCE_MS = 700

function slugify(title) {
  return title
    .toLowerCase()
    .trim()
    .replace(/[^a-z0-9]+/g, '-')
    .replace(/^-+|-+$/g, '')
}

export default function ProposeModal({ viewer, onClose, onSubmitted, initialTitle = '', projectId, collectionId }) {
  // #28 Part 2: a "create RFC for '<term>'" affordance pre-fills the title
  // (App passes the `?propose=<term>` value here); the slug derives from it
  // via the same effect that drives manual typing.
  const [title, setTitle] = useState(initialTitle)
  // §22.4a: the type-driven noun for the active collection ("RFC" | "Spec" |
  // "Feature"), read from the API. Defaults to "RFC" until the collection loads.
  const [entryNoun, setEntryNoun] = useState('RFC')
  const [slug, setSlug] = useState('')
  const [slugEdited, setSlugEdited] = useState(false)
  const [pitch, setPitch] = useState('')
  // #26: optional ground-truth use case, sibling to the required pitch.
  const [useCase, setUseCase] = useState('')
  const [tagInput, setTagInput] = useState('')
  const [tags, setTags] = useState([])
  const [submitting, setSubmitting] = useState(false)
  const [error, setError] = useState(null)
  // #27: Claude Haiku tag suggestions. `suggestions` is the latest
  // ranked list from the backend ({ tag, confidence }); we render the
  // subset not already chosen. `suggestedOnce` gates the disclosure +
  // row so they only appear after the assist has actually run.
  const [suggestions, setSuggestions] = useState([])
  const [suggestedOnce, setSuggestedOnce] = useState(false)

  useEffect(() => {
    if (!slugEdited) setSlug(slugify(title))
  }, [title, slugEdited])

  // §22.4a: resolve the active collection's entry noun so the modal chrome
  // names entries per the collection type. Best-effort; falls back to "RFC".
  useEffect(() => {
    if (!projectId || !collectionId) return
    let live = true
    getCollection(projectId, collectionId)
      .then(c => { if (live) setEntryNoun(c?.entry_noun || 'RFC') })
      .catch(() => {})
    return () => { live = false }
  }, [projectId, collectionId])

  // #27: debounced tag-suggestion fetch. Fires after the draft sits
  // unchanged for SUGGEST_DEBOUNCE_MS, only once there's something to go
  // on (a title). A stale-response guard keeps an earlier in-flight
  // request from clobbering a newer one.
  const suggestSeq = useRef(0)
  useEffect(() => {
    if (!title.trim()) {
      setSuggestions([])
      return
    }
    const handle = setTimeout(async () => {
      const seq = ++suggestSeq.current
      const result = await suggestTags({ title, pitch, useCase })
      if (seq !== suggestSeq.current) return // a newer request superseded us
      setSuggestions(Array.isArray(result) ? result : [])
      if (result && result.length) setSuggestedOnce(true)
    }, SUGGEST_DEBOUNCE_MS)
    return () => clearTimeout(handle)
  }, [title, pitch, useCase])

  // Suggestions the user hasn't already added.
  const freshSuggestions = suggestions.filter(s => !tags.includes(s.tag))

  function addTag() {
    const t = tagInput.trim()
    if (t && !tags.includes(t)) setTags([...tags, t])
    setTagInput('')
  }

  function addSuggested(tag) {
    if (!tags.includes(tag)) setTags([...tags, tag])
  }

  async function handleSubmit(e) {
    e.preventDefault()
    if (!title.trim() || !slug || !pitch.trim()) return
    setSubmitting(true)
    setError(null)
    try {
      const result = await proposeRFC(projectId, {
        title: title.trim(),
        slug,
        pitch: pitch.trim(),
        tags,
        proposedUseCase: useCase.trim() || null,
        collectionId,
      })
      // v0.15.0 — analytics: fire on the §9.1 propose-RFC submit.
      // Slug is a stable, low-cardinality identifier (kebab-case
      // ascii); title and pitch stay out of the event body.
      track(EVENTS.RFC_PROPOSED, { rfc_slug: slug })
      onSubmitted?.(result)
    } catch (err) {
      setError(err.message || 'Submission failed.')
    } finally {
      setSubmitting(false)
    }
  }

  return (
    <div className="modal-overlay" onClick={e => { if (e.target === e.currentTarget) onClose() }}>
      <div className="modal">
        <div className="modal-header">
          <h2>Propose a New {entryNoun}</h2>
          <button className="modal-close" onClick={onClose}>×</button>
        </div>
        <form onSubmit={handleSubmit}>
          <div className="modal-body">
            <label htmlFor="propose-title">Title</label>
            <input
              id="propose-title"
              value={title}
              onChange={e => setTitle(e.target.value)}
              placeholder="e.g. Open Human Model"
              autoFocus
              required
            />
            <p className="field-help">The word or topic this {entryNoun} will define.</p>

            <label htmlFor="propose-slug">Slug</label>
            <input
              id="propose-slug"
              value={slug}
              onChange={e => { setSlug(slugify(e.target.value)); setSlugEdited(true) }}
              placeholder="open-human-model"
              required
            />
            <p className="field-help">Auto-derived from the title; edit if needed.</p>

            <label htmlFor="propose-pitch">Why is this {entryNoun} needed?</label>
            <textarea
              id="propose-pitch"
              value={pitch}
              onChange={e => setPitch(e.target.value)}
              placeholder={`One or two paragraphs answering 'why this ${entryNoun} is needed.'`}
              rows={5}
              required
            />

            <label htmlFor="propose-use-case">What will you be using this {entryNoun} for? (optional)</label>
            <textarea
              id="propose-use-case"
              value={useCase}
              onChange={e => setUseCase(e.target.value)}
              placeholder={`The concrete thing you intend to build or do with this ${entryNoun}. Optional, but it helps ground the work.`}
              rows={3}
            />
            <p className="field-help">
              The concrete ground-truth use case — distinct from "why it's
              needed" above. Leave blank if you'd rather not say.
            </p>

            <label htmlFor="propose-tag">Tags (optional)</label>
            <div style={{ display: 'flex', gap: 6, alignItems: 'center', marginBottom: 4 }}>
              <input
                id="propose-tag"
                value={tagInput}
                onChange={e => setTagInput(e.target.value)}
                onKeyDown={e => {
                  if (e.key === 'Enter' || e.key === ',') { e.preventDefault(); addTag() }
                }}
                placeholder="identity, schema"
                style={{ marginBottom: 0 }}
              />
              <button type="button" className="btn-secondary" onClick={addTag} style={{ padding: '6px 12px' }}>
                Add
              </button>
            </div>
            {tags.length > 0 && (
              <div style={{ marginTop: 4, marginBottom: 14 }}>
                {tags.map(t => (
                  <span key={t} className="entry-tag" style={{ display: 'inline-block', marginRight: 4 }}>
                    {t}{' '}
                    <button
                      type="button"
                      onClick={() => setTags(tags.filter(x => x !== t))}
                      style={{ background: 'none', border: 'none', cursor: 'pointer', color: '#999' }}
                    >×</button>
                  </span>
                ))}
              </div>
            )}

            {/* #27: Claude Haiku suggested tags. Clickable chips that add
                to the tag list; nothing auto-applies. The disclosure is
                required — the draft text is sent to Anthropic to generate
                these — so it renders whenever the suggestion row does. */}
            {(freshSuggestions.length > 0 || (suggestedOnce && suggestions.length > 0)) && (
              <div style={{ marginTop: 4, marginBottom: 14 }}>
                {freshSuggestions.length > 0 && (
                  <>
                    <p className="field-help" style={{ marginTop: 0, marginBottom: 4 }}>
                      Suggested tags — click to add:
                    </p>
                    <div>
                      {freshSuggestions.map(s => (
                        <button
                          key={s.tag}
                          type="button"
                          className="entry-tag"
                          onClick={() => addSuggested(s.tag)}
                          title={`Add "${s.tag}"`}
                          style={{
                            display: 'inline-block',
                            marginRight: 4,
                            marginBottom: 4,
                            border: '1px dashed var(--color-border, #ccc)',
                            background: 'none',
                            cursor: 'pointer',
                          }}
                        >+ {s.tag}</button>
                      ))}
                    </div>
                  </>
                )}
                <p className="field-help" style={{ marginTop: 4, marginBottom: 0, fontStyle: 'italic' }}>
                  Suggestions are generated by Claude (Anthropic). The text you've
                  entered above is sent to Anthropic to produce them.
                </p>
              </div>
            )}

            {viewer && (
              <p className="field-help" style={{ marginTop: 14, marginBottom: 0 }}>
                Owner: <strong>{viewer.display_name || viewer.gitea_login}</strong> — you'll be the first owner of this super-draft. Additional owners can claim later (§13.1).
              </p>
            )}

            {error && <p className="field-error">{error}</p>}
          </div>
          <div className="modal-actions">
            <button type="button" className="btn-secondary" onClick={onClose}>Cancel</button>
            <button
              type="submit"
              className="btn-primary"
              disabled={!title.trim() || !slug || !pitch.trim() || submitting}
            >
              {submitting ? 'Opening PR…' : 'Open proposal PR'}
            </button>
          </div>
        </form>
      </div>
    </div>
  )
}
