// frontend/src/pages/NicheBuilder.jsx
import { useState, useEffect } from 'react';
import { useAuth } from '../context/AuthContext.jsx';
import { useT } from '../i18n/translations.js';
import { api } from '../context/AuthContext.jsx';
import { Button, Card, Input, Badge, Spinner, Modal } from '../components/ui/index.jsx';
import toast from 'react-hot-toast';
import {
  Target, Users, Lightbulb, Hash, Plus, X, ChevronRight,
  ChevronLeft, CheckCircle2, Edit3, Trash2, Zap, Star,
  TrendingUp, BarChart2, RefreshCw, Play, AlertCircle
} from 'lucide-react';
import { clsx } from 'clsx';
import { formatDistanceToNow } from 'date-fns';

const INDUSTRIES = [
  'Health & Fitness', 'Business & Entrepreneurship', 'Personal Finance',
  'Technology & Software', 'Marketing & Sales', 'Real Estate',
  'Education & E-learning', 'Food & Cooking', 'Travel & Lifestyle',
  'Arts & Creative', 'Relationships & Dating', 'Spirituality & Mindfulness',
  'Gaming & Entertainment', 'Fashion & Beauty', 'Parenting & Family',
  'Sports & Athletics', 'Self-Improvement', 'Politics & News', 'Other'
];

const PLATFORMS = [
  { id: 'youtube', label: '🎬 YouTube' },
  { id: 'instagram', label: '📸 Instagram' },
  { id: 'x', label: '𝕏 X/Twitter' },
  { id: 'tiktok', label: '🎵 TikTok' },
  { id: 'linkedin', label: '💼 LinkedIn' },
  { id: 'blog', label: '📰 Blog' },
];

const AUDIENCE_LEVELS = ['beginner', 'intermediate', 'expert', 'mixed'];

