'use client'; import { useQueryClient } from '@tanstack/react-query'; import Link from 'next/link'; import { Suspense, useCallback, useEffect, useMemo, useState } from 'react'; import { format } from 'date-fns'; import { CartesianGrid, Line, LineChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts'; import { BrainCircuit, ChartNoAxesCombined, RefreshCcw, Search } from 'lucide-react'; import { useSearchParams } from 'next/navigation'; import { AppShell } from '@/components/shell/app-shell'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Panel } from '@/components/ui/panel'; import { useAuthGuard } from '@/hooks/use-auth-guard'; import { useLinkPrefetch } from '@/hooks/use-link-prefetch'; import { asNumber, formatCurrency, formatCurrencyByScale, formatPercent, type NumberScaleUnit } from '@/lib/format'; import { queryKeys } from '@/lib/query/keys'; import { companyAnalysisQueryOptions } from '@/lib/query/options'; import type { CompanyAnalysis } from '@/lib/types'; type FinancialPeriodFilter = 'quarterlyAndFiscalYearEnd' | 'quarterlyOnly' | 'fiscalYearEndOnly'; type FinancialSeriesPoint = { filingDate: string; filingType: '10-K' | '10-Q'; periodLabel: 'Quarter End' | 'Fiscal Year End'; revenue: number | null; netIncome: number | null; assets: number | null; netMargin: number | null; }; const FINANCIAL_PERIOD_FILTER_OPTIONS: Array<{ value: FinancialPeriodFilter; label: string }> = [ { value: 'quarterlyAndFiscalYearEnd', label: 'Quarterly + Fiscal Year End' }, { value: 'quarterlyOnly', label: 'Quarterly only' }, { value: 'fiscalYearEndOnly', label: 'Fiscal Year End only' } ]; const FINANCIAL_VALUE_SCALE_OPTIONS: Array<{ value: NumberScaleUnit; label: string }> = [ { value: 'thousands', label: 'Thousands (K)' }, { value: 'millions', label: 'Millions (M)' }, { value: 'billions', label: 'Billions (B)' } ]; const CHART_TEXT = '#e8fff8'; const CHART_MUTED = '#b4ced9'; const CHART_GRID = 'rgba(126, 217, 255, 0.24)'; const CHART_TOOLTIP_BG = 'rgba(6, 17, 24, 0.95)'; const CHART_TOOLTIP_BORDER = 'rgba(123, 255, 217, 0.45)'; function formatShortDate(value: string) { return format(new Date(value), 'MMM yyyy'); } function formatLongDate(value: string) { return format(new Date(value), 'MMM dd, yyyy'); } function ratioPercent(numerator: number | null, denominator: number | null) { if (numerator === null || denominator === null || denominator === 0) { return null; } return (numerator / denominator) * 100; } function isFinancialSnapshotForm( filingType: CompanyAnalysis['filings'][number]['filing_type'] ): filingType is '10-K' | '10-Q' { return filingType === '10-K' || filingType === '10-Q'; } function includesFinancialPeriod(filingType: '10-K' | '10-Q', filter: FinancialPeriodFilter) { if (filter === 'quarterlyOnly') { return filingType === '10-Q'; } if (filter === 'fiscalYearEndOnly') { return filingType === '10-K'; } return true; } function asScaledFinancialCurrency( value: number | null | undefined, scale: NumberScaleUnit ) { if (value === null || value === undefined) { return 'n/a'; } return formatCurrencyByScale(value, scale); } export default function AnalysisPage() { return ( Loading analysis desk...}> ); } function AnalysisPageContent() { const { isPending, isAuthenticated } = useAuthGuard(); const searchParams = useSearchParams(); const queryClient = useQueryClient(); const { prefetchReport, prefetchResearchTicker } = useLinkPrefetch(); const [tickerInput, setTickerInput] = useState('MSFT'); const [ticker, setTicker] = useState('MSFT'); const [analysis, setAnalysis] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [financialPeriodFilter, setFinancialPeriodFilter] = useState('quarterlyAndFiscalYearEnd'); const [financialValueScale, setFinancialValueScale] = useState('millions'); useEffect(() => { const fromQuery = searchParams.get('ticker'); if (!fromQuery) { return; } const normalized = fromQuery.trim().toUpperCase(); if (!normalized) { return; } setTickerInput(normalized); setTicker(normalized); }, [searchParams]); const loadAnalysis = useCallback(async (symbol: string) => { const options = companyAnalysisQueryOptions(symbol); if (!queryClient.getQueryData(options.queryKey)) { setLoading(true); } setError(null); try { const response = await queryClient.ensureQueryData(options); setAnalysis(response.analysis); } catch (err) { setError(err instanceof Error ? err.message : 'Unable to load company analysis'); setAnalysis(null); } finally { setLoading(false); } }, [queryClient]); useEffect(() => { if (!isPending && isAuthenticated) { void loadAnalysis(ticker); } }, [isPending, isAuthenticated, ticker, loadAnalysis]); const priceSeries = useMemo(() => { return (analysis?.priceHistory ?? []).map((point) => ({ ...point, label: formatShortDate(point.date) })); }, [analysis?.priceHistory]); const financialSeries = useMemo(() => { return (analysis?.financials ?? []) .filter((item): item is CompanyAnalysis['financials'][number] & { filingType: '10-K' | '10-Q' } => { return isFinancialSnapshotForm(item.filingType); }) .slice() .sort((a, b) => Date.parse(a.filingDate) - Date.parse(b.filingDate)) .map((item) => ({ filingDate: item.filingDate, filingType: item.filingType, periodLabel: item.filingType === '10-Q' ? 'Quarter End' : 'Fiscal Year End', revenue: item.revenue, netIncome: item.netIncome, assets: item.totalAssets, netMargin: ratioPercent(item.netIncome ?? null, item.revenue ?? null) })); }, [analysis?.financials]); const filteredFinancialSeries = useMemo(() => { return financialSeries.filter((point) => includesFinancialPeriod(point.filingType, financialPeriodFilter)); }, [financialSeries, financialPeriodFilter]); const periodEndFilings = useMemo(() => { return (analysis?.filings ?? []).filter((filing) => isFinancialSnapshotForm(filing.filing_type)); }, [analysis?.filings]); const selectedFinancialScaleLabel = useMemo(() => { return FINANCIAL_VALUE_SCALE_OPTIONS.find((option) => option.value === financialValueScale)?.label ?? 'Millions (M)'; }, [financialValueScale]); if (isPending || !isAuthenticated) { return
Loading analysis desk...
; } return ( { void queryClient.invalidateQueries({ queryKey: queryKeys.companyAnalysis(ticker.trim().toUpperCase()) }); void loadAnalysis(ticker); }} > Refresh )} >
{ event.preventDefault(); const normalized = tickerInput.trim().toUpperCase(); if (!normalized) { return; } setTicker(normalized); }} > setTickerInput(event.target.value.toUpperCase())} placeholder="Ticker (AAPL)" className="max-w-xs" /> {analysis ? ( prefetchResearchTicker(analysis.company.ticker)} onFocus={() => prefetchResearchTicker(analysis.company.ticker)} className="text-sm text-[color:var(--accent)] hover:text-[color:var(--accent-strong)]" > Open filing stream ) : null}
{error ? (

{error}

) : null}

