import dynamic from 'next/dynamic';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useSelector } from 'react-redux';
import type { ApexOptions } from 'apexcharts';

import { IRootState } from '@/store';
import { getThemeChartColors, getThemeChartFont } from '@/lib/theme-colors';
import type { JourneyStats } from './JourneyStatsPanel';
import { journeyChartGrid, journeyChartInteract } from './journey-chart-options';
import styles from './journey-overview-snapshot.module.css';
import { useJourneyCountMode } from './JourneyCountModeContext';

const ReactApexChart = dynamic(() => import('react-apexcharts'), { ssr: false });

const POLL_MS = 10_000;

export type JourneyRealtimeSnapshot = {
    ok?: boolean;
    source?: 'redis' | 'mongo' | string;
    window_minutes?: number;
    active_users_now?: number;
    active_users_30m?: number;
    per_minute?: { minute_offset?: number; active_users: number }[];
    by_entry_path?: { path: string; active_users: number }[];
    active_users?: {
        visitor_id: string;
        visitor_ref?: string;
        session_id?: string;
        path: string;
        entry_page: string;
        last_seen_at: string;
        last_active_at?: string;
    }[];
    redis?: { ready?: boolean; status?: string };
    generated_at?: string;
};

type MetricId = 'event_count' | 'active_users' | 'engaged_sessions' | 'purchases';

const METRIC_OPTIONS: { id: MetricId; label: string }[] = [
    { id: 'event_count', label: 'Event count' },
    { id: 'active_users', label: 'Active users' },
    { id: 'engaged_sessions', label: 'Engaged sessions' },
    { id: 'purchases', label: 'Purchases' },
];

const DEFAULT_SLOTS: MetricId[] = ['event_count', 'active_users', 'engaged_sessions', 'purchases'];

function formatCompact(n: number) {
    const v = Number(n) || 0;
    if (Math.abs(v) >= 1_000_000) return `${(v / 1_000_000).toFixed(1)}M`;
    if (Math.abs(v) >= 1_000) return `${(v / 1_000).toFixed(1)}K`;
    return v.toLocaleString('id-ID');
}

function changeClass(pct: number) {
    if (pct > 0) return styles.changeUp;
    if (pct < 0) return styles.changeDown;
    return styles.changeFlat;
}

function formatChange(pct: number) {
    const sign = pct > 0 ? '+' : '';
    return `${sign}${pct.toFixed(1)}%`;
}

type Props = {
    statsData: JourneyStats;
    onNavigate?: (section: 'acquisition' | 'sessions' | 'realtime') => void;
    compareEnabled?: boolean;
    compareStatsData?: JourneyStats | null;
};