// ─── MAIN PAGE ────────────────────────────────────────────────────────────
export default function NicheBuilder() {
  const { user } = useAuth();
  const [niches, setNiches] = useState([]);
  const [activeNiche, setActiveNiche] = useState(null);
  const [view, setView] = useState('list'); // list | create | edit | topics
  const [editingNiche, setEditingNiche] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => { fetchNiches(); }, []);

  async function fetchNiches() {
    setLoading(true);
    try {
      const { data } = await api.get('/niche');
      setNiches(data);
      setActiveNiche(data.find(n => n.is_active) || null);
    } catch {}
    setLoading(false);
  }

  async function activateNiche(id) {
    try {
      await api.post(`/niche/${id}/activate`);
      toast.success('Active niche updated');
      fetchNiches();
    } catch { toast.error('Failed to activate'); }
  }

  async function deleteNiche(id) {
    if (!confirm('Delete this niche profile?')) return;
    try {
      await api.delete(`/niche/${id}`);
      toast.success('Deleted');
      fetchNiches();
    } catch { toast.error('Failed to delete'); }
  }

  if (view === 'create' || view === 'edit') {
    return (
      <NicheWizard
        niche={editingNiche}
        onSave={async (data) => {
          try {
            if (editingNiche) await api.put(`/niche/${editingNiche.id}`, data);
            else await api.post('/niche', data);
            toast.success(editingNiche ? 'Niche updated!' : 'Niche created!');
            setView('list');
            setEditingNiche(null);
            fetchNiches();
          } catch (err) {
            toast.error(err.response?.data?.error || 'Save failed');
          }
        }}
        onCancel={() => { setView('list'); setEditingNiche(null); }}
      />
    );
  }

  if (view === 'topics') {
    return (
      <TopicApprovalFlow
        niche={activeNiche}
        onBack={() => setView('list')}
      />
    );
  }

  // ── LIST VIEW ──
  return (
    <div className="space-y-6">
      <div className="flex items-center justify-between">
        <div>
          <h1 className="text-2xl font-semibold text-gray-900">Content Niches</h1>
          <p className="text-sm text-gray-500 mt-0.5">Define your niche precisely — the more specific, the better the content</p>
        </div>
        <Button onClick={() => { setEditingNiche(null); setView('create'); }}>
          <Plus size={16} /> New Niche
        </Button>
      </div>

      {/* Active niche banner */}
      {activeNiche && (
        <Card className="p-5 border-brand-200 bg-gradient-to-r from-brand-50 to-emerald-50">
          <div className="flex items-start justify-between">
            <div className="flex items-start gap-3">
              <div className="w-10 h-10 bg-brand-100 rounded-xl flex items-center justify-center flex-shrink-0">
                <Target size={20} className="text-brand-600" />
              </div>
              <div>
                <div className="flex items-center gap-2">
                  <h2 className="font-semibold text-gray-900">{activeNiche.name}</h2>
                  <Badge variant="success">Active</Badge>
                </div>
                <p className="text-sm text-gray-600 mt-0.5">{activeNiche.sub_niche}</p>
                <div className="flex gap-2 mt-2 flex-wrap">
                  {(activeNiche.platforms || []).map(p => (
                    <span key={p} className="text-xs bg-white border border-brand-200 text-brand-700 px-2 py-0.5 rounded-full">{p}</span>
                  ))}
                </div>
              </div>
            </div>
            <Button onClick={() => setView('topics')} className="flex-shrink-0">
              <Zap size={15} />
              Generate Topics
            </Button>
          </div>
        </Card>
      )}

      {!activeNiche && niches.length > 0 && (
        <Card className="p-4 border-amber-200 bg-amber-50">
          <div className="flex items-center gap-2 text-amber-700">
            <AlertCircle size={16} />
            <p className="text-sm font-medium">No active niche selected. Click "Set active" on one of your niches below.</p>
          </div>
        </Card>
      )}

      {loading ? (
        <div className="flex justify-center py-16"><Spinner size={32} /></div>
      ) : niches.length === 0 ? (
        <Card className="p-16 text-center">
          <Target size={40} className="text-gray-200 mx-auto mb-4" />
          <h3 className="font-semibold text-gray-900 mb-1">No niches yet</h3>
          <p className="text-sm text-gray-400 mb-6">Create your first niche profile to start generating targeted content</p>
          <Button onClick={() => setView('create')}>Create first niche</Button>
        </Card>
      ) : (
        <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
          {niches.map(niche => (
            <Card key={niche.id} className={clsx('p-5 transition-all', niche.is_active && 'ring-2 ring-brand-400')}>
              <div className="flex items-start justify-between mb-3">
                <div>
                  <div className="flex items-center gap-2">
                    <h3 className="font-semibold text-gray-900">{niche.name}</h3>
                    {niche.is_active && <Badge variant="success">Active</Badge>}
                  </div>
                  <p className="text-xs text-gray-400 mt-0.5">{niche.industry}</p>
                </div>
                <div className="flex gap-1">
                  <button
                    onClick={() => { setEditingNiche(niche); setView('edit'); }}
                    className="p-1.5 text-gray-400 hover:text-gray-600 hover:bg-gray-100 rounded-lg transition-colors"
                  >
                    <Edit3 size={14} />
                  </button>
                  <button
                    onClick={() => deleteNiche(niche.id)}
                    className="p-1.5 text-gray-400 hover:text-red-500 hover:bg-red-50 rounded-lg transition-colors"
                  >
                    <Trash2 size={14} />
                  </button>
                </div>
              </div>

              <p className="text-sm text-gray-600 mb-3 line-clamp-2">{niche.sub_niche}</p>

              <div className="flex flex-wrap gap-1 mb-4">
                {(niche.seed_keywords || []).slice(0, 4).map(kw => (
                  <span key={kw} className="text-xs bg-gray-100 text-gray-600 px-2 py-0.5 rounded-full">#{kw}</span>
                ))}
              </div>

              <div className="flex gap-2">
                {!niche.is_active && (
                  <Button size="sm" variant="secondary" onClick={() => activateNiche(niche.id)}>
                    Set active
                  </Button>
                )}
                {niche.is_active && (
                  <Button size="sm" onClick={() => setView('topics')}>
                    <Zap size={13} /> Generate Topics
                  </Button>
                )}
              </div>
            </Card>
          ))}
        </div>
      )}
    </div>
  );
}