{analysis?.company.companyName ?? ticker}

{analysis?.company.ticker ?? ticker}

{analysis?.company.sector ?? 'Sector unavailable'}

{analysis?.company.category ? (

{analysis.company.category}

) : null} {analysis?.company.tags.length ? (
{analysis.company.tags.map((tag) => ( {tag} ))}
) : null}

{formatCurrency(analysis?.quote ?? 0)}

CIK {analysis?.company.cik ?? 'n/a'}

{formatCurrency(analysis?.position?.market_value)}

{analysis?.position ? `${asNumber(analysis.position.shares).toLocaleString()} shares` : 'Not held in portfolio'}

= 0 ? 'text-[#96f5bf]' : 'text-[#ff9f9f]'}`}> {formatCurrency(analysis?.position?.gain_loss)}

{formatPercent(analysis?.position?.gain_loss_pct)}

{loading ? (

Loading price history...

) : priceSeries.length === 0 ? (

No price history available.

) : (
`$${value.toFixed(0)}`} /> formatCurrency(value)} contentStyle={{ backgroundColor: CHART_TOOLTIP_BG, border: `1px solid ${CHART_TOOLTIP_BORDER}`, borderRadius: '0.75rem' }} labelStyle={{ color: CHART_TEXT }} itemStyle={{ color: CHART_TEXT }} cursor={{ stroke: 'rgba(104, 255, 213, 0.35)', strokeWidth: 1 }} />
)}
{FINANCIAL_PERIOD_FILTER_OPTIONS.map((option) => ( ))}
{FINANCIAL_VALUE_SCALE_OPTIONS.map((option) => ( ))}
)} > {loading ? (

Loading financials...

) : filteredFinancialSeries.length === 0 ? (

No financial rows match the selected period filter.

) : (
{filteredFinancialSeries.map((point, index) => ( ))}
Filed Period Form Revenue Net Income Assets Net Margin
{formatLongDate(point.filingDate)} {point.periodLabel} {point.filingType} {asScaledFinancialCurrency(point.revenue, financialValueScale)} = 0 ? 'text-[#96f5bf]' : 'text-[#ff9f9f]'}> {asScaledFinancialCurrency(point.netIncome, financialValueScale)} {asScaledFinancialCurrency(point.assets, financialValueScale)} {point.netMargin === null ? 'n/a' : formatPercent(point.netMargin)}
)} {loading ? (

Loading filings...

) : periodEndFilings.length === 0 ? (

No 10-K or 10-Q filings available for this ticker.

) : (
{periodEndFilings.map((filing) => ( ))}
Filed Period Type Revenue Net Income Assets Document
{format(new Date(filing.filing_date), 'MMM dd, yyyy')} {filing.filing_type === '10-Q' ? 'Quarter End' : 'Fiscal Year End'} {filing.filing_type} {asScaledFinancialCurrency(filing.metrics?.revenue, financialValueScale)} {asScaledFinancialCurrency(filing.metrics?.netIncome, financialValueScale)} {asScaledFinancialCurrency(filing.metrics?.totalAssets, financialValueScale)} {filing.filing_url ? ( SEC filing ) : ( 'n/a' )}
)}
{loading ? (

Loading AI reports...

) : !analysis || analysis.aiReports.length === 0 ? (

No AI reports generated yet. Run filing analysis from the filings stream.

) : (
{analysis.aiReports.map((report) => (

{report.filingType} ยท {format(new Date(report.filingDate), 'MMM dd, yyyy')}

{report.provider} / {report.model}

{report.summary}

{report.accessionNumber}

prefetchReport(analysis.company.ticker, report.accessionNumber)} onFocus={() => prefetchReport(analysis.company.ticker, report.accessionNumber)} className="text-xs uppercase tracking-[0.12em] text-[color:var(--accent)] hover:text-[color:var(--accent-strong)]" > Open summary
))}
)}
Analysis scope: price + filings + ai synthesis
); }