const { BrowserRouter, Switch, Route, Link } = ReactRouterDOM;

function App() {
    async function get(url) {
        return (await axios
            .get(url, { timeout: 60000 })).data
    }

    const [status, setStatus] = React.useState('');
    const [accData, setAccData] = React.useState([]);
    const [valAccData, setValAccData] = React.useState([]);
    const [lossData, setLossData] = React.useState([]);
    const [valLossData, setValLossData] = React.useState([]);
    const [logs, setLogs] = React.useState([]);
    const colorAcc = '#13a530ff'
    const colorValAcc = 'rgb(19, 165, 158)'
    const colorLoss = '#dc3545'
    const colorValLoss = 'rgb(228, 79, 154)'
    const chartRef = React.useRef(null);
    const chartInstanceRef = React.useRef(null);

    let url

    async function fetchRealtimeData() {
        setStatus('Getting pod url...');
        const startTime = new Date().getTime()
        do {
            url = (await get("http://localhost:5000/api/training_url")).url
        } while (!url)
        const socket = io(url);
        const startSeconds = (new Date().getTime() - startTime) / 1000
        setLogs([...logs, `Started pod in (${startSeconds}s)`])

        socket.on('connect', () => {
            console.log('Connected to server');
            setStatus('Connected');
        });

        socket.on('train_status', (data) => {
            console.log('Received train_status:', data);
            setStatus(JSON.stringify(data, null, 2));

            if (data.acc !== undefined) {
                setAccData(prev => [...prev, data.acc]);
            }
            if (data.val_acc !== undefined) {
                setValAccData(prev => [...prev, data.val_acc]);
            }
            if (data.loss !== undefined && data.loss !== null) {
                setLossData(prev => [...prev, Number(data.loss)]);
            }
            if (data.val_loss !== undefined && data.val_loss !== null) {
                setValLossData(prev => [...prev, Number(data.val_loss)]);
            }
            if (data.status === "stopped") {
                socket.disconnect()
            }
        });

        socket.on('disconnect', () => {
            console.log('Disconnected from server');
            setStatus('Disconnected');
        });

        return () => socket.disconnect();
    }

    React.useEffect(() => {
        fetchRealtimeData()
    }, []);

    function padSeries(arr, n) {
        if (arr.length >= n) return arr.slice(0, n);
        return arr.concat(Array(n - arr.length).fill(null));
    }

    React.useEffect(() => {
        const canvas = chartRef.current;
        const Chart = window.Chart;
        if (!canvas || !Chart) return;

        const n = Math.max(accData.length, valAccData.length, lossData.length, valLossData.length);
        if (n === 0) return;

        const labels = Array.from({ length: n }, (_, i) => String(i + 1));

        const datasets = [
            { label: 'Acc', data: padSeries(accData, n), borderColor: colorAcc, backgroundColor: colorAcc, tension: 0.1, pointRadius: 0 },
            { label: 'Val Acc', data: padSeries(valAccData, n), borderColor: colorValAcc, backgroundColor: colorValAcc, tension: 0.1, pointRadius: 0 },
            { label: 'Loss', data: padSeries(lossData, n), borderColor: colorLoss, backgroundColor: colorLoss, tension: 0.1, pointRadius: 0 },
            { label: 'Val Loss', data: padSeries(valLossData, n), borderColor: colorValLoss, backgroundColor: colorValLoss, tension: 0.1, pointRadius: 0 },
        ];

        if (!chartInstanceRef.current) {
            chartInstanceRef.current = new Chart(canvas, {
                type: 'line',
                data: { labels, datasets },
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    interaction: { mode: 'index', intersect: false },
                    plugins: {
                        legend: { display: true, position: 'top' },
                        title: { display: true, text: 'Training metrics (Y-axis auto-scales to data)' },
                    },
                    scales: {
                        x: { title: { display: true, text: 'Update #' } },
                        y: {
                            beginAtZero: true,
                            grace: '5%',
                        },
                    },
                    animation: { duration: 0 },
                },
            });
        } else {
            chartInstanceRef.current.data.labels = labels;
            datasets.forEach((ds, i) => {
                chartInstanceRef.current.data.datasets[i].data = ds.data;
            });
            chartInstanceRef.current.update();
        }
    }, [accData, valAccData, lossData, valLossData]);

    React.useEffect(() => {
        return () => {
            if (chartInstanceRef.current) {
                chartInstanceRef.current.destroy();
                chartInstanceRef.current = null;
            }
        };
    }, []);

    return (
        <BrowserRouter>
            <div className="box">
                <nav style={{ marginBottom: 16 }}>
                    <Link to="/" style={{ marginRight: 12 }}>Monitor</Link>
                    <Link to="/logs">Logs</Link>
                </nav>
                <Switch>
                    <Route path="/logs">
                        <h1>Logs</h1>
                        <pre style={{ fontSize: '12px' }}>{JSON.stringify(logs)}</pre>
                    </Route>
                    <Route path="/" exact>
                        <h1>Training Monitor 📊</h1>
                        <p>Real-time accuracy visualization (Chart.js, auto Y-scale)</p>
                        <h3>Chart:</h3>
                        <div style={{
                            height: 320,
                            maxWidth: 720,
                            border: '1px solid #ddd',
                            borderRadius: '4px',
                            padding: '8px',
                            background: '#fafafa',
                        }}>
                            <canvas ref={chartRef} />
                        </div>
                        <p style={{ fontSize: '12px', color: '#666' }}>
                            Points: {Math.max(accData.length, valAccData.length, lossData.length, valLossData.length)}
                        </p>
                        <h3>Socket.IO Status:</h3>
                        <pre style={{ fontSize: '12px', maxHeight: '200px', overflow: 'auto' }}>{status}</pre>
                    </Route>
                </Switch>
            </div>
        </BrowserRouter>
    );
}

console.log('App.jsx loaded and executed!');