// ─── NICHE WIZARD (multi-step form) ──────────────────────────────────────
function NicheWizard({ niche, onSave, onCancel }) {
  const [step, setStep] = useState(0);
  const [saving, setSaving] = useState(false);
  const [form, setForm] = useState({
    name: niche?.name || '',
    industry: niche?.industry || '',
    subNiche: niche?.sub_niche || '',
    contentAngle: niche?.content_angle || '',
    uniqueValue: niche?.unique_value || '',
    audienceAge: niche?.audience_age || '',
    audienceGender: niche?.audience_gender || '',
    audienceLevel: niche?.audience_level || 'mixed',
    audienceGoals: niche?.audience_goals || [],
    audiencePains: niche?.audience_pains || [],
    platforms: niche?.platforms || ['youtube'],
    contentFormats: niche?.content_formats || ['long-form'],
    topicsToAvoid: niche?.topics_to_avoid || [],
    seedKeywords: niche?.seed_keywords || [],
    trendingSources: niche?.trending_sources || [],
    competitorUrls: niche?.competitor_urls || [],
  });

  const steps = [
    { title: 'Core Identity', icon: Target },
    { title: 'Your Audience', icon: Users },
    { title: 'Content Strategy', icon: Lightbulb },
    { title: 'Keywords & Sources', icon: Hash },
  ];

  const update = (key, val) => setForm(f => ({ ...f, [key]: val }));

  const toggleArr = (key, val) => {
    setForm(f => ({
      ...f,
      [key]: f[key].includes(val) ? f[key].filter(x => x !== val) : [...f[key], val]
    }));
  };

  const addToArr = (key, val) => {
    if (!val.trim()) return;
    setForm(f => ({ ...f, [key]: [...new Set([...f[key], val.trim()])] }));
  };

  const removeFromArr = (key, val) => setForm(f => ({ ...f, [key]: f[key].filter(x => x !== val) }));

  const handleSave = async () => {
    setSaving(true);
    await onSave(form);
    setSaving(false);
  };

  const canNext = () => {
    if (step === 0) return form.name && form.industry && form.subNiche && form.contentAngle;
    if (step === 1) return true;
    if (step === 2) return form.platforms.length > 0;
    return true;
  };

  return (
    <div className="max-w-2xl mx-auto space-y-6">
      {/* Header */}
      <div className="flex items-center gap-3">
        <button onClick={onCancel} className="p-2 text-gray-400 hover:text-gray-600 hover:bg-gray-100 rounded-lg">
          <ChevronLeft size={18} />
        </button>
        <h1 className="text-xl font-semibold text-gray-900">{niche ? 'Edit Niche' : 'Create Niche Profile'}</h1>
      </div>

      {/* Step indicators */}
      <div className="flex gap-2">
        {steps.map((s, i) => {
          const Icon = s.icon;
          return (
            <div key={i} className={clsx('flex-1 flex flex-col items-center gap-1 cursor-pointer', i > step && 'opacity-40')} onClick={() => i < step && setStep(i)}>
              <div className={clsx('w-9 h-9 rounded-xl flex items-center justify-center transition-all',
                i === step ? 'bg-brand-600 text-white shadow-md shadow-brand-200'
                : i < step ? 'bg-brand-100 text-brand-600'
                : 'bg-gray-100 text-gray-400'
              )}>
                {i < step ? <CheckCircle2 size={16} /> : <Icon size={16} />}
              </div>
              <span className="text-xs text-gray-500 hidden sm:block">{s.title}</span>
            </div>
          );
        })}
      </div>

      {/* Step content */}
      <Card className="p-6">
        {step === 0 && (
          <StepCore form={form} update={update} />
        )}
        {step === 1 && (
          <StepAudience form={form} update={update} addToArr={addToArr} removeFromArr={removeFromArr} toggleArr={toggleArr} />
        )}
        {step === 2 && (
          <StepContent form={form} update={update} toggleArr={toggleArr} addToArr={addToArr} removeFromArr={removeFromArr} />
        )}
        {step === 3 && (
          <StepKeywords form={form} update={update} addToArr={addToArr} removeFromArr={removeFromArr} />
        )}
      </Card>

      {/* Navigation */}
      <div className="flex justify-between">
        <Button variant="secondary" onClick={() => step === 0 ? onCancel() : setStep(s => s - 1)}>
          {step === 0 ? 'Cancel' : <><ChevronLeft size={15} /> Back</>}
        </Button>
        {step < steps.length - 1 ? (
          <Button onClick={() => setStep(s => s + 1)} disabled={!canNext()}>
            Next <ChevronRight size={15} />
          </Button>
        ) : (
          <Button onClick={handleSave} loading={saving} disabled={!canNext()}>
            <CheckCircle2 size={15} /> {niche ? 'Update Niche' : 'Create Niche'}
          </Button>
        )}
      </div>
    </div>
  );
}

