import { useParams, useNavigate } from 'react-router-dom';
import { useQuery } from '@tanstack/react-query';
import { AppLayout } from '../../components/layout/AppLayout';
import { leadGenApi } from '../../api/leadGen';
import { useAuth } from '../../contexts/AuthContext';
import {
ArrowLeft,
Loader2,
TrendingUp,
TrendingDown,
Eye,
MousePointer,
Target,
DollarSign,
Activity,
AlertTriangle,
} from 'lucide-react';
export function CampaignDetailPage() {
const { campaignId } = useParams<{ campaignId: string }>();
const navigate = useNavigate();
const { user } = useAuth();
const companyId = user?.company_id;
// Dashboard data (includes campaign stats)
const { data: dashboardData, isLoading } = useQuery({
queryKey: ['lead-gen-dashboard', companyId, 30],
queryFn: () => leadGenApi.getDashboard(companyId!, 30),
enabled: !!companyId,
});
// Attribution data
const { data: attributionData } = useQuery({
queryKey: ['lead-gen-attribution', companyId, 30],
queryFn: () => leadGenApi.getAttributions(companyId!, { days: 30 }),
enabled: !!companyId,
});
// Rules
const { data: rulesData } = useQuery({
queryKey: ['lead-gen-rules', companyId],
queryFn: () => leadGenApi.getRules(companyId!),
enabled: !!companyId,
});
// Optimization log
const { data: logData } = useQuery({
queryKey: ['lead-gen-log', companyId, 50],
queryFn: () => leadGenApi.getOptimizationLog(companyId!, 50, 30),
enabled: !!companyId,
});
const dashboard = dashboardData?.data?.data;
const attributions = attributionData?.data?.data?.attributions || [];
const summary = attributionData?.data?.data?.summary;
const rules = rulesData?.data?.data?.rules || [];
const logs = logData?.data?.data?.logs || [];
if (isLoading) {
return (
<AppLayout title="Campaign Detail">
<div className="flex justify-center py-12">
<Loader2 className="h-8 w-8 animate-spin text-brand-500" />
</div>
</AppLayout>
);
}
const totalImpressions = dashboard?.campaigns?.total_impressions || 0;
const totalClicks = dashboard?.campaigns?.total_clicks || 0;
const totalConversions = dashboard?.campaigns?.total_conversions || 0;
const totalSpend = dashboard?.campaigns?.total_spend || 0;
const ctr = totalImpressions > 0 ? ((totalClicks / totalImpressions) * 100).toFixed(2) : '0.00';
const cpa = totalConversions > 0 ? (totalSpend / totalConversions).toFixed(2) : '—';
return (
<AppLayout title="Campaign Detail">
<div className="max-w-6xl mx-auto">
{/* Header */}
<div className="flex items-center gap-4 mb-8">
<button
type="button"
onClick={() => navigate('/app/lead-gen')}
className="p-2 hover:bg-surface-100 rounded-lg transition-colors"
>
<ArrowLeft className="h-5 w-5" />
</button>
<div className="flex-1">
<h1 className="text-2xl font-bold text-surface-900">Campaign Detail</h1>
<p className="text-sm text-surface-500">
Campaign {campaignId?.slice(0, 8) || '—'} · Performance overview
</p>
</div>
</div>
{/* KPI Cards */}
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-4 mb-8">
{[
{ label: 'Active', value: dashboard?.campaigns?.active || 0, icon: Activity, color: 'text-emerald-600' },
{ label: 'Spend', value: `$${totalSpend.toLocaleString(undefined, { maximumFractionDigits: 0 })}`, icon: DollarSign, color: 'text-blue-600' },
{ label: 'Impressions', value: totalImpressions.toLocaleString(), icon: Eye, color: 'text-purple-600' },
{ label: 'Clicks', value: totalClicks.toLocaleString(), icon: MousePointer, color: 'text-orange-600' },
{ label: 'Conversions', value: totalConversions, icon: Target, color: 'text-emerald-600' },
{ label: 'CPA', value: cpa !== '—' ? `$${cpa}` : '—', icon: DollarSign, color: 'text-amber-600' },
].map(kpi => (
<div key={kpi.label} className="rounded-xl border border-surface-200 bg-white p-4">
<div className="flex items-center gap-2 mb-2">
<kpi.icon className={`h-4 w-4 ${kpi.color}`} />
<span className="text-xs font-medium uppercase tracking-wider text-surface-400">
{kpi.label}
</span>
</div>
<p className={`text-xl font-bold ${kpi.color}`}>{kpi.value}</p>
</div>
))}
</div>
{/* CTR and ROAS row */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-8">
<div className="rounded-xl border border-surface-200 bg-white p-6">
<h3 className="text-sm font-medium text-surface-500 mb-1">Click-Through Rate</h3>
<div className="flex items-baseline gap-2">
<span className="text-3xl font-bold text-surface-900">{ctr}%</span>
<span className="text-sm text-surface-400">
{totalClicks.toLocaleString()} / {totalImpressions.toLocaleString()} clicks
</span>
</div>
</div>
<div className="rounded-xl border border-surface-200 bg-white p-6">
<h3 className="text-sm font-medium text-surface-500 mb-1">Return on Ad Spend</h3>
<div className="flex items-baseline gap-2">
<span className="text-3xl font-bold text-surface-900">
{summary?.overall_roas ? `${summary.overall_roas.toFixed(1)}x` : '—'}
</span>
{summary && (
<span className="text-sm text-surface-400">
${summary.total_revenue.toLocaleString()} / ${summary.total_spend.toLocaleString()}
</span>
)}
</div>
</div>
</div>
{/* Attribution Table */}
<div className="rounded-xl border border-surface-200 bg-white mb-8 overflow-hidden">
<div className="border-b border-surface-200 px-6 py-4">
<h2 className="font-semibold text-surface-900">Lead Attribution</h2>
<p className="text-sm text-surface-500">
{summary?.attribution_count || 0} leads tracked in last 30 days
</p>
</div>
{attributions.length === 0 ? (
<div className="px-6 py-12 text-center text-surface-400">
<Target className="h-8 w-8 mx-auto mb-3 opacity-50" />
<p className="text-sm">No attribution data yet. Leads will appear here when forms are submitted with UTM params.</p>
</div>
) : (
<div className="overflow-x-auto">
<table className="w-full text-sm">
<thead>
<tr className="border-b border-surface-200 bg-surface-50">
<th className="text-left px-6 py-3 text-xs font-medium uppercase tracking-wider text-surface-500">Source</th>
<th className="text-left px-6 py-3 text-xs font-medium uppercase tracking-wider text-surface-500">Campaign</th>
<th className="text-left px-6 py-3 text-xs font-medium uppercase tracking-wider text-surface-500">Keyword</th>
<th className="text-right px-6 py-3 text-xs font-medium uppercase tracking-wider text-surface-500">Spend</th>
<th className="text-right px-6 py-3 text-xs font-medium uppercase tracking-wider text-surface-500">Revenue</th>
<th className="text-right px-6 py-3 text-xs font-medium uppercase tracking-wider text-surface-500">ROAS</th>
<th className="text-center px-6 py-3 text-xs font-medium uppercase tracking-wider text-surface-500">Status</th>
</tr>
</thead>
<tbody>
{attributions.map(a => (
<tr key={a.id} className="border-b border-surface-100 last:border-b-0">
<td className="px-6 py-3">
<span className="capitalize text-surface-700">{a.utm_source || a.lead_source}</span>
</td>
<td className="px-6 py-3 text-surface-700">
{a.utm_campaign || '—'}
</td>
<td className="px-6 py-3 text-surface-500">
{a.utm_term || '—'}
</td>
<td className="px-6 py-3 text-right tabular-nums text-surface-700">
{a.total_ad_spend ? `$${a.total_ad_spend.toFixed(2)}` : '—'}
</td>
<td className="px-6 py-3 text-right tabular-nums font-medium text-emerald-600">
{a.deal_amount ? `$${a.deal_amount.toFixed(2)}` : '—'}
</td>
<td className="px-6 py-3 text-right tabular-nums">
{a.roas ? (
<span className={a.roas >= 3 ? 'text-emerald-600 font-medium' : 'text-amber-600'}>
{a.roas.toFixed(1)}x
</span>
) : (
<span className="text-surface-400">—</span>
)}
</td>
<td className="px-6 py-3 text-center">
<span className={`inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${
a.attribution_status === 'deal'
? 'bg-emerald-100 text-emerald-700'
: a.attribution_status === 'lead'
? 'bg-blue-100 text-blue-700'
: 'bg-surface-100 text-surface-600'
}`}>
{a.attribution_status}
</span>
</td>
</tr>
))}
</tbody>
</table>
</div>
)}
</div>
{/* Optimization Log */}
<div className="rounded-xl border border-surface-200 bg-white overflow-hidden">
<div className="border-b border-surface-200 px-6 py-4">
<h2 className="font-semibold text-surface-900">Optimization Actions</h2>
<p className="text-sm text-surface-500">
{logs.length} actions in last 30 days · {rules.filter(r => r.is_active).length} active rules
</p>
</div>
{logs.length === 0 ? (
<div className="px-6 py-12 text-center text-surface-400">
<Activity className="h-8 w-8 mx-auto mb-3 opacity-50" />
<p className="text-sm">No optimization actions yet. Rules will trigger based on campaign performance.</p>
</div>
) : (
<div className="divide-y divide-surface-100">
{logs.slice(0, 20).map(log => (
<div key={log.id} className="px-6 py-4 flex items-start gap-4">
<div className={`mt-0.5 shrink-0 h-2 w-2 rounded-full ${
log.status === 'success' ? 'bg-emerald-500' :
log.status === 'failed' ? 'bg-red-500' :
'bg-amber-500'
}`} />
<div className="flex-1 min-w-0">
<div className="flex items-center gap-2 mb-1">
<span className="font-medium text-sm text-surface-900">{log.target_name || log.target_id}</span>
<span className="inline-flex items-center rounded-full bg-surface-100 px-2 py-0.5 text-xs font-medium text-surface-600 capitalize">
{log.action}
</span>
<span className="text-xs text-surface-400 capitalize">
{log.source_service.replace('_', ' ')}
</span>
</div>
{log.reason && (
<p className="text-xs text-surface-500">{log.reason}</p>
)}
</div>
<time className="text-xs text-surface-400 shrink-0 whitespace-nowrap">
{new Date(log.created_at).toLocaleDateString()}
</time>
</div>
))}
</div>
)}
</div>
</div>
</AppLayout>
);
}