import React, { useEffect, useState, useRef } from 'react';
import axios from 'axios';
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';
import LineChartComponent from './Components/LineChartComponent';

const MAX_POINTS = 20;
const COLORS = ['#3e95cd', '#8e5ea2', '#3cba9f', '#e8c3b9', '#c45850'];
const TIME_RANGES = [
    { label: '1 минута', value: 60, interval: 3000 },
    { label: '5 минут', value: 300, interval: 15000 },
    { label: '30 минут', value: 1800, interval: 90000 },
    { label: '1 час', value: 3600, interval: 180000 },
    { label: '3 часа', value: 10800, interval: 540000 },
    { label: '6 часов', value: 21600, interval: 1080000 },
    { label: '12 часов', value: 43200, interval: 2160000 },
    { label: '24 часа', value: 86400, interval: 4320000 },
    { label: '2 дня', value: 172800, interval: 8640000 },
    { label: '7 дней', value: 604800, interval: 30240000 },
    { label: '30 дней', value: 2592000, interval: 129600000 },
    { label: '90 дней', value: 7776000, interval: 388800000 },
    { label: '6 месяцев', value: 15552000, interval: 777600000 },
    { label: '9 месяцев', value: 23328000, interval: 1166400000 },
    { label: '1 год', value: 31536000, interval: 1576800000 },
];