function StepCore({ form, update }) {
  return (
    <div className="space-y-5">
      <div>
        <h2 className="text-base font-semibold text-gray-900 mb-1">Core Identity</h2>
        <p className="text-sm text-gray-500">Define your niche with precision. Vague = generic content. Specific = targeted content.</p>
      </div>
      <Input label="Niche profile name (internal)" value={form.name} onChange={e => update('name', e.target.value)} placeholder="e.g. Main Fitness Channel" />
      <div>
        <label className="block text-sm font-medium text-gray-700 mb-1">Industry</label>
        <select className="w-full rounded-lg border border-gray-200 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-brand-500"
          value={form.industry} onChange={e => update('industry', e.target.value)}>
          <option value="">Select industry…</option>
          {INDUSTRIES.map(i => <option key={i} value={i}>{i}</option>)}
        </select>
      </div>
      <div>
        <label className="block text-sm font-medium text-gray-700 mb-1">Sub-niche <span className="text-red-400">*</span></label>
        <input className="w-full rounded-lg border border-gray-200 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-brand-500"
          value={form.subNiche} onChange={e => update('subNiche', e.target.value)}
          placeholder="e.g. Weight loss for women over 40 with hormonal imbalances" />
        <p className="text-xs text-gray-400 mt-1">Be as specific as possible. Bad: "fitness". Good: "HIIT workouts for busy moms with no equipment"</p>
      </div>
      <div>
        <label className="block text-sm font-medium text-gray-700 mb-1">Content angle <span className="text-red-400">*</span></label>
        <input className="w-full rounded-lg border border-gray-200 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-brand-500"
          value={form.contentAngle} onChange={e => update('contentAngle', e.target.value)}
          placeholder="e.g. Science-based, no-BS approach that cuts through fitness myths" />
      </div>
      <div>
        <label className="block text-sm font-medium text-gray-700 mb-1">Your unique value / story</label>
        <textarea className="w-full rounded-lg border border-gray-200 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-brand-500" rows={2}
          value={form.uniqueValue} onChange={e => update('uniqueValue', e.target.value)}
          placeholder="e.g. Lost 40kg myself after failing 10 diets. I share what actually worked." />
      </div>
    </div>
  );
}

function StepAudience({ form, update, addToArr, removeFromArr }) {
  const [goalInput, setGoalInput] = useState('');
  const [painInput, setPainInput] = useState('');
  return (
    <div className="space-y-5">
      <div>
        <h2 className="text-base font-semibold text-gray-900 mb-1">Your Audience</h2>
        <p className="text-sm text-gray-500">The more precisely you define who you're talking to, the more targeted the content.</p>
      </div>
      <div className="grid grid-cols-2 gap-4">
        <Input label="Age range" value={form.audienceAge} onChange={e => update('audienceAge', e.target.value)} placeholder="e.g. 28–45" />
        <Input label="Gender" value={form.audienceGender} onChange={e => update('audienceGender', e.target.value)} placeholder="e.g. Primarily women" />
      </div>
      <div>
        <label className="block text-sm font-medium text-gray-700 mb-2">Knowledge level</label>
        <div className="flex gap-2">
          {AUDIENCE_LEVELS.map(l => (
            <button key={l} type="button" onClick={() => update('audienceLevel', l)}
              className={clsx('flex-1 py-2 rounded-lg text-sm capitalize border transition-all',
                form.audienceLevel === l ? 'border-brand-500 bg-brand-50 text-brand-700 font-medium' : 'border-gray-200 text-gray-500 hover:border-gray-300')}>
              {l}
            </button>
          ))}
        </div>
      </div>
      <TagInput label="Audience goals (what they want to achieve)" placeholder="e.g. lose 20kg" items={form.audienceGoals}
        onAdd={v => addToArr('audienceGoals', v)} onRemove={v => removeFromArr('audienceGoals', v)} color="green" />
      <TagInput label="Audience pain points (what frustrates them)" placeholder="e.g. no time to exercise" items={form.audiencePains}
        onAdd={v => addToArr('audiencePains', v)} onRemove={v => removeFromArr('audiencePains', v)} color="red" />
    </div>
  );
}

