components/ui/tradingPerformanceChart/TradingPerformanceChart.jsx

import React, {useEffect, useMemo, useState} from 'react';
import {useTranslation} from 'react-i18next';
import {Line} from 'react-chartjs-2';
import {
    BarController,
    BarElement,
    CategoryScale,
    Chart as ChartJS,
    Filler,
    Legend,
    LinearScale,
    LineElement,
    PointElement,
    Tooltip,
} from 'chart.js';
import {SelectableButton} from "../selectableButton/SelectableButton";

ChartJS.register(
    CategoryScale,
    LinearScale,
    PointElement,
    LineElement,
    Tooltip,
    Legend,
    Filler,
    BarElement,
    BarController
);


/**
 * TradingPerformanceChart component renders a combined line and bar chart showing
 * trading returns performance, either on a monthly or annual basis, with support for
 * light and dark themes.
 *
 * The component reacts to changes in the `dark` CSS class on the document element
 * to dynamically update chart colors. Users can switch between monthly and annual
 * views via a select dropdown. Below the chart, a summary section displays detailed
 * returns with positive values in green and negative values in red.
 *
 * Translations are supported via `react-i18nex
 *
 * @component
 * @module components/ui/tradingPerformanceChart/TradingPerformanceChart
 *
 * @param {Object} props - Component props.
 * @param {number} [props.startYear=2022] - The first year of the dataset.
 * @param {Array<number | null>} [props.monthlyReturns=Array(12).fill(0)] - Array of monthly returns.
 *    Each entry represents the return for a month in percent. Use `null` for missing data.
 *
 * @returns {JSX.Element} The trading performance chart section.
 */
