// IvantiCountsChart.js
// Collapsible trend panel for the Vulnerability Triage page.
// Shows open vs closed Ivanti finding counts over time (last sync per day),
// with a separate sparkline row for archived/returned finding activity.

import React, { useState, useEffect, useMemo } from 'react';
import {
    LineChart, Line,
    BarChart, Bar, Cell,
    XAxis, YAxis, CartesianGrid,
    Tooltip, Legend,
    ResponsiveContainer,
} from 'recharts';
import { TrendingUp, ChevronDown, ChevronUp, Loader } from 'lucide-react';

const API_BASE = process.env.REACT_APP_API_BASE || 'http://localhost:3001/api';

const AMBER  = '#F59E0B';
const SKY    = '#0EA5E9';
const GREEN  = '#10B981';
const RED    = '#EF4444';
const ROSE   = '#F43F5E';
const TEAL   = '#14B8A6';

const AXIS_STYLE   = { fontFamily: 'monospace', fontSize: '0.6rem', fill: '#475569' };
const GRID_STYLE   = { stroke: 'rgba(255,255,255,0.05)', strokeDasharray: '3 3' };
const LEGEND_STYLE = { fontFamily: 'monospace', fontSize: '0.62rem', color: '#64748B' };

// ---------------------------------------------------------------------------
// Custom dark tooltip — main trend chart
// ---------------------------------------------------------------------------
function DarkTooltip({ active, payload, label }) {
    if (!active || !payload?.length) return null;

    const openVal   = payload.find(p => p.dataKey === 'open_count')?.value;
    const closedVal = payload.find(p => p.dataKey === 'closed_count')?.value;

    return (
        <div style={{
            background: 'rgba(10,17,32,0.97)',
            border: '1px solid rgba(245,158,11,0.3)',
            borderRadius: '0.375rem',
            padding: '0.5rem 0.75rem',
            fontFamily: 'monospace',
            fontSize: '0.7rem',
            minWidth: '160px',
        }}>
            <div style={{ color: AMBER, marginBottom: '0.35rem', fontWeight: '700', fontSize: '0.65rem' }}>
                {label}
            </div>
            {payload.map(p => (
                <div key={p.dataKey} style={{ color: p.color, marginTop: '0.125rem', display: 'flex', justifyContent: 'space-between', gap: '1rem' }}>
                    <span style={{ opacity: 0.8 }}>{p.name}</span>
                    <span style={{ fontWeight: '700' }}>{p.value}</span>
                </div>
            ))}
            {openVal != null && closedVal != null && (
                <div style={{ borderTop: '1px solid rgba(255,255,255,0.06)', marginTop: '0.35rem', paddingTop: '0.3rem', color: '#475569', display: 'flex', justifyContent: 'space-between', gap: '1rem' }}>
                    <span>total</span>
                    <span style={{ color: '#64748B', fontWeight: '600' }}>{openVal + closedVal}</span>
                </div>
            )}
        </div>
    );
}