function StepContent({ form, update, toggleArr, addToArr, removeFromArr }) {
  return (
    <div className="space-y-5">
      <div>
        <h2 className="text-base font-semibold text-gray-900 mb-1">Content Strategy</h2>
        <p className="text-sm text-gray-500">Where you publish and what formats you use.</p>
      </div>
      <div>
        <label className="block text-sm font-medium text-gray-700 mb-2">Platforms</label>
        <div className="grid grid-cols-2 sm:grid-cols-3 gap-2">
          {PLATFORMS.map(p => (
            <button key={p.id} type="button" onClick={() => toggleArr('platforms', p.id)}
              className={clsx('py-2.5 px-3 rounded-xl border text-sm transition-all text-left',
                form.platforms.includes(p.id) ? 'border-brand-500 bg-brand-50 text-brand-700 font-medium' : 'border-gray-200 text-gray-500 hover:border-gray-300')}>
              {p.label}
            </button>
          ))}
        </div>
      </div>
      <TagInput label="Topics / subjects to AVOID" placeholder="e.g. supplements, keto diet"
        items={form.topicsToAvoid} onAdd={v => addToArr('topicsToAvoid', v)} onRemove={v => removeFromArr('topicsToAvoid', v)} color="red" />
    </div>
  );
}

function StepKeywords({ form, addToArr, removeFromArr }) {
  return (
    <div className="space-y-5">
      <div>
        <h2 className="text-base font-semibold text-gray-900 mb-1">Keywords & Sources</h2>
        <p className="text-sm text-gray-500">These help the Intel Agent find relevant trending topics in your exact niche.</p>
      </div>
      <TagInput label="Seed keywords (core topics in your niche)" placeholder="e.g. HIIT, meal prep, metabolism"
        items={form.seedKeywords} onAdd={v => addToArr('seedKeywords', v)} onRemove={v => removeFromArr('seedKeywords', v)} color="blue" />
      <TagInput label="Trending sources (sites / subreddits / forums)" placeholder="e.g. reddit.com/r/fitness"
        items={form.trendingSources} onAdd={v => addToArr('trendingSources', v)} onRemove={v => removeFromArr('trendingSources', v)} color="purple" />
      <TagInput label="Competitor channels (for style reference)" placeholder="e.g. youtube.com/@hubermanlab"
        items={form.competitorUrls} onAdd={v => addToArr('competitorUrls', v)} onRemove={v => removeFromArr('competitorUrls', v)} color="orange" />
    </div>
  );
}