const PrometheusChart = ({ metricName }) => {
    const [chartData, setChartData] = useState({});
    const [selectedRange, setSelectedRange] = useState(TIME_RANGES[0]);
    const [startDate, setStartDate] = useState(new Date());
    const [endDate, setEndDate] = useState(new Date());
    const [useCustomRange, setUseCustomRange] = useState(false);
    const [selectedGraphRange, setSelectedGraphRange] = useState(null); // Выбранный диапазон
    const [filteredData, setFilteredData] = useState(null); // Отфильтрованные данные
    const intervalRef = useRef(null);

    // Функция для интерполяции данных
    const interpolateData = (data, minPoints = 15) => {
        if (data.length >= minPoints) return data;

        const interpolatedData = [];
        for (let i = 0; i < data.length - 1; i++) {
            interpolatedData.push(data[i]);

            const currentPoint = data[i];
            const nextPoint = data[i + 1];

            // Вычисляем разницу во времени между точками
            const currentTime = new Date(currentPoint.time).getTime();
            const nextTime = new Date(nextPoint.time).getTime();
            const timeDiff = nextTime - currentTime;

            // Добавляем промежуточные точки
            const steps = Math.ceil((minPoints - data.length) / (data.length - 1));
            for (let j = 1; j <= steps; j++) {
                const interpolatedTime = new Date(currentTime + (timeDiff * j) / (steps + 1)).toLocaleString();
                const interpolatedPoint = { time: interpolatedTime };

                // Интерполируем значения для каждой метрики
                Object.keys(currentPoint).forEach(key => {
                    if (key !== 'time') {
                        const currentValue = currentPoint[key];
                        const nextValue = nextPoint[key];
                        interpolatedPoint[key] = currentValue + ((nextValue - currentValue) * j) / (steps + 1);
                    }
                });

                interpolatedData.push(interpolatedPoint);
            }
        }

        interpolatedData.push(data[data.length - 1]); // Добавляем последнюю точку
        return interpolatedData.slice(0, minPoints); // Обрезаем до minPoints
    };

    const fetchData = async () => {
        try {
            let start, end;

            if (useCustomRange) {
                start = Math.floor(startDate.getTime() / 1000);
                end = Math.floor(endDate.getTime() / 1000);
            } else {
                end = Math.floor(Date.now() / 1000);
                start = end - selectedRange.value;
            }

            let step;
            const range = end - start;
            if (range <= 3600) step = 5;
            else if (range <= 21600) step = 30;
            else if (range <= 86400) step = 120;
            else step = 300;

            const response = await axios.get('https://192.168.2.43:3000/metrics', {
                params: { metric: metricName, start, end, step },
            });

            /*
                        const response = await axios.get(`${process.env.REACT_APP_BACK_URL}/metrics`, {
                            params: { metric: metricName, start, end, step },
                        }); */

            const result = response.data;
            let metrics = Array.isArray(result) ? result : result.data || [];

            if (!Array.isArray(metrics)) {
                metrics = [];
            }

            const timePoints = [];
            for (let t = start; t <= end; t += step) {
                const date = new Date(t * 1000);
                const formattedTime = range > 86400
                    ? date.toLocaleString([], { day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit' })
                    : date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' });

                timePoints.push(formattedTime);
            }

            const updatedData = {};
            metrics.forEach(m => {
                const date = new Date(m.timestamp);
                const formattedTime = range > 86400
                    ? date.toLocaleString([], { day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit' })
                    : date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' });

                const key = `${m.instance}-${m.device || m.scrape_job}`;
                if (!updatedData[key]) updatedData[key] = {};
                updatedData[key][formattedTime] = m.value;
            });

            const chartData = {};
            Object.keys(updatedData).forEach(key => {
                chartData[key] = timePoints.map(time => ({
                    time,
                    value: updatedData[key][time] ?? null,
                }));
            });

            setChartData(chartData);
        } catch (error) {
            console.error('Ошибка при загрузке метрик:', error);
        }
    };

    useEffect(() => {
        fetchData();

        intervalRef.current = setInterval(() => {
            fetchData();
        }, selectedRange.interval);

        return () => {
            if (intervalRef.current) {
                clearInterval(intervalRef.current);
            }
        };
    }, [metricName, selectedRange, useCustomRange, startDate, endDate]);

    const handleRangeChange = (event) => {
        const selectedValue = event.target.value;
        const range = TIME_RANGES.find(range => range.value === parseInt(selectedValue, 10));
        setSelectedRange(range);
        setUseCustomRange(false);
        setSelectedGraphRange(null); // Сбрасываем выбранный диапазон
        setFilteredData(null); // Сбрасываем отфильтрованные данные
    };

    const handleCustomRangeChange = () => {
        setUseCustomRange(true);
        setSelectedGraphRange(null); // Сбрасываем выбранный диапазон
        setFilteredData(null); // Сбрасываем отфильтрованные данные
    };

    useEffect(() => {
        if (selectedGraphRange) {
            const { startIndex, endIndex } = selectedGraphRange;
            const allTimes = Object.values(chartData)
                .flat()
                .map(point => point.time)
                .filter((time, index, self) => self.indexOf(time) === index);

            const data = allTimes.map(time => {
                const point = { time };
                Object.keys(chartData).forEach(key => {
                    const instanceData = chartData[key].find(p => p.time === time);
                    point[key] = instanceData ? instanceData.value : null;
                });
                return point;
            });

            const filtered = data.slice(startIndex, endIndex + 1);

            // Интерполируем данные, если точек меньше 15
            const interpolated = interpolateData(filtered, 15);
            setFilteredData(interpolated); // Сохраняем интерполированные данные
        } else {
            setFilteredData(null); // Сбрасываем фильтрацию, если диапазон не выбран
        }
    }, [selectedGraphRange, chartData]);

    if (!Object.keys(chartData).length) return <p>Loading...</p>;

    const allTimes = Object.values(chartData)
        .flat()
        .map(point => point.time)
        .filter((time, index, self) => self.indexOf(time) === index);

    const data = allTimes.map(time => {
        const point = { time };
        Object.keys(chartData).forEach(key => {
            const instanceData = chartData[key].find(p => p.time === time);
            point[key] = instanceData ? instanceData.value : null;
        });
        return point;
    });

    return (
        <div>
            <div>
                <label htmlFor="time-range">Выберите временной диапазон: </label>
                <select id="time-range" value={selectedRange.value} onChange={handleRangeChange}>
                    {TIME_RANGES.map(range => (
                        <option key={range.value} value={range.value}>{range.label}</option>
                    ))}
                </select>
            </div>
            <div>
                <label>Или выберите другой диапазон: </label>
                <div>
                    <label>Начальная дата: </label>
                    <DatePicker
                        selected={startDate}
                        onChange={(date) => setStartDate(date)}
                        showTimeSelect
                        timeFormat="HH:mm"
                        timeIntervals={15}
                        dateFormat="yyyy-MM-dd HH:mm"
                    />
                </div>
                <div>
                    <label>Конечная дата: </label>
                    <DatePicker
                        selected={endDate}
                        onChange={(date) => setEndDate(date)}
                        showTimeSelect
                        timeFormat="HH:mm"
                        timeIntervals={15}
                        dateFormat="yyyy-MM-dd HH:mm"
                    />
                </div>
                <button onClick={handleCustomRangeChange}>Использовать кастомный диапазон</button>
            </div>
            <LineChartComponent
                chartData={chartData}
                metricName={metricName}
                colors={COLORS}
                description={metricName}
                onRangeSelect={setSelectedGraphRange}
                filteredData={filteredData}
            />
        </div>
    );
};

export default PrometheusChart;