// ---------------------------------------------------------------------------
// Custom dark tooltip — archive activity sparkline
// ---------------------------------------------------------------------------
function ArchiveTooltip({ active, payload, label }) {
    if (!active || !payload?.length) return null;

    const archived = payload.find(p => p.dataKey === 'archived')?.value || 0;
    const returned = payload.find(p => p.dataKey === 'returned')?.value || 0;

    // Parse classification if present
    const dataPoint = payload[0]?.payload;
    const classification = dataPoint?.classification;
    const returnClassification = dataPoint?.return_classification;

    return (
        <div style={{
            background: 'rgba(10,17,32,0.97)',
            border: '1px solid rgba(244,63,94,0.3)',
            borderRadius: '0.375rem',
            padding: '0.5rem 0.75rem',
            fontFamily: 'monospace',
            fontSize: '0.7rem',
            minWidth: '180px',
        }}>
            <div style={{ color: ROSE, marginBottom: '0.35rem', fontWeight: '700', fontSize: '0.65rem' }}>
                {label}
            </div>
            {archived > 0 && (
                <div style={{ color: ROSE, marginTop: '0.125rem', display: 'flex', justifyContent: 'space-between', gap: '1rem' }}>
                    <span style={{ opacity: 0.8 }}>Archived</span>
                    <span style={{ fontWeight: '700' }}>{archived}</span>
                </div>
            )}
            {returned > 0 && (
                <div style={{ color: TEAL, marginTop: '0.125rem', display: 'flex', justifyContent: 'space-between', gap: '1rem' }}>
                    <span style={{ opacity: 0.8 }}>Returned</span>
                    <span style={{ fontWeight: '700' }}>{returned}</span>
                </div>
            )}
            {archived === 0 && returned === 0 && (
                <div style={{ color: '#475569', marginTop: '0.125rem' }}>No archive activity</div>
            )}
            {classification && archived > 0 && (
                <div style={{ borderTop: '1px solid rgba(255,255,255,0.06)', marginTop: '0.35rem', paddingTop: '0.3rem' }}>
                    {classification.bu_reassignment > 0 && (
                        <div style={{ color: '#FB923C', fontSize: '0.62rem', display: 'flex', justifyContent: 'space-between', gap: '1rem' }}>
                            <span style={{ opacity: 0.8 }}>BU reassignment</span>
                            <span>{classification.bu_reassignment}</span>
                        </div>
                    )}
                    {classification.severity_drift > 0 && (
                        <div style={{ color: '#A78BFA', fontSize: '0.62rem', display: 'flex', justifyContent: 'space-between', gap: '1rem' }}>
                            <span style={{ opacity: 0.8 }}>Severity drift</span>
                            <span>{classification.severity_drift}</span>
                        </div>
                    )}
                    {classification.closed_on_platform > 0 && (
                        <div style={{ color: SKY, fontSize: '0.62rem', display: 'flex', justifyContent: 'space-between', gap: '1rem' }}>
                            <span style={{ opacity: 0.8 }}>Closed on platform</span>
                            <span>{classification.closed_on_platform}</span>
                        </div>
                    )}
                    {classification.decommissioned > 0 && (
                        <div style={{ color: '#94A3B8', fontSize: '0.62rem', display: 'flex', justifyContent: 'space-between', gap: '1rem' }}>
                            <span style={{ opacity: 0.8 }}>Decommissioned</span>
                            <span>{classification.decommissioned}</span>
                        </div>
                    )}
                </div>
            )}
            {returnClassification && returned > 0 && (returnClassification.bu_reassignment > 0 || returnClassification.severity_drift > 0 || returnClassification.closed_on_platform > 0 || returnClassification.decommissioned > 0) && (
                <div style={{ borderTop: '1px solid rgba(255,255,255,0.06)', marginTop: '0.35rem', paddingTop: '0.3rem' }}>
                    <div style={{ color: '#475569', fontSize: '0.58rem', textTransform: 'uppercase', letterSpacing: '0.06em', marginBottom: '0.2rem' }}>
                        Returned because
                    </div>
                    {returnClassification.bu_reassignment > 0 && (
                        <div style={{ color: '#FB923C', fontSize: '0.62rem', display: 'flex', justifyContent: 'space-between', gap: '1rem' }}>
                            <span style={{ opacity: 0.8 }}>BU reassigned back</span>
                            <span>{returnClassification.bu_reassignment}</span>
                        </div>
                    )}
                    {returnClassification.severity_drift > 0 && (
                        <div style={{ color: '#A78BFA', fontSize: '0.62rem', display: 'flex', justifyContent: 'space-between', gap: '1rem' }}>
                            <span style={{ opacity: 0.8 }}>Severity re-escalated</span>
                            <span>{returnClassification.severity_drift}</span>
                        </div>
                    )}
                    {returnClassification.closed_on_platform > 0 && (
                        <div style={{ color: SKY, fontSize: '0.62rem', display: 'flex', justifyContent: 'space-between', gap: '1rem' }}>
                            <span style={{ opacity: 0.8 }}>Reopened on platform</span>
                            <span>{returnClassification.closed_on_platform}</span>
                        </div>
                    )}
                    {returnClassification.decommissioned > 0 && (
                        <div style={{ color: '#94A3B8', fontSize: '0.62rem', display: 'flex', justifyContent: 'space-between', gap: '1rem' }}>
                            <span style={{ opacity: 0.8 }}>Re-provisioned</span>
                            <span>{returnClassification.decommissioned}</span>
                        </div>
                    )}
                </div>
            )}
        </div>
    );
}

// ---------------------------------------------------------------------------
// Shorten YYYY-MM-DD (or ISO datetime) to MM/DD/YY
// ---------------------------------------------------------------------------
function fmtDate(d) {
    if (!d) return '';
    // Handle ISO datetime strings (e.g. "2026-05-12T06:00:00.000Z") — extract date part first
    const dateStr = String(d).split('T')[0];
    const p = dateStr.split('-');
    if (p.length === 3) return `${p[1]}/${p[2]}/${p[0].slice(2)}`;
    return dateStr;
}

// Extract YYYY-MM-DD from a datetime string
function extractDate(ts) {
    if (!ts) return '';
    return ts.split('T')[0].split(' ')[0];
}