// ─── TOPIC APPROVAL FLOW ──────────────────────────────────────────────────
function TopicApprovalFlow({ niche, onBack }) {
  const { user } = useAuth();
  const [proposals, setProposals] = useState([]);
  const [generating, setGenerating] = useState(false);
  const [running, setRunning] = useState(false);
  const [count, setCount] = useState(7);
  const [editingId, setEditingId] = useState(null);
  const [editTitle, setEditTitle] = useState('');
  const [jobId, setJobId] = useState(null);
  const [jobState, setJobState] = useState(null);

  useEffect(() => { fetchProposals(); }, []);

  // Poll job
  useEffect(() => {
    if (!jobId) return;
    const interval = setInterval(async () => {
      try {
        const { data } = await api.get(`/pipeline/job/${jobId}`);
        setJobState(data.state);
        if (data.state === 'completed') { clearInterval(interval); toast.success('Pipeline completed! 🎉'); setRunning(false); setJobId(null); }
        if (data.state === 'failed') { clearInterval(interval); toast.error('Pipeline failed'); setRunning(false); setJobId(null); }
      } catch {}
    }, 2000);
    return () => clearInterval(interval);
  }, [jobId]);

  async function fetchProposals() {
    try {
      const { data } = await api.get(`/niche/proposals?status=pending&nicheId=${niche.id}`);
      setProposals(data);
    } catch {}
  }

  async function generateTopics() {
    setGenerating(true);
    setProposals([]);
    try {
      const { data } = await api.post(`/niche/${niche.id}/propose-topics`, { count });
      setProposals(data.proposals);
      toast.success(`${data.count} topics proposed!`);
    } catch (err) {
      toast.error(err.response?.data?.error || 'Generation failed');
    }
    setGenerating(false);
  }

  async function handleDecision(id, status, finalTitle = null) {
    try {
      const { data } = await api.patch(`/niche/proposals/${id}`, { status, finalTitle });
      setProposals(p => p.map(t => t.id === id ? data : t));
    } catch { toast.error('Failed to update topic'); }
  }

  async function approveAll() {
    const pendingIds = proposals.filter(p => p.status === 'pending').map(p => p.id);
    if (pendingIds.length === 0) return;
    await api.patch('/niche/proposals/bulk', { ids: pendingIds, status: 'approved' });
    setProposals(p => p.map(t => pendingIds.includes(t.id) ? { ...t, status: 'approved' } : t));
    toast.success(`${pendingIds.length} topics approved`);
  }

  async function runPipeline() {
    const approved = proposals.filter(p => ['approved', 'modified'].includes(p.status));
    if (approved.length === 0) { toast.error('Approve at least 1 topic first'); return; }
    setRunning(true);
    try {
      const { data } = await api.post('/niche/run-with-topics', {
        nicheId: niche.id,
        topicIds: approved.map(p => p.id)
      });
      setJobId(data.jobId);
      toast.success(`Pipeline started with ${data.topicsCount} topics!`);
    } catch (err) {
      toast.error(err.response?.data?.message || 'Failed to start pipeline');
      setRunning(false);
    }
  }

  const approvedCount = proposals.filter(p => ['approved', 'modified'].includes(p.status)).length;
  const pendingCount = proposals.filter(p => p.status === 'pending').length;
  const rejectedCount = proposals.filter(p => p.status === 'rejected').length;

  return (
    <div className="space-y-6 max-w-3xl">
      {/* Header */}
      <div className="flex items-center gap-3">
        <button onClick={onBack} className="p-2 text-gray-400 hover:text-gray-600 hover:bg-gray-100 rounded-lg">
          <ChevronLeft size={18} />
        </button>
        <div>
          <h1 className="text-xl font-semibold text-gray-900">Topic Proposals</h1>
          <p className="text-sm text-gray-500">{niche.name} · {niche.sub_niche}</p>
        </div>
      </div>

      {/* Generate controls */}
      <Card className="p-5">
        <div className="flex items-center gap-4 flex-wrap">
          <div className="flex items-center gap-2">
            <label className="text-sm text-gray-600">Generate</label>
            <select
              value={count}
              onChange={e => setCount(parseInt(e.target.value))}
              className="border border-gray-200 rounded-lg px-2 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-brand-500"
            >
              {[3, 5, 7, 10].map(n => <option key={n} value={n}>{n} topics</option>)}
            </select>
          </div>
          <Button onClick={generateTopics} loading={generating} variant="secondary">
            <RefreshCw size={15} />
            {proposals.length > 0 ? 'Regenerate' : 'Generate Topics'}
          </Button>
          {proposals.length > 0 && (
            <p className="text-xs text-gray-400 ml-auto">
              {approvedCount} approved · {pendingCount} pending · {rejectedCount} rejected
            </p>
          )}
        </div>
      </Card>

      {/* Topic list */}
      {generating ? (
        <div className="flex flex-col items-center justify-center py-20 gap-3">
          <Spinner size={36} />
          <p className="text-sm text-gray-500 animate-pulse">AI is analyzing your niche and generating targeted topics…</p>
        </div>
      ) : proposals.length === 0 ? (
        <Card className="p-12 text-center">
          <Lightbulb size={36} className="text-gray-200 mx-auto mb-3" />
          <p className="text-gray-400 text-sm">Click "Generate Topics" to get AI-proposed topics tailored to your niche</p>
        </Card>
      ) : (
        <div className="space-y-3">
          {proposals.map((topic, i) => (
            <TopicCard
              key={topic.id}
              topic={topic}
              index={i}
              isEditing={editingId === topic.id}
              editTitle={editTitle}
              onEditStart={() => { setEditingId(topic.id); setEditTitle(topic.final_title || topic.proposed_title); }}
              onEditChange={setEditTitle}
              onEditSave={() => { handleDecision(topic.id, 'modified', editTitle); setEditingId(null); }}
              onEditCancel={() => setEditingId(null)}
              onApprove={() => handleDecision(topic.id, 'approved')}
              onReject={() => handleDecision(topic.id, 'rejected')}
              onReset={() => handleDecision(topic.id, 'pending')}
            />
          ))}
        </div>
      )}

      {/* Action bar */}
      {proposals.length > 0 && (
        <div className="sticky bottom-6 flex items-center justify-between bg-white border border-gray-200 rounded-2xl shadow-xl shadow-black/10 p-4">
          <div className="flex items-center gap-3">
            {pendingCount > 0 && (
              <Button variant="secondary" size="sm" onClick={approveAll}>
                <CheckCircle2 size={14} /> Approve all ({pendingCount})
              </Button>
            )}
            <span className="text-sm text-gray-500">
              {approvedCount > 0
                ? <><span className="font-semibold text-brand-600">{approvedCount}</span> topic{approvedCount > 1 ? 's' : ''} selected</>
                : 'Approve topics to run pipeline'}
            </span>
          </div>
          <Button
            onClick={runPipeline}
            loading={running}
            disabled={approvedCount === 0}
            size="lg"
          >
            <Play size={16} />
            {running ? 'Running…' : `Run Pipeline (${approvedCount})`}
          </Button>
        </div>
      )}
    </div>
  );
}