const JourneyOverviewSnapshot = ({
    statsData,
    onNavigate,
    compareEnabled = false,
    compareStatsData = null,
}: Props) => {
    const countMode = useJourneyCountMode();
    const isUsers = countMode === 'users';
    const isDark = useSelector(
        (state: IRootState) => state.themeConfig.theme === 'dark' || state.themeConfig.isDarkMode
    );
    const colorScheme = useSelector((state: IRootState) => state.themeConfig.colorScheme);
    const chartColors = getThemeChartColors(colorScheme);
    const [slots, setSlots] = useState<MetricId[]>(DEFAULT_SLOTS);
    const [chartMetric, setChartMetric] = useState<MetricId>('active_users');
    const [realtime, setRealtime] = useState<JourneyRealtimeSnapshot | null>(null);
    const [realtimeError, setRealtimeError] = useState('');

    const snapshot = statsData.overview_snapshot;
    const snapshotCompare = Boolean(snapshot?.previous);
    const showCompare = compareEnabled || snapshotCompare;

    const previousRangeLabel = compareStatsData?.filters
        ? `${compareStatsData.filters.date_from} → ${compareStatsData.filters.date_to}`
        : snapshot?.previous_range
          ? `${snapshot.previous_range.from} → ${snapshot.previous_range.to}`
          : '';

    const fetchRealtime = useCallback(async () => {
        if (typeof document !== 'undefined' && document.visibilityState === 'hidden') return;
        try {
            const api_url = process.env.API_URL;
            const res = await fetch(`${api_url}api/journey/realtime`, {
                method: 'GET',
                headers: { 'Content-Type': 'application/json' },
                credentials: 'include',
            });
            const data = await res.json();
            if (!res.ok) throw new Error(data?.message || 'Gagal memuat realtime');
            setRealtime(data);
            setRealtimeError('');
        } catch (err: any) {
            setRealtimeError(err?.message || 'Realtime unavailable');
        }
    }, []);

    useEffect(() => {
        fetchRealtime();
        const id = window.setInterval(fetchRealtime, POLL_MS);
        const onVis = () => {
            if (document.visibilityState === 'visible') fetchRealtime();
        };
        document.addEventListener('visibilitychange', onVis);
        return () => {
            window.clearInterval(id);
            document.removeEventListener('visibilitychange', onVis);
        };
    }, [fetchRealtime]);

    const metricLabel = (id: MetricId) => {
        if (id === 'engaged_sessions') return isUsers ? 'Engaged users' : 'Engaged sessions';
        if (id === 'purchases') return 'Purchases';
        if (id === 'active_users') return 'Active users';
        return 'Event count';
    };

    const seriesKey = (id: MetricId) => {
        if (isUsers && id === 'purchases') return 'purchases_orders';
        if (isUsers && id === 'engaged_sessions') return 'engaged_users';
        return id;
    };

    const metricValue = (id: MetricId) => {
        const cur = snapshot?.current as Record<string, number> | undefined;
        const key = seriesKey(id);
        if (cur && typeof cur[key] === 'number') return cur[key];
        if (id === 'event_count') return statsData.overview.total_event_count || 0;
        if (id === 'active_users') return statsData.overview.unique_visitors || 0;
        if (id === 'engaged_sessions') {
            return isUsers ? statsData.overview.engaged_users || 0 : statsData.overview.engaged_sessions || 0;
        }
        return isUsers ? statsData.funnel.users?.purchase || 0 : statsData.funnel.purchase || 0;
    };

    const compareMetricValue = (id: MetricId) => {
        if (!showCompare) return null;

        if (compareStatsData) {
            const snap = compareStatsData.overview_snapshot?.current as Record<string, number> | undefined;
            const key = seriesKey(id);
            if (snap && typeof snap[key] === 'number') return snap[key];
            if (id === 'event_count') return compareStatsData.overview.total_event_count || 0;
            if (id === 'active_users') return compareStatsData.overview.unique_visitors || 0;
            if (id === 'engaged_sessions') {
                return isUsers
                    ? compareStatsData.overview.engaged_users || 0
                    : compareStatsData.overview.engaged_sessions || 0;
            }
            return isUsers
                ? compareStatsData.funnel.users?.purchase || 0
                : compareStatsData.funnel.purchase || 0;
        }

        const prev = snapshot?.previous as Record<string, number> | undefined;
        const key = seriesKey(id);
        if (prev && typeof prev[key] === 'number') return prev[key];
        return null;
    };

    const metricChange = (id: MetricId) => {
        if (!showCompare) return 0;

        const change = snapshot?.change_percent as Record<string, number> | undefined;
        const changeKey = seriesKey(id);
        if (change && typeof change[changeKey] === 'number') {
            return change[changeKey];
        }
        if (change && id === 'purchases' && typeof change.purchases === 'number') {
            return change.purchases;
        }

        const current = metricValue(id);
        const previous = compareMetricValue(id);
        if (previous == null) return 0;
        if (previous === 0) return current > 0 ? 100 : 0;
        return Math.round(((current - previous) / previous) * 1000) / 10;
    };

    const chartOptions = useMemo<ApexOptions>(() => {
        const currentDays = snapshot?.series?.current?.days || [];
        const prevDays = showCompare
            ? compareStatsData?.overview_snapshot?.series?.current?.days ||
              snapshot?.series?.previous?.days ||
              []
            : [];
        const categories =
            currentDays.length >= prevDays.length
                ? currentDays.map((_, i) => String(i + 1))
                : prevDays.map((_, i) => String(i + 1));

        return {
            chart: {
                type: 'line',
                fontFamily: getThemeChartFont(colorScheme),
                ...journeyChartInteract,
            },
            stroke: {
                width: showCompare ? [3, 2] : [3],
                curve: 'smooth',
                dashArray: showCompare ? [0, 6] : [0],
            },
            colors: [chartColors[0], chartColors[1] || '#90caf9'],
            dataLabels: { enabled: false },
            grid: journeyChartGrid(isDark),
            xaxis: {
                categories,
                labels: { style: { colors: '#5f6368', fontSize: '11px' } },
                axisBorder: { show: false },
                axisTicks: { show: false },
            },
            yaxis: {
                labels: {
                    style: { colors: '#5f6368', fontSize: '11px' },
                    formatter: (v) => formatCompact(Number(v)),
                },
            },
            legend: {
                show: showCompare,
                position: 'top',
                horizontalAlign: 'left',
                fontSize: '12px',
            },
            tooltip: {
                shared: true,
                y: { formatter: (v) => (Number(v) || 0).toLocaleString('id-ID') },
            },
        };
    }, [snapshot, showCompare, compareStatsData, isDark, chartColors, colorScheme]);

    const chartSeries = useMemo(() => {
        const key = seriesKey(chartMetric);
        const currentSeries = snapshot?.series?.current as Record<string, number[] | string[]> | undefined;
        const prevSeries = (
            compareStatsData?.overview_snapshot?.series?.current ||
            snapshot?.series?.previous
        ) as Record<string, number[] | string[]> | undefined;
        const cur =
            (currentSeries?.[key] as number[]) ||
            (currentSeries?.[chartMetric] as number[]) ||
            [];
        const prev = showCompare
            ? (prevSeries?.[key] as number[]) || (prevSeries?.[chartMetric] as number[]) || []
            : [];
        const len = Math.max(cur.length, prev.length, 1);
        const pad = (arr: number[]) => Array.from({ length: len }, (_, i) => Number(arr[i]) || 0);
        const series: { name: string; data: number[] }[] = [{ name: 'Periode ini', data: pad(cur) }];
        if (showCompare) {
            series.push({ name: 'Compare period', data: pad(prev) });
        }
        return series;
    }, [snapshot, chartMetric, showCompare, compareStatsData, isUsers]);

    const perMinute = realtime?.per_minute || [];
    const maxPerMin = Math.max(...perMinute.map((p) => p.active_users || 0), 1);
    const entryRows = realtime?.by_entry_path || [];
    const maxEntry = Math.max(...entryRows.map((r) => r.active_users || 0), 1);
    const active30 = realtime?.active_users_30m ?? realtime?.active_users_now ?? 0;

    return (
        <div className={styles.grid}>
            <section className={styles.card} style={{ gridColumn: 'span 2' }}>
                <div className={styles.metricsRow}>
                    {slots.map((slotId, idx) => (
                        <div key={`${slotId}-${idx}`} className={styles.metricCell}>
                            <select
                                className={styles.metricSelect}
                                value={slotId}
                                onChange={(e) => {
                                    const next = e.target.value as MetricId;
                                    setSlots((prev) => {
                                        const copy = [...prev];
                                        copy[idx] = next;
                                        return copy;
                                    });
                                    if (idx === 1) setChartMetric(next);
                                }}
                            >
                                {METRIC_OPTIONS.map((opt) => (
                                    <option key={opt.id} value={opt.id}>
                                        {metricLabel(opt.id)}
                                    </option>
                                ))}
                            </select>
                            <div className={styles.metricValue}>{formatCompact(metricValue(slotId))}</div>
                            {showCompare ? (
                                <>
                                    <div className="text-[11px] text-gray-400">
                                        vs {formatCompact(compareMetricValue(slotId) || 0)}
                                    </div>
                                    <div className={`${styles.metricChange} ${changeClass(metricChange(slotId))}`}>
                                        {formatChange(metricChange(slotId))}
                                    </div>
                                </>
                            ) : null}
                        </div>
                    ))}
                </div>

                <div className={styles.chartHead}>
                    <select
                        className={styles.metricSelect}
                        value={chartMetric}
                        onChange={(e) => setChartMetric(e.target.value as MetricId)}
                    >
                        {METRIC_OPTIONS.map((opt) => (
                            <option key={opt.id} value={opt.id}>
                                Chart: {metricLabel(opt.id)}
                            </option>
                        ))}
                    </select>
                    {showCompare && previousRangeLabel ? (
                        <span className={styles.muted}>vs {previousRangeLabel}</span>
                    ) : null}
                </div>

                <div className={styles.chartWrap}>
                    <ReactApexChart options={chartOptions} series={chartSeries} type="line" height={220} />
                </div>

                <div className={styles.footer}>
                    <button
                        type="button"
                        className={styles.linkBtn}
                        onClick={() => onNavigate?.('acquisition')}
                    >
                        View reports snapshot →
                    </button>
                </div>
            </section>
       

            <section
                className={styles.card}
                
            >
                <div className={styles.rtHeader}>
                    <div>
                        <div className={styles.rtEyebrow}>Active users in last 30 minutes</div>
                        <div className={styles.rtBig}>{active30.toLocaleString('id-ID')}</div>
                    </div>
                    <div className={styles.rtMeta}>
                        <span className={styles.sourcePill}>
                            {realtime?.source === 'redis' ? 'Redis' : realtime?.source === 'mongo' ? 'Mongo fallback' : '…'}
                        </span>
                        {realtime?.active_users_now != null ? (
                            <span className={styles.muted}>now {realtime.active_users_now}</span>
                        ) : null}
                    </div>
                </div>

                <div className={styles.rtSubtitle}>Active users per minute</div>
                <div className={styles.minuteBars} aria-hidden>
                    {perMinute.map((p, i) => (
                        <div
                            key={i}
                            className={styles.minuteBar}
                            style={{ height: `${Math.max(4, ((p.active_users || 0) / maxPerMin) * 100)}%` }}
                            title={`${p.active_users || 0}`}
                        />
                    ))}
                    {!perMinute.length ? <div className={styles.emptyMini}>Data Not Available</div> : null}
                </div>

                <div className={styles.tableHead}>
                    <span>Entry path</span>
                    <span>Active users</span>
                </div>
                <div className={styles.tableBody}>
                    {entryRows.length ? (
                        entryRows.map((row) => (
                            <div key={row.path} className={styles.tableRow}>
                                <span className={styles.pathCell} title={row.path}>
                                    {row.path}
                                </span>
                                <span className={styles.barCell}>
                                    <span
                                        className={styles.shareBar}
                                        style={{ width: `${((row.active_users || 0) / maxEntry) * 100}%` }}
                                    />
                                    <strong>{row.active_users}</strong>
                                </span>
                            </div>
                        ))
                    ) : (
                        <div className={styles.emptyMini}>
                            {realtimeError || 'No active users'}
                        </div>
                    )}
                </div>

                <div className={styles.footer}>
                    <button
                        type="button"
                        className={styles.linkBtn}
                        onClick={() => onNavigate?.('realtime')}
                    >
                        View realtime →
                    </button>
                </div>
            </section>
     
        </div>
    );
};

export default JourneyOverviewSnapshot;