// ---------------------------------------------------------------------------
// Main component
// ---------------------------------------------------------------------------
export default function IvantiCountsChart({ teamsParam }) {
    const [collapsed, setCollapsed] = useState(false);
    const [loading,   setLoading]   = useState(true);
    const [history,   setHistory]   = useState([]);
    const [anomalies, setAnomalies] = useState([]);

    useEffect(() => {
        let cancelled = false;
        const load = async () => {
            setLoading(true);
            try {
                const historyUrl = teamsParam
                    ? `${API_BASE}/ivanti/findings/counts/history?teams=${encodeURIComponent(teamsParam)}`
                    : `${API_BASE}/ivanti/findings/counts/history`;
                const [countsRes, anomalyRes] = await Promise.all([
                    fetch(historyUrl, { credentials: 'include' }),
                    fetch(`${API_BASE}/ivanti/findings/anomaly/history`, { credentials: 'include' }),
                ]);
                if (!cancelled) {
                    if (countsRes.ok) {
                        const d = await countsRes.json();
                        setHistory(d.history || []);
                    }
                    if (anomalyRes.ok) {
                        const d = await anomalyRes.json();
                        setAnomalies(d.history || []);
                    }
                }
            } catch { /* silent — chart shows no-data state */ }
            finally { if (!cancelled) setLoading(false); }
        };
        load();
        return () => { cancelled = true; };
    }, [teamsParam]);

    const chartData = useMemo(
        () => history.map(r => ({ ...r, date: fmtDate(r.date) })),
        [history]
    );

    // Build archive activity data aligned to the same date axis as the main chart.
    // Aggregate anomaly rows by date — sum archived/returned counts and merge
    // classifications across all syncs that day, then align to the chartData dates.
    const archiveData = useMemo(() => {
        if (!anomalies.length || !chartData.length) return [];

        // Aggregate all anomaly rows per date (sum counts, merge classifications)
        const byDate = {};
        for (const a of anomalies) {
            const rawDate = extractDate(a.sync_timestamp);
            const dateKey = fmtDate(rawDate);
            if (!byDate[dateKey]) {
                byDate[dateKey] = {
                    archived: 0,
                    returned: 0,
                    classification: {},
                    return_classification: {},
                    is_significant: false,
                };
            }
            const entry = byDate[dateKey];
            entry.archived += (a.newly_archived_count || 0);
            entry.returned += (a.returned_count || 0);
            if (a.is_significant) entry.is_significant = true;

            // Merge classification counts
            for (const [key, val] of Object.entries(a.classification || {})) {
                entry.classification[key] = (entry.classification[key] || 0) + (val || 0);
            }
            for (const [key, val] of Object.entries(a.return_classification || {})) {
                entry.return_classification[key] = (entry.return_classification[key] || 0) + (val || 0);
            }
        }

        // Map onto the chart date axis so both charts share the same X positions
        return chartData.map(point => {
            const agg = byDate[point.date];
            if (agg) {
                return { date: point.date, ...agg };
            }
            return { date: point.date, archived: 0, returned: 0, classification: {}, return_classification: {}, is_significant: false };
        });
    }, [anomalies, chartData]);

    // Check if there's any archive activity worth showing
    const hasArchiveActivity = useMemo(
        () => archiveData.some(d => d.archived > 0 || d.returned > 0),
        [archiveData]
    );

    // Compute a simple delta label for the latest vs previous point
    const deltaLabel = useMemo(() => {
        if (chartData.length < 2) return null;
        const latest = chartData[chartData.length - 1];
        const prev   = chartData[chartData.length - 2];
        const delta  = latest.open_count - prev.open_count;
        if (delta === 0) return { text: 'no change in open', color: '#475569' };
        if (delta < 0)   return { text: `▼ ${Math.abs(delta)} open since ${prev.date}`, color: GREEN };
        return             { text: `▲ ${delta} open since ${prev.date}`, color: RED };
    }, [chartData]);

    return (
        <div style={{ marginBottom: '1.25rem' }}>

            {/* ── Header ────────────────────────────────────────────────── */}
            <button
                onClick={() => setCollapsed(c => !c)}
                style={{
                    width: '100%', display: 'flex', alignItems: 'center', justifyContent: 'space-between',
                    background: 'none', border: 'none', cursor: 'pointer',
                    padding: '0 0 0.625rem 0',
                    borderBottom: collapsed ? 'none' : '1px solid rgba(245,158,11,0.1)',
                    marginBottom: collapsed ? 0 : '0.875rem',
                }}
            >
                <div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
                    <TrendingUp style={{ width: '14px', height: '14px', color: AMBER }} />
                    <span style={{
                        fontFamily: 'monospace', fontSize: '0.65rem', fontWeight: '700',
                        color: '#334155', textTransform: 'uppercase', letterSpacing: '0.1em',
                    }}>
                        Findings Trend
                    </span>
                    {loading && (
                        <Loader style={{ width: '12px', height: '12px', color: '#334155', animation: 'spin 1s linear infinite' }} />
                    )}
                    {!loading && deltaLabel && (
                        <span style={{ fontFamily: 'monospace', fontSize: '0.62rem', color: deltaLabel.color, marginLeft: '0.25rem' }}>
                            {deltaLabel.text}
                        </span>
                    )}
                </div>
                {collapsed
                    ? <ChevronDown style={{ width: '14px', height: '14px', color: '#334155' }} />
                    : <ChevronUp   style={{ width: '14px', height: '14px', color: '#334155' }} />
                }
            </button>

            {!collapsed && (
                <div style={{
                    background: 'linear-gradient(135deg,rgba(30,41,59,0.95) 0%,rgba(15,23,42,0.98) 100%)',
                    border: '1px solid rgba(245,158,11,0.15)',
                    borderRadius: '0.5rem',
                    padding: '1rem 1.25rem 0.875rem',
                }}>
                    <div style={{ marginBottom: '0.625rem', display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
                        <div style={{ fontFamily: 'monospace', fontSize: '0.65rem', color: '#334155', textTransform: 'uppercase', letterSpacing: '0.08em' }}>
                            Open vs Closed — end-of-day snapshot per sync day
                        </div>
                        {chartData.length > 0 && (
                            <div style={{ fontFamily: 'monospace', fontSize: '0.62rem', color: '#334155' }}>
                                {chartData.length} day{chartData.length !== 1 ? 's' : ''} of data
                            </div>
                        )}
                    </div>

                    {chartData.length < 2 ? (
                        <div style={{
                            display: 'flex', alignItems: 'center', justifyContent: 'center',
                            height: '160px', color: '#334155',
                            fontFamily: 'monospace', fontSize: '0.72rem',
                            border: '1px dashed rgba(245,158,11,0.1)', borderRadius: '0.375rem',
                        }}>
                            {chartData.length === 0
                                ? 'Trend data begins accumulating after the first sync — check back tomorrow'
                                : 'Need at least 2 days of syncs to display a trend'}
                        </div>
                    ) : (
                        <>
                            {/* ── Main trend chart ──────────────────────── */}
                            <ResponsiveContainer width="100%" height={220}>
                                <LineChart data={chartData} margin={{ top: 4, right: 12, bottom: 0, left: -12 }}>
                                    <CartesianGrid {...GRID_STYLE} />
                                    <XAxis dataKey="date" tick={AXIS_STYLE} />
                                    <YAxis tick={AXIS_STYLE} allowDecimals={false} />
                                    <Tooltip content={<DarkTooltip />} />
                                    <Legend wrapperStyle={LEGEND_STYLE} iconSize={8} />
                                    <Line
                                        type="monotone" dataKey="open_count" name="Open"
                                        stroke={AMBER} strokeWidth={2}
                                        dot={{ r: 3, fill: AMBER, strokeWidth: 0 }}
                                        activeDot={{ r: 5 }}
                                    />
                                    <Line
                                        type="monotone" dataKey="closed_count" name="Closed"
                                        stroke={SKY} strokeWidth={2}
                                        dot={{ r: 3, fill: SKY, strokeWidth: 0 }}
                                        activeDot={{ r: 5 }}
                                    />
                                </LineChart>
                            </ResponsiveContainer>

                            {/* ── Archive activity sparkline ────────────── */}
                            {hasArchiveActivity && (
                                <div style={{ marginTop: '0.5rem' }}>
                                    <div style={{
                                        fontFamily: 'monospace', fontSize: '0.58rem', color: '#334155',
                                        textTransform: 'uppercase', letterSpacing: '0.08em',
                                        marginBottom: '0.25rem',
                                    }}>
                                        Archive Activity
                                    </div>
                                    <ResponsiveContainer width="100%" height={80}>
                                        <BarChart data={archiveData} margin={{ top: 2, right: 12, bottom: 0, left: -12 }}>
                                            <CartesianGrid {...GRID_STYLE} />
                                            <XAxis dataKey="date" tick={false} axisLine={false} />
                                            <YAxis tick={AXIS_STYLE} allowDecimals={false} width={30} />
                                            <Tooltip content={<ArchiveTooltip />} />
                                            <Bar dataKey="archived" name="Archived" stackId="a" maxBarSize={14}>
                                                {archiveData.map((entry, idx) => (
                                                    <Cell
                                                        key={`arch-${idx}`}
                                                        fill={entry.is_significant ? ROSE : 'rgba(244,63,94,0.5)'}
                                                    />
                                                ))}
                                            </Bar>
                                            <Bar dataKey="returned" name="Returned" stackId="a" maxBarSize={14}>
                                                {archiveData.map((entry, idx) => (
                                                    <Cell
                                                        key={`ret-${idx}`}
                                                        fill={TEAL}
                                                    />
                                                ))}
                                            </Bar>
                                        </BarChart>
                                    </ResponsiveContainer>
                                </div>
                            )}
                        </>
                    )}
                </div>
            )}
        </div>
    );
}