// ─── TOPIC CARD ────────────────────────────────────────────────────────────
function TopicCard({ topic, index, isEditing, editTitle, onEditStart, onEditChange, onEditSave, onEditCancel, onApprove, onReject, onReset }) {
  const [expanded, setExpanded] = useState(false);

  const statusConfig = {
    pending:  { bg: 'bg-white', border: 'border-gray-200', badge: null },
    approved: { bg: 'bg-emerald-50', border: 'border-emerald-200', badge: { label: '✓ Approved', cls: 'bg-emerald-100 text-emerald-700' } },
    modified: { bg: 'bg-blue-50', border: 'border-blue-200', badge: { label: '✏ Modified', cls: 'bg-blue-100 text-blue-700' } },
    rejected: { bg: 'bg-red-50/50', border: 'border-red-100', badge: { label: '✗ Rejected', cls: 'bg-red-100 text-red-500' } },
  };
  const sc = statusConfig[topic.status] || statusConfig.pending;
  const displayTitle = topic.final_title || topic.proposed_title;

  return (
    <div className={clsx('rounded-xl border-2 p-4 transition-all', sc.bg, sc.border, topic.status === 'rejected' && 'opacity-60')}>
      <div className="flex items-start gap-3">
        {/* Index */}
        <div className="w-7 h-7 rounded-lg bg-gray-100 flex items-center justify-center flex-shrink-0 mt-0.5">
          <span className="text-xs font-semibold text-gray-500">{index + 1}</span>
        </div>

        {/* Content */}
        <div className="flex-1 min-w-0">
          {isEditing ? (
            <div className="space-y-2">
              <input
                className="w-full rounded-lg border border-brand-300 px-3 py-2 text-sm font-medium focus:outline-none focus:ring-2 focus:ring-brand-500"
                value={editTitle}
                onChange={e => onEditChange(e.target.value)}
                autoFocus
              />
              <div className="flex gap-2">
                <Button size="sm" onClick={onEditSave}><CheckCircle2 size={13} /> Save</Button>
                <Button size="sm" variant="ghost" onClick={onEditCancel}>Cancel</Button>
              </div>
            </div>
          ) : (
            <>
              <div className="flex items-start justify-between gap-2">
                <p className={clsx('text-sm font-semibold text-gray-900', topic.status === 'rejected' && 'line-through text-gray-400')}>
                  {displayTitle}
                </p>
                {sc.badge && (
                  <span className={clsx('text-xs font-medium px-2 py-0.5 rounded-full flex-shrink-0', sc.badge.cls)}>
                    {sc.badge.label}
                  </span>
                )}
              </div>

              {/* Meta chips */}
              <div className="flex gap-2 mt-1.5 flex-wrap">
                {topic.search_intent && (
                  <span className="text-xs text-gray-400 bg-gray-100 px-1.5 py-0.5 rounded">{topic.search_intent}</span>
                )}
                {topic.difficulty && (
                  <span className={clsx('text-xs px-1.5 py-0.5 rounded',
                    topic.difficulty === 'easy' ? 'bg-green-100 text-green-600'
                    : topic.difficulty === 'medium' ? 'bg-amber-100 text-amber-600'
                    : 'bg-red-100 text-red-500'
                  )}>{topic.difficulty}</span>
                )}
              </div>

              {/* Expandable details */}
              {(topic.proposed_angle || topic.proposed_hook || topic.why_now) && (
                <button
                  onClick={() => setExpanded(e => !e)}
                  className="text-xs text-brand-600 hover:text-brand-700 mt-1.5 flex items-center gap-1"
                >
                  {expanded ? 'Hide details' : 'Show details'}
                  <ChevronRight size={11} className={clsx('transition-transform', expanded && 'rotate-90')} />
                </button>
              )}

              {expanded && (
                <div className="mt-3 space-y-2 text-xs text-gray-600 bg-white/70 rounded-lg p-3 border border-gray-100">
                  {topic.proposed_angle && <p><span className="font-medium text-gray-700">Angle: </span>{topic.proposed_angle}</p>}
                  {topic.proposed_hook && <p><span className="font-medium text-gray-700">Hook: </span>"{topic.proposed_hook}"</p>}
                  {topic.why_now && <p><span className="font-medium text-gray-700">Why now: </span>{topic.why_now}</p>}
                </div>
              )}
            </>
          )}
        </div>

        {/* Actions */}
        {!isEditing && (
          <div className="flex gap-1 flex-shrink-0">
            {topic.status === 'pending' && (
              <>
                <button onClick={onApprove} className="p-1.5 text-gray-400 hover:text-emerald-600 hover:bg-emerald-50 rounded-lg transition-colors" title="Approve">
                  <CheckCircle2 size={16} />
                </button>
                <button onClick={onEditStart} className="p-1.5 text-gray-400 hover:text-blue-600 hover:bg-blue-50 rounded-lg transition-colors" title="Edit title">
                  <Edit3 size={16} />
                </button>
                <button onClick={onReject} className="p-1.5 text-gray-400 hover:text-red-500 hover:bg-red-50 rounded-lg transition-colors" title="Reject">
                  <X size={16} />
                </button>
              </>
            )}
            {['approved', 'modified', 'rejected'].includes(topic.status) && (
              <button onClick={onReset} className="p-1.5 text-gray-400 hover:text-gray-600 hover:bg-gray-100 rounded-lg transition-colors text-xs">
                Undo
              </button>
            )}
          </div>
        )}
      </div>
    </div>
  );
}

