import React, { useState, useEffect } from 'react';
import LineChartComponent from './Components/LineChartComponent';
import DateRangeSelector from './Components/DateRangeSelector';
import metricsService from './Components/metricsService';
import { Button, Radio, message, Tag } from 'antd';
import moment from 'moment';
import StatusLogTable from './Components/StatusLogTable';
import { Box, IconButton, Tooltip as MuiTooltip } from '@mui/material';
import { ListAlt } from '@mui/icons-material';

const PrometheusChart = ({ metricInfo, chartHeight = 580 }) => {
    const {
        name: metricName,
        filters = {},
        title = metricName,
        description,
        context = {},
        ranges = []
    } = metricInfo || {};

    const { device, source_id } = context;

    const [chartData, setChartData] = useState([]);
    const [isLoading, setIsLoading] = useState(true);
    const [error, setError] = useState(null);
    const [metricMeta, setMetricMeta] = useState({});
    const [mode, setMode] = useState('realtime');
    const [startDate, setStartDate] = useState(moment().subtract(1, 'hour').toDate());
    const [endDate, setEndDate] = useState(moment().toDate());
    const [isLiveUpdating, setIsLiveUpdating] = useState(false);
    const [showLogs, setShowLogs] = useState(false);
    const [statusLogs, setStatusLogs] = useState([]);
    const MAX_POINTS = 50;
    const TIME_WINDOW_MS = 3600 * 1000; // 1 час в миллисекундах


    const getSubscriptionKey = () => {
        const filterParts = [];
        if (device) filterParts.push(`device=${encodeURIComponent(device)}`);
        if (source_id) filterParts.push(`source_id=${encodeURIComponent(source_id)}`);
        return `${metricName}${filterParts.length ? `?${filterParts.join('&')}` : ''}`;
    };

    const formatMetricData = (dataArray) => {
        return dataArray
            .map(item => ({
                ...item,
                timestamp: item.timestamp,
                value: parseFloat(item.value),
                name: item.__name__ || metricName,
                status: parseInt(item.status) || 0,
                device: item.device?.trim() || null,
                source_id: item.source_id || null,
                description: item.description || description
            }))
            .sort((a, b) => a.timestamp - b.timestamp);
    };

    const calculateStep = (startTime, endTime, maxPoints = 10000) => {
        const durationSeconds = (endTime.getTime() - startTime.getTime()) / 1000;
        return Math.max(Math.ceil(durationSeconds / maxPoints), 1);
    };

    const downsampleData = (data, maxPoints = MAX_POINTS) => {
        if (data.length <= maxPoints) return [...data];

        const sortedData = [...data].sort((a, b) => a.timestamp - b.timestamp);
        const step = Math.max(1, Math.floor(sortedData.length / maxPoints));

        const result = [];
        for (let i = 0; i < sortedData.length; i += step) {
            if (result.length >= maxPoints) break;
            result.push(sortedData[i]);
        }

        // Всегда включаем последнюю точку
        if (result.length > 0) {
            const lastOriginalPoint = sortedData[sortedData.length - 1];
            if (result[result.length - 1].timestamp !== lastOriginalPoint.timestamp) {
                result[result.length - 1] = lastOriginalPoint;
            }
        }

        return result;
    };


    // Обновляем логи при изменении данных
    useEffect(() => {
        if (chartData.length > 0) {
            const newLogs = chartData.reduce((acc, point, index) => {
                if (index === 0 || point.status !== chartData[index - 1].status) {
                    return [...acc, point];
                }
                return acc;
            }, []);
            setStatusLogs(newLogs);
        }
    }, [chartData]);


    const fetchHistoricalData = async (start, end) => {
        setIsLoading(true);
        setError(null);

        try {
            const extendedFilters = {
                ...filters,
                ...(device && { device: device.toString() }),
                ...(source_id && { source_id: source_id.toString() })
            };

            const step = calculateStep(start, end);
            const data = await metricsService.fetchMetricsRange(
                metricName,
                Math.floor(start.getTime() / 1000),
                Math.floor(end.getTime() / 1000),
                step,
                extendedFilters
            );

            const formattedData = formatMetricData(data)
                .sort((a, b) => a.timestamp - b.timestamp);

            // Применяем ограничение по количеству точек только для исторических данных
            const limitedData = formattedData.length > MAX_POINTS
                ? formattedData.slice(-MAX_POINTS)
                : formattedData;

            if (limitedData.length > 0) {
                setMetricMeta({
                    type: data[0]?.type,
                    description: data[0]?.description || description,
                    instance: data[0]?.instance,
                    job: data[0]?.job
                });
            }

            setChartData(limitedData);
        } catch (err) {
            console.error(`Error loading historical data for ${metricName}:`, err);
            setError(err.message);
            message.error(`Failed to load historical data: ${err.message}`);
        } finally {
            setIsLoading(false);
        }
    };

    const startRealtimeUpdates = () => {
        setIsLiveUpdating(true);
        setIsLoading(true);

        const end = new Date();
        const start = new Date(end.getTime() - TIME_WINDOW_MS);
        fetchHistoricalData(start, end).finally(() => setIsLoading(false));

        return metricsService.subscribeToMetric(
            getSubscriptionKey(),
            (newData) => {
                setChartData(prev => {
                    const now = Date.now();
                    const cutoffTime = now - TIME_WINDOW_MS;

                    // Фильтруем старые точки (старше TIME_WINDOW_MS)
                    const filteredPrev = prev.filter(point => point.timestamp >= cutoffTime);

                    // Добавляем новые точки
                    const newPoints = formatMetricData(newData)
                        .filter(point => point.timestamp >= cutoffTime);

                    // Объединяем и удаляем дубликаты
                    const mergedData = [...filteredPrev, ...newPoints]
                        .filter((v, i, a) => a.findIndex(t => t.timestamp === v.timestamp) === i)
                        .sort((a, b) => a.timestamp - b.timestamp);

                    // Если точек слишком много, равномерно прореживаем
                    if (mergedData.length > MAX_POINTS) {
                        const step = Math.ceil(mergedData.length / MAX_POINTS);
                        return mergedData.filter((_, index) => index % step === 0);
                    }

                    return mergedData;
                });
            },
            1000, // Уменьшаем интервал обновления до 1 секунды
            {
                ...filters,
                ...(device && { device }),
                ...(source_id && { source_id })
            }
        );
    };


    const stopRealtimeUpdates = () => {
        setIsLiveUpdating(false);
        metricsService.unsubscribeFromMetric(getSubscriptionKey());
    };

    const handleCustomRangeApply = () => {
        if (startDate && endDate) {
            fetchHistoricalData(startDate, endDate);
        }
    };

    useEffect(() => {
        console.log('Current metric context:', { device, source_id, metricName });
        let unsubscribe;
        if (mode === 'realtime') {
            unsubscribe = startRealtimeUpdates();
        } else {
            stopRealtimeUpdates();
            fetchHistoricalData(startDate, endDate);
        }

        return () => {
            if (unsubscribe) unsubscribe();
            stopRealtimeUpdates();
        };
    }, [mode, metricName, device, source_id]);

    const metaInfo = [
        metricMeta.instance && `Instance: ${metricMeta.instance}`,
        metricMeta.job && `Job: ${metricMeta.job}`,
        metricMeta.type && `Type: ${metricMeta.type}`
    ].filter(Boolean).join(' | ');

    return (
        <div>
            <div style={{ marginBottom: 16 }}>
                <Radio.Group
                    value={mode}
                    onChange={(e) => setMode(e.target.value)}
                    buttonStyle="solid"
                    style={{ marginBottom: 10 }}
                >
                    <Radio.Button value="realtime">Режим реального времени</Radio.Button>
                    <Radio.Button value="historical">Исторические данные</Radio.Button>
                </Radio.Group>

                {mode === 'historical' && (
                    <DateRangeSelector
                        startDate={startDate}
                        endDate={endDate}
                        onStartDateChange={setStartDate}
                        onEndDateChange={setEndDate}
                        onApply={handleCustomRangeApply}
                    />
                )}

                {mode === 'realtime' && isLiveUpdating && (
                    <Button
                        type="primary"
                        danger
                        onClick={() => setMode('historical')}
                        style={{ marginTop: 10 }}
                    >
                        Остановить обновление
                    </Button>
                )}
            </div>

            {device && <Tag color="geekblue">Устройство: {device}</Tag>}
            {source_id && <Tag color="purple">Модуль: {source_id.split('$')[1]}</Tag>}

            <Box position="relative">
                <MuiTooltip title={showLogs ? "Скрыть логи" : "Показать логи"}>
                    <IconButton
                        onClick={() => setShowLogs(!showLogs)}
                        sx={{
                            position: 'absolute',
                            right: 16,
                            top: 16,
                            zIndex: 1000,
                            bgcolor: 'background.paper',
                            boxShadow: 1
                        }}
                    >
                        <ListAlt />
                    </IconButton>
                </MuiTooltip>

                {isLoading ? (
                    <div>Загрузка графика...</div>
                ) : error ? (
                    <div>Ошибка: {error}</div>
                ) : chartData.length === 0 ? (
                    <div>Нет данных для метрики: {metricName}</div>
                ) : (
                    <>
                        <LineChartComponent
                            data={chartData}
                            title={title}
                            description={description}
                            metaInfo={metaInfo}
                            height={chartHeight}
                            additionalFilters={{
                                device,
                                source_id
                            }}
                            ranges={ranges}
                        />
                        {showLogs && (
                            <StatusLogTable logs={statusLogs} />
                        )}
                    </>
                )}
            </Box>
        </div>
    );
};

export default PrometheusChart;