export function TradingPerformanceChart({
                                            startYear = 2022,
                                            monthlyReturns = Array(12).fill(0) // 12 months of default at 0%
                                        }) {
    const {t} = useTranslation();

// --- States ---
    const [selectedYear, setSelectedYear] = useState("2026");
    const [isDark, setIsDark] = useState(() =>
        document.documentElement.classList.contains('dark')
    );
    const [view, setView] = useState('monthly');
    const [windowWidth, setWindowWidth] = useState(
        typeof window !== 'undefined' ? window.innerWidth : 1024
    );

// --- Effects ---
// Dark mode observer
    useEffect(() => {
        const observer = new MutationObserver(() =>
            setIsDark(document.documentElement.classList.contains('dark'))
        );
        observer.observe(document.documentElement, {attributes: true, attributeFilter: ['class']});
        return () => observer.disconnect();
    }, []);

// Window resize listener
    useEffect(() => {
        if (typeof window === 'undefined') return;
        const handleResize = () => setWindowWidth(window.innerWidth);
        window.addEventListener('resize', handleResize);
        return () => window.removeEventListener('resize', handleResize);
    }, []);

// --- Helper functions ---
    const calcAnnualReturn = (months) => {
        const valid = months.filter((r) => r != null);
        let capital = 1;
        valid.forEach((r) => (capital *= 1 + r / 100));
        return +((capital - 1) * 100).toFixed(2);
    };

    const getCumulativeSum = (returns) => {
        let capital = 100;
        return returns.map((r) => {
            if (r == null) return null;
            capital *= 1 + r / 100;
            return +(capital - 100).toFixed(2);
        });
    };

// --- Derived values ---
    const totalMonths = monthlyReturns.length;
    const lastMonthIndex = totalMonths - 1;
    const currentYear = startYear + Math.floor(lastMonthIndex / 12);

    const months = useMemo(() => [
        t('months.jan'), t('months.feb'), t('months.mar'), t('months.apr'),
        t('months.may'), t('months.jun'), t('months.jul'), t('months.aug'),
        t('months.sep'), t('months.oct'), t('months.nov'), t('months.dec')
    ], [t]);

    const allYears = useMemo(
        () => Array.from({length: currentYear - startYear + 1}, (_, i) => startYear + i),
        [startYear, currentYear]
    );

    const annualLabels = useMemo(() =>
            allYears.map((y, idx) => {
                const validMonths = monthlyReturns.slice(idx * 12, (idx + 1) * 12).filter(v => v != null).length;
                return validMonths < 12 ? `${y} (${t('partial')})` : String(y);
            }),
        [allYears, monthlyReturns, t]
    );

    const annualReturns = useMemo(
        () => allYears.map((_, i) => calcAnnualReturn(monthlyReturns.slice(i * 12, i * 12 + 12))),
        [allYears, monthlyReturns]
    );

    const isMonthly = view === 'monthly';

    const dataSet = useMemo(() => (isMonthly ? monthlyReturns : annualReturns), [isMonthly, monthlyReturns, annualReturns]);

    const labels = useMemo(() => isMonthly
            ? allYears.flatMap((year, idx) => {
                const start = idx * 12;
                const remaining = monthlyReturns.slice(start, start + 12).filter(v => v != null);
                return remaining.map((_, i) => `${months[i]} ${year}`);
            })
            : annualLabels,
        [isMonthly, allYears, monthlyReturns, months, annualLabels]
    );

    const cumulative = useMemo(() => getCumulativeSum(dataSet), [dataSet]);

    const cumulativeColor = useMemo(() => {
        const last = cumulative.filter((v) => v != null).at(-1) ?? 0;
        return last >= 0
            ? isDark ? '#7ee787' : '#22c55e'
            : isDark ? '#ff6b81' : '#dc2626';
    }, [cumulative, isDark]);

    const positive = useMemo(() => dataSet.map(v => (v != null && v > 0 ? v : 0)), [dataSet]);
    const negative = useMemo(() => dataSet.map(v => (v != null && v < 0 ? v : 0)), [dataSet]);

    const chartData = {
        labels,
        datasets: [
            {
                type: 'line',
                label: String(t('performance_cumulative')),
                data: cumulative,
                borderColor: cumulativeColor,
                backgroundColor: 'transparent',
                borderWidth: 3,
                pointRadius: windowWidth < 640 ? 1 : 4,
                pointHoverRadius: windowWidth < 640 ? 3 : 6,
                spanGaps: true,
                tension: isMonthly ? 0.3 : 0,
            },
            {
                type: 'bar',
                label: String(t('performance_positive')),
                data: positive,
                backgroundColor: isDark ? 'rgba(126, 231, 135, 0.8)' : 'rgba(74, 222, 128, 0.8)',
                stack: 'stack1',
            },
            {
                type: 'bar',
                label: String(t('performance_negative')),
                data: negative,
                backgroundColor: isDark ? 'rgba(255, 99, 132, 0.8)' : 'rgba(239, 68, 68, 0.8)',
                stack: 'stack1',
            },
        ],
    };

    const options = {
        responsive: true,
        maintainAspectRatio: false,
        scales: {
            y: {
                stacked: true,
                beginAtZero: true,
                ticks: {
                    color: isDark ? '#ddd' : '#333',
                    callback: (val) => `${val}%`,
                },
                grid: {
                    color: isDark ? '#444' : '#ddd',
                },
            },
            x: {
                stacked: true,
                ticks: {
                    color: isDark ? '#ddd' : '#333',
                    autoSkip: true,
                    maxTicksLimit: windowWidth < 640 ? 6 : 20 // mobile: 6 tick max
                },
                grid: {
                    color: isDark ? '#444' : '#ddd',
                },
            },
        },
        plugins: {
            legend: {
                labels: {
                    color: isDark ? '#eee' : '#333',
                    font: {size: 14, weight: 'bold'},
                },
            },
            tooltip: {
                mode: 'index',
                intersect: false,
                callbacks: {
                    label: (ctx) => {
                        const val = ctx.parsed.y;
                        return `${ctx.dataset.label}: ${val >= 0 ? '+' : ''}${val}%`;
                    },
                },
            },
        },
    };

    function renderSummary() {
        const years = Object.fromEntries(
            allYears.map((y, i) => [y, i * 12])
        );

        if (isMonthly) {
            return (
                <div className="space-y-4">
                    {/* Tabs by year */}
                    <div className="mb-4">
                        <div
                            className="relative flex flex-row sm:flex-wrap sm:justify-center gap-2 sm:gap-3 overflow-x-auto sm:overflow-visible no-scrollbar snap-x snap-mandatory sm:snap-none px-2 sm:px-0 pb-3 sm:pb-0"
                        >
                            {[...allYears].reverse().map((year) => (
                                <div key={year} className="snap-start shrink-0 sm:shrink">
                                    <SelectableButton
                                        key={year}
                                        label={year}
                                        isSelected={selectedYear === String(year)}
                                        onClick={() => setSelectedYear(String(year))}
                                    />
                                </div>
                            ))}
                        </div>
                    </div>

                    {/* Cards for the selected year */}
                    <div className="p-4">
                        {/* Desktop: 12-card grid on one line */}
                        <div className="hidden sm:grid grid-cols-12 gap-3">
                            {monthlyReturns
                                .slice(years[selectedYear], years[selectedYear] + 12)
                                .map((val, i) => {
                                    const isNeutral = val == null || val === "-";
                                    const isPositive = !isNeutral && val >= 0;
                                    const monthIndex = i;
                                    const monthLabel = months[monthIndex] || `M${monthIndex + 1}`;

                                    return (
                                        <div
                                            key={i}
                                            className={`rounded-xl shadow-md p-2 transition transform hover:scale-105 hover:shadow-lg
                                        ${
                                                isNeutral
                                                    ? "bg-gray-100 dark:bg-gray-800"
                                                    : isPositive
                                                        ? "bg-green-50 dark:bg-green-900/20"
                                                        : "bg-red-50 dark:bg-red-900/20"
                                            }`}
                                        >
                                            <h4 className="mb-1 text-sm font-bold text-gray-900 dark:text-gray-100 text-center">
                                                {monthLabel}
                                            </h4>
                                            <p
                                                className={`text-xs font-semibold text-center ${
                                                    isNeutral
                                                        ? "text-gray-500 dark:text-gray-400"
                                                        : isPositive
                                                            ? "text-green-700 dark:text-green-400"
                                                            : "text-red-600 dark:text-red-400"
                                                }`}
                                            >
                                                {t("performance_return_label")}
                                            </p>
                                            <p
                                                className={`mt-1 text-sm font-bold text-center break-words ${
                                                    isNeutral
                                                        ? "text-gray-500 dark:text-gray-400"
                                                        : isPositive
                                                            ? "text-green-700 dark:text-green-400"
                                                            : "text-red-600 dark:text-red-400"
                                                }`}
                                            >
                                                {isNeutral
                                                    ? "—"
                                                    : (val > 0 ? "+" : "") +
                                                    val.toFixed(2).replace(".", ",") +
                                                    "%"}
                                            </p>
                                        </div>
                                    );
                                })}
                        </div>

                        {/* Mobile: horizontal scroll */}
                        <div
                            className="sm:hidden overflow-x-auto overflow-y-hidden scrollbar-thin scrollbar-thumb-gray-400 dark:scrollbar-thumb-gray-600 scrollbar-track-gray-200 dark:scrollbar-track-gray-800">
                            <div className="flex flex-nowrap gap-4 p-2">
                                {monthlyReturns
                                    .slice(years[selectedYear], years[selectedYear] + 12)
                                    .map((val, i) => {
                                        const isNeutral = val == null || val === "-";
                                        const isPositive = !isNeutral && val >= 0;
                                        const monthIndex = i;
                                        const monthLabel = months[monthIndex] || `M${monthIndex + 1}`;

                                        return (
                                            <div
                                                key={i}
                                                className={`flex-shrink-0 w-36 rounded-xl shadow-md p-3 transition transform hover:scale-105 hover:shadow-lg
                                            ${
                                                    isNeutral
                                                        ? "bg-gray-100 dark:bg-gray-800"
                                                        : isPositive
                                                            ? "bg-green-50 dark:bg-green-900/20"
                                                            : "bg-red-50 dark:bg-red-900/20"
                                                }`}
                                            >
                                                <h4 className="mb-1 text-sm font-bold text-gray-900 dark:text-gray-100 text-center">
                                                    {monthLabel}
                                                </h4>
                                                <p
                                                    className={`text-xs font-semibold text-center ${
                                                        isNeutral
                                                            ? "text-gray-500 dark:text-gray-400"
                                                            : isPositive
                                                                ? "text-green-700 dark:text-green-400"
                                                                : "text-red-600 dark:text-red-400"
                                                    }`}
                                                >
                                                    {t("performance_return_label")}
                                                </p>
                                                <p
                                                    className={`mt-1 text-sm font-bold text-center break-words ${
                                                        isNeutral
                                                            ? "text-gray-500 dark:text-gray-400"
                                                            : isPositive
                                                                ? "text-green-700 dark:text-green-400"
                                                                : "text-red-600 dark:text-red-400"
                                                    }`}
                                                >
                                                    {isNeutral
                                                        ? "—"
                                                        : (val > 0 ? "+" : "") +
                                                        val.toFixed(2).replace(".", ",") +
                                                        "%"}
                                                </p>
                                            </div>
                                        );
                                    })}
                            </div>
                        </div>
                    </div>
                </div>
            );
        }

        // --- ANNUAL VIEW ---
        return (
            <div className="overflow-x-auto sm:overflow-x-visible">
                <div className="flex sm:grid sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4 p-2">
                    {annualLabels.map((year, i) => {
                        const isPositive = annualReturns[i] >= 0;

                        return (
                            <div
                                key={year}
                                className={`flex-shrink-0 w-36 sm:w-auto rounded-xl shadow-md p-4 transition transform hover:scale-105 hover:shadow-lg
                            ${
                                    isPositive
                                        ? "bg-green-50 dark:bg-green-900/20"
                                        : "bg-red-50 dark:bg-red-900/20"
                                }`}
                            >
                                <h4 className="mb-2 text-lg font-bold text-gray-900 dark:text-gray-100 text-center">
                                    {year}
                                </h4>
                                <p
                                    className={`text-sm font-semibold text-center ${
                                        isPositive
                                            ? "text-green-700 dark:text-green-400"
                                            : "text-red-600 dark:text-red-400"
                                    }`}
                                >
                                    {t("performance_return_label")}
                                </p>
                                <p
                                    className={`mt-1 text-xl font-bold text-center ${
                                        isPositive
                                            ? "text-green-700 dark:text-green-400"
                                            : "text-red-600 dark:text-red-400"
                                    }`}
                                >
                                    {annualReturns[i] != null
                                        ? (annualReturns[i] > 0 ? "+" : "") +
                                        annualReturns[i].toFixed(2).replace(".", ",") +
                                        "%"
                                        : "—"}
                                </p>
                            </div>
                        );
                    })}
                </div>
            </div>
        );
    }

    return (
        <section
            className="max-w-6xl mx-auto px-4 sm:px-6 py-6 bg-white dark:bg-gray-900 rounded-xl shadow-lg flex flex-col gap-6">
            <header className="text-center flex flex-col items-center gap-4">
                <h3 className="text-3xl font-bold text-gray-900 dark:text-gray-100">
                    {t('performance_title')}
                </h3>
                <select
                    className="rounded border border-gray-300 dark:border-gray-700 px-3 py-1 text-gray-900 dark:text-gray-100 bg-white dark:bg-gray-800 cursor-pointer"
                    value={view}
                    onChange={(e) => setView(e.target.value === 'annual' ? 'annual' : 'monthly')}
                    aria-label={t('performance_view_selector_aria')}
                >
                    <option value="monthly">{t('performance_view_monthly')}</option>
                    <option value="annual">{t('performance_view_annual')}</option>
                </select>
            </header>

            <div className="w-full h-[300px] sm:h-[500px] md:h-[700px]">
                <Line data={chartData} options={options}/>
            </div>

            <div className="text-gray-800 dark:text-gray-300 text-sm space-y-6 text-center">
                {renderSummary()}
            </div>
        </section>
    );
}