// ─── TAG INPUT HELPER ────────────────────────────────────────────────────
function TagInput({ label, placeholder, items, onAdd, onRemove, color = 'blue' }) {
  const [input, setInput] = useState('');
  const colorMap = {
    blue:   'bg-blue-100 text-blue-700',
    green:  'bg-emerald-100 text-emerald-700',
    red:    'bg-red-100 text-red-600',
    purple: 'bg-purple-100 text-purple-700',
    orange: 'bg-orange-100 text-orange-700',
  };
  const cls = colorMap[color] || colorMap.blue;

  const add = () => { if (input.trim()) { onAdd(input.trim()); setInput(''); } };

  return (
    <div className="space-y-2">
      <label className="block text-sm font-medium text-gray-700">{label}</label>
      <div className="flex gap-2">
        <input
          className="flex-1 rounded-lg border border-gray-200 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-brand-500"
          value={input}
          onChange={e => setInput(e.target.value)}
          onKeyDown={e => { if (e.key === 'Enter') { e.preventDefault(); add(); } }}
          placeholder={placeholder}
        />
        <button type="button" onClick={add} className="px-3 py-2 rounded-lg bg-gray-100 hover:bg-gray-200 text-gray-600 transition-colors">
          <Plus size={16} />
        </button>
      </div>
      {items.length > 0 && (
        <div className="flex flex-wrap gap-1.5">
          {items.map(item => (
            <span key={item} className={clsx('inline-flex items-center gap-1 text-xs px-2 py-1 rounded-full font-medium', cls)}>
              {item}
              <button type="button" onClick={() => onRemove(item)} className="opacity-60 hover:opacity-100 transition-opacity">
                <X size={11} />
              </button>
            </span>
          ))}
        </div>
      )}
    </div>
  );
}
