﻿using LiveChartsCore;
using LiveChartsCore.Defaults;
using LiveChartsCore.SkiaSharpView;
using LiveChartsCore.SkiaSharpView.Extensions;
using LiveChartsCore.SkiaSharpView.Painting;
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WinFormsApp2
{
    public partial class UserControl1 : UserControl
    {
        private ObservableValue gaugeValue;
        private System.Windows.Forms.Timer timer;
        private static readonly HttpClient client;

        // Для PieChart состояния сети
        private ObservableValue workingCount;
        private ObservableValue brokenCount;
        private ObservableValue maintenanceCount;

        private List<DateTimePoint> salesData;
        private bool showByAmount = true;

        // Храним серии для графика продаж
        private ColumnSeries<DateTimePoint> salesSeries;

        static UserControl1()
        {
            var handler = new HttpClientHandler
            {
                UseProxy = false
            };
            client = new HttpClient(handler);
        }

        public UserControl1()
        {
            InitializeComponent();

            // Включаем DoubleBuffering для уменьшения мигания
            this.DoubleBuffered = true;

            InitializeGauge();
            InitializeNetworkStatusPie();
            InitializeSalesChart();
            InitializeSummary();
            StartNotificationPolling();
            // Инициализируем таймер
            timer = new System.Windows.Forms.Timer { Interval = 3000 };
            timer.Tick += async (_, __) => await UpdateChartsFromApi();
            timer.Start();

            // Сразу загружаем данные при запуске
            UpdateChartsFromApi();
        }

        private void InitializeGauge()
        {
            gaugeValue = new ObservableValue(0);

            var gaugeSeries = GaugeGenerator.BuildSolidGauge(
                new GaugeItem(gaugeValue, s =>
                {
                    s.Fill = new SolidColorPaint(SKColors.Green);
                    s.MaxRadialColumnWidth = 40;
                    s.DataLabelsSize = 0; // Убираем лейблы если не нужны
                }),
                new GaugeItem(GaugeItem.Background, s =>
                {
                    s.Fill = new SolidColorPaint(new SKColor(200, 200, 200));
                })
            );

            pieChart1.Series = gaugeSeries;
            pieChart1.InitialRotation = -225;
            pieChart1.MaxAngle = 270;
            pieChart1.MinValue = 0;
            pieChart1.MaxValue = 100;

            // ОТКЛЮЧАЕМ АНИМАЦИИ
            pieChart1.AnimationsSpeed = TimeSpan.FromMilliseconds(0);
            pieChart1.EasingFunction = null;
        }

        private void InitializeNetworkStatusPie()
        {
            workingCount = new ObservableValue(1);
            brokenCount = new ObservableValue(1);
            maintenanceCount = new ObservableValue(1);

            pieChart2.Series = new ISeries[]
            {
                new PieSeries<ObservableValue>
                {
                    Values = new[] { workingCount },
                    Name = "Работает",
                    Fill = new SolidColorPaint(SKColor.Parse("#4CAF50")),
                    DataLabelsPaint = new SolidColorPaint(SKColors.White),
                    DataLabelsSize = 16,
                    DataLabelsPosition = LiveChartsCore.Measure.PolarLabelsPosition.Middle,
                    DataLabelsFormatter = point => $"{point.PrimaryValue}",
                    InnerRadius = 60
                },
                new PieSeries<ObservableValue>
                {
                    Values = new[] { brokenCount },
                    Name = "Не работает",
                    Fill = new SolidColorPaint(SKColor.Parse("#F44336")),
                    DataLabelsPaint = new SolidColorPaint(SKColors.White),
                    DataLabelsSize = 16,
                    DataLabelsPosition = LiveChartsCore.Measure.PolarLabelsPosition.Middle,
                    DataLabelsFormatter = point => $"{point.PrimaryValue}",
                    InnerRadius = 60
                },
                new PieSeries<ObservableValue>
                {
                    Values = new[] { maintenanceCount },
                    Name = "На обслуживании",
                    Fill = new SolidColorPaint(SKColor.Parse("#2196F3")),
                    DataLabelsPaint = new SolidColorPaint(SKColors.White),
                    DataLabelsSize = 16,
                    DataLabelsPosition = LiveChartsCore.Measure.PolarLabelsPosition.Middle,
                    DataLabelsFormatter = point => $"{point.PrimaryValue}",
                    InnerRadius = 60
                }
            };

            pieChart2.LegendPosition = LiveChartsCore.Measure.LegendPosition.Bottom;
            pieChart2.LegendTextPaint = new SolidColorPaint(SKColors.Black);
            pieChart2.LegendTextSize = 14;

            // ОТКЛЮЧАЕМ АНИМАЦИИ
            pieChart2.AnimationsSpeed = TimeSpan.FromMilliseconds(0);
            pieChart2.EasingFunction = null;

            UpdateCenterText(0);
        }

        private void UpdateCenterText(int maintenanceValue)
        {
            if (labelCenterText != null)
            {
                labelCenterText.Text = $"Под вопросом:\n{maintenanceValue}";
            }
        }

        private void InitializeSalesChart()
        {
            salesData = new List<DateTimePoint>();

            // Создаем серию один раз
            salesSeries = new ColumnSeries<DateTimePoint>
            {
                Values = salesData,
                Fill = new SolidColorPaint(SKColor.Parse("#81D4FA")),
                Stroke = new SolidColorPaint(SKColor.Parse("#0288D1")) { StrokeThickness = 2 },
                Name = "Сумма продаж"
            };

            cartesianChart1.Series = new ISeries[] { salesSeries };

            // Настройка осей (делаем один раз)
            cartesianChart1.XAxes = new[]
            {
                new Axis
                {
                    Labeler = value =>
                    {
                        var date = new DateTime((long)value);
                        return date.ToString("dd.MM");
                    },
                    LabelsRotation = 0,
                    TextSize = 12,
                    LabelsPaint = new SolidColorPaint(SKColors.Black),
                    SeparatorsPaint = new SolidColorPaint(SKColor.Parse("#E0E0E0"))
                }
            };

            cartesianChart1.YAxes = new[]
            {
                new Axis
                {
                    TextSize = 12,
                    LabelsPaint = new SolidColorPaint(SKColors.Black),
                    SeparatorsPaint = new SolidColorPaint(SKColor.Parse("#E0E0E0")),
                    MinLimit = 0
                }
            };

            // ОТКЛЮЧАЕМ АНИМАЦИИ
            cartesianChart1.AnimationsSpeed = TimeSpan.FromMilliseconds(0);
            cartesianChart1.EasingFunction = null;

            // Настройка кнопок фильтрации
            buttonByAmount.BackColor = Color.FromArgb(33, 150, 243);
            buttonByAmount.ForeColor = Color.White;
            buttonByQuantity.BackColor = Color.LightGray;
            buttonByQuantity.ForeColor = Color.Black;

            buttonByAmount.Click += async (s, e) =>
            {
                showByAmount = true;
                buttonByAmount.BackColor = Color.FromArgb(33, 150, 243);
                buttonByAmount.ForeColor = Color.White;
                buttonByQuantity.BackColor = Color.LightGray;
                buttonByQuantity.ForeColor = Color.Black;

                // Обновляем название серии
                salesSeries.Name = "Сумма продаж";

                // Перезагружаем данные
                await UpdateSalesData();
            };

            buttonByQuantity.Click += async (s, e) =>
            {
                showByAmount = false;
                buttonByQuantity.BackColor = Color.FromArgb(33, 150, 243);
                buttonByQuantity.ForeColor = Color.White;
                buttonByAmount.BackColor = Color.LightGray;
                buttonByAmount.ForeColor = Color.Black;

                // Обновляем название серии
                salesSeries.Name = "Количество продаж";

                // Перезагружаем данные
                await UpdateSalesData();
            };
        }

        private void InitializeSummary()
        {
            if (dataGridViewSummary != null)
            {
                dataGridViewSummary.Columns.Clear();
                dataGridViewSummary.Columns.Add("Parameter", "");
                dataGridViewSummary.Columns.Add("Value", "");

                dataGridViewSummary.Columns[0].Width = 200;
                dataGridViewSummary.Columns[1].Width = 100;

                dataGridViewSummary.ColumnHeadersVisible = false;
                dataGridViewSummary.RowHeadersVisible = false;
                dataGridViewSummary.AllowUserToAddRows = false;
                dataGridViewSummary.ReadOnly = true;
                dataGridViewSummary.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
                dataGridViewSummary.BackgroundColor = Color.White;
                dataGridViewSummary.BorderStyle = BorderStyle.None;

                dataGridViewSummary.Rows.Add("Денег в ТА", "0 ₽");
                dataGridViewSummary.Rows.Add("Инкассаций, входящие", "0 ₽");
                dataGridViewSummary.Rows.Add("Выручка, сегодня", "0 ₽");
                dataGridViewSummary.Rows.Add("Выручка, вчера", "0 ₽");
                dataGridViewSummary.Rows.Add("Техобслуживание, плановое", "0 ч");
                dataGridViewSummary.Rows.Add("Техобслуживание, внеплановое", "0 ч");
                dataGridViewSummary.Rows.Add("Обращений ТП, сегодня", "0");
            }
        }

        private async Task UpdateChartsFromApi()
        {
            try
            {
                // Получаем данные о состоянии сети
                var statusResponse = await client.GetAsync("http://127.0.0.1:8000/network-status");
                var statusText = await statusResponse.Content.ReadAsStringAsync();

                if (statusResponse.IsSuccessStatusCode)
                {
                    var result = JsonSerializer.Deserialize<JsonElement>(statusText);

                    double efficiency = result.GetProperty("efficiency").GetDouble();
                    int working = result.GetProperty("working_machines").GetInt32();
                    int broken = result.GetProperty("broken_machines").GetInt32();
                    int maintenance = result.GetProperty("maintenance_machines").GetInt32();

                    if (InvokeRequired)
                    {
                        Invoke(new Action(() =>
                        {
                            // Просто обновляем значения, не пересоздаем серии
                            gaugeValue.Value = efficiency;
                            UpdateGaugeColor(efficiency);

                            workingCount.Value = working;
                            brokenCount.Value = broken;
                            maintenanceCount.Value = maintenance;

                            UpdateCenterText(maintenance);
                        }));
                    }
                    else
                    {
                        gaugeValue.Value = efficiency;
                        UpdateGaugeColor(efficiency);

                        workingCount.Value = working;
                        brokenCount.Value = broken;
                        maintenanceCount.Value = maintenance;

                        UpdateCenterText(maintenance);
                    }
                }

                // Получаем данные о продажах
                await UpdateSalesData();

                // Получаем сводку
                var summaryResponse = await client.GetAsync("http://127.0.0.1:8000/summary");
                var summaryText = await summaryResponse.Content.ReadAsStringAsync();

                if (summaryResponse.IsSuccessStatusCode)
                {
                    var summaryResult = JsonSerializer.Deserialize<JsonElement>(summaryText);

                    if (InvokeRequired)
                    {
                        Invoke(new Action(() => UpdateSummary(summaryResult)));
                    }
                    else
                    {
                        UpdateSummary(summaryResult);
                    }
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"Ошибка: {ex.Message}");
            }
        }

        private async Task UpdateSalesData()
        {
            try
            {
                var salesResponse = await client.GetAsync($"http://127.0.0.1:8000/sales-dynamics?by_amount={showByAmount}");
                var salesText = await salesResponse.Content.ReadAsStringAsync();

                if (salesResponse.IsSuccessStatusCode)
                {
                    var salesResult = JsonSerializer.Deserialize<JsonElement>(salesText);
                    var salesArray = salesResult.GetProperty("sales").EnumerateArray();

                    var newSalesData = new List<DateTimePoint>();

                    foreach (var sale in salesArray)
                    {
                        var dateStr = sale.GetProperty("date").GetString();
                        var value = sale.GetProperty("value").GetDouble();
                        var date = DateTime.Parse(dateStr);

                        newSalesData.Add(new DateTimePoint(date, value));
                    }

                    if (InvokeRequired)
                    {
                        Invoke(new Action(() =>
                        {
                            // Обновляем данные в существующей серии
                            salesData.Clear();
                            salesData.AddRange(newSalesData);
                            salesSeries.Values = salesData;
                        }));
                    }
                    else
                    {
                        salesData.Clear();
                        salesData.AddRange(newSalesData);
                        salesSeries.Values = salesData;
                    }
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"Ошибка при обновлении продаж: {ex.Message}");
            }
        }

        private void UpdateSummary(JsonElement data)
        {
            if (dataGridViewSummary != null)
            {
                var moneyInMachines = data.GetProperty("money_in_machines").GetDouble();
                var collectionIncoming = data.GetProperty("collection_incoming").GetDouble();
                var revenueToday = data.GetProperty("revenue_today").GetDouble();
                var revenueYesterday = data.GetProperty("revenue_yesterday").GetDouble();
                var maintenancePlanned = data.GetProperty("maintenance_planned_hours").GetInt32();
                var maintenanceUnplanned = data.GetProperty("maintenance_unplanned_hours").GetInt32();
                var supportRequestsToday = data.GetProperty("support_requests_today").GetInt32();

                dataGridViewSummary.Rows[0].Cells[1].Value = $"{moneyInMachines:N0} ₽";
                dataGridViewSummary.Rows[1].Cells[1].Value = $"{collectionIncoming:N0} ₽";
                dataGridViewSummary.Rows[2].Cells[1].Value = $"{revenueToday:N0} ₽";
                dataGridViewSummary.Rows[3].Cells[1].Value = $"{revenueYesterday:N0} ₽";
                dataGridViewSummary.Rows[4].Cells[1].Value = $"{maintenancePlanned} ч";
                dataGridViewSummary.Rows[5].Cells[1].Value = $"{maintenanceUnplanned} ч";
                dataGridViewSummary.Rows[6].Cells[1].Value = $"{supportRequestsToday}";
            }
        }

        private void UpdateGaugeColor(double percentage)
        {
            SKColor color;

            if (percentage >= 80)
                color = SKColors.Green;
            else if (percentage >= 50)
                color = SKColors.Orange;
            else
                color = SKColors.Red;

            // Обновляем только цвет, не пересоздаем всю серию
            var series = pieChart1.Series.ToArray();
            if (series.Length > 0 && series[0] is PieSeries<ObservableValue> pieSeries)
            {
                pieSeries.Fill = new SolidColorPaint(color);
            }
        }

        private void StartNotificationPolling()
        {
            notificationTimer = new System.Windows.Forms.Timer { Interval = 30000 }; // 30 секунд
            notificationTimer.Tick += async (s, e) => await CheckNotifications();
            notificationTimer.Start();

            // Первая проверка сразу
            Task.Run(async () => await CheckNotifications());
        }

        private async Task CheckNotifications()
        {
            try
            {
                var response = await client.GetAsync("http://127.0.0.1:8000/notifications");
                var responseText = await response.Content.ReadAsStringAsync();

                if (response.IsSuccessStatusCode)
                {
                    var result = JsonSerializer.Deserialize<JsonElement>(responseText);
                    var notifications = result.GetProperty("notifications").EnumerateArray();

                    foreach (var notif in notifications)
                    {
                        var type = notif.GetProperty("type").GetString();
                        var title = notif.GetProperty("title").GetString();
                        var message = notif.GetProperty("message").GetString();
                        var vmId = notif.GetProperty("vending_machine_id").GetInt32();
                        var requiresConfirmation = notif.GetProperty("requires_confirmation").GetBoolean();

                        NotificationType notifType;
                        switch (type?.ToLower())
                        {
                            case "critical":
                                notifType = NotificationType.Critical;
                                break;
                            case "warning":
                                notifType = NotificationType.Warning;
                                break;
                            default:
                                notifType = NotificationType.Info;
                                break;
                        }

                        // Вызываем в UI потоке
                        if (InvokeRequired)
                        {
                            Invoke(new Action(() =>
                            {
                                NotificationManager.ShowNotification(
                                    notifType,
                                    title,
                                    message,
                                    vmId,
                                    requiresConfirmation
                                );
                            }));
                        }
                        else
                        {
                            NotificationManager.ShowNotification(
                                notifType,
                                title,
                                message,
                                vmId,
                                requiresConfirmation
                            );
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"Ошибка при проверке уведомлений: {ex.Message}");
            }
        }

        private void panel1_Paint(object sender, PaintEventArgs e)
        {

        }
    }
}