package com.aksenov.monitor.views.dashboard;

import com.aksenov.monitor.data.Sales;
import com.aksenov.monitor.repositories.*;
import com.aksenov.monitor.services.SalesService;
import com.aksenov.monitor.views.dashboard.ServiceHealth.Status;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.board.Board;
import com.vaadin.flow.component.charts.Chart;
import com.vaadin.flow.component.charts.model.*;
import com.vaadin.flow.component.grid.ColumnTextAlign;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.grid.GridVariant;
import com.vaadin.flow.component.html.H2;
import com.vaadin.flow.component.html.Main;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.select.Select;
import com.vaadin.flow.data.renderer.ComponentRenderer;
import com.vaadin.flow.router.Menu;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.spring.annotation.SpringComponent;
import com.vaadin.flow.theme.lumo.LumoUtility.*;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.vaadin.lineawesome.LineAwesomeIconUrl;

@PageTitle("Dashboard")
@Route("dashboard")
@Menu(order = 6, icon = LineAwesomeIconUrl.CHART_AREA_SOLID)
@SpringComponent
@Scope("prototype")
public class DashboardView extends Main {

    private final CityRepository cityRepository;
    private final CustomerRepository customerRepository;
    private final ManufacturerRepository manufacturerRepository;
    private final MonitorRepository monitorRepository;

    private final SalesService salesService;
    private final SalesRepository salesRepository;



    public DashboardView(CityRepository cityRepository, CustomerRepository customerRepository, ManufacturerRepository manufacturerRepository, MonitorRepository monitorRepository, SalesService salesService, SalesRepository salesRepository) {
        this.cityRepository = cityRepository;
        this.customerRepository = customerRepository;
        this.manufacturerRepository = manufacturerRepository;
        this.monitorRepository = monitorRepository;
        this.salesService = salesService;
        this.salesRepository = salesRepository;
        addClassName("dashboard-view");

        Board board = new Board();
        board.addRow(
                createHighlight("Current amount of sales", String.valueOf(salesRepository.findTotalSalesByMonthAndYear(LocalDateTime.now().getMonthValue(), LocalDateTime.now().getYear())), 33.7),
                createHighlight("Current sales", String.valueOf((long) salesRepository.findAllBySaleDateMonthAndYear(LocalDateTime.now().getMonthValue(), LocalDateTime.now().getYear()).size()), 33.7),
                createHighlight("Current customer", String.valueOf(customerRepository.count()), -112.45));
        board.addRow(createViewEvents());
        board.addRow(createResponseTimes());
        add(board);
    }

    private List<Series> getSalesSeries(int year) {
        List<Series> seriesList = new ArrayList<>();
        String[] categories = new String[]{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
        List<DataSeriesItem> dataSeriesItems = new ArrayList<>();

        for (int i = 0; i < 12; i++) {
            List<Sales> sales = salesService.findSalesByMonthAndYear(i + 1, year);
            int salesCount = sales != null ? sales.size() : 0;
            dataSeriesItems.add(new DataSeriesItem(categories[i], salesCount));
        }


        DataSeries dataSeries = new DataSeries();
        dataSeries.setData(dataSeriesItems);
        seriesList.add(dataSeries);
        return seriesList;
    }


    private Component createHighlight(String title, String value, Double percentage) {
        VaadinIcon icon = VaadinIcon.ARROW_UP;
        String prefix = "";
        String theme = "badge";

        if (percentage == 0) {
            prefix = "±";
        } else if (percentage > 0) {
            prefix = "+";
            theme += " success";
        } else if (percentage < 0) {
            icon = VaadinIcon.ARROW_DOWN;
            theme += " error";
        }

        H2 h2 = new H2(title);
        h2.addClassNames(FontWeight.NORMAL, Margin.NONE, TextColor.SECONDARY, FontSize.XSMALL);

        Span span = new Span(value);
        span.addClassNames(FontWeight.SEMIBOLD, FontSize.XXXLARGE);

        Icon i = icon.create();
        i.addClassNames(BoxSizing.BORDER, Padding.XSMALL);

        Span badge = new Span(i, new Span(prefix + percentage.toString()));
        badge.getElement().getThemeList().add(theme);

        VerticalLayout layout = new VerticalLayout(h2, span, badge);
        layout.addClassName(Padding.LARGE);
        layout.setPadding(false);
        layout.setSpacing(false);
        return layout;
    }

    private Component createViewEvents() {
        // Header
        Select<String> year = new Select<>();
        year.setItems("2011", "2012", "2013", "2014", "2015", "2016", "2017", "2018", "2019", "2020", "2021", "2022", "2023", "2024", "2025");
        year.setValue("2024");
        year.setWidth("100px");


        // Chart
        Chart chart = new Chart(ChartType.AREASPLINE);
        Configuration conf = chart.getConfiguration();
        conf.getChart().setStyledMode(true);

        XAxis xAxis = new XAxis();
        xAxis.setCategories("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
        conf.addxAxis(xAxis);

        conf.getyAxis().setTitle("Values");

        PlotOptionsAreaspline plotOptions = new PlotOptionsAreaspline();
        plotOptions.setPointPlacement(PointPlacement.ON);
        plotOptions.setMarker(new Marker(false));
        conf.addPlotOptions(plotOptions);

        //  Load data for sales chart.
        List<Series> salesSeries = getSalesSeries(Integer.parseInt(year.getValue()));
        conf.setSeries(salesSeries);


        year.addValueChangeListener(event -> {
            chart.getConfiguration().setSeries(getSalesSeries(Integer.parseInt(event.getValue())));
            chart.drawChart();
        });

        // Add it all together
        HorizontalLayout header = createHeader("Sales events", "Sales/month");
        header.add(year);

        VerticalLayout viewEvents = new VerticalLayout(header, chart);
        viewEvents.addClassName(Padding.LARGE);
        viewEvents.setPadding(false);
        viewEvents.setSpacing(false);
        viewEvents.getElement().getThemeList().add("spacing-l");
        return viewEvents;
    }

    private Component createResponseTimes() {
        HorizontalLayout header = createHeader("Sales by Model", "Average across all models");

        // Chart
        Chart chart = new Chart(ChartType.PIE);
        Configuration conf = chart.getConfiguration();
        conf.getChart().setStyledMode(true);
        chart.setThemeName("gradient");

        DataSeries series = new DataSeries();
        Map<String, Long> salesData = salesService.getSalesDataByModel();
        for (Map.Entry<String, Long> entry : salesData.entrySet()) {
            series.add(new DataSeriesItem(entry.getKey(), entry.getValue()));
        }
        conf.addSeries(series);

        // Add it all together
        VerticalLayout serviceHealth = new VerticalLayout(header, chart);
        serviceHealth.addClassName(Padding.LARGE);
        serviceHealth.setPadding(false);
        serviceHealth.setSpacing(false);
        serviceHealth.getElement().getThemeList().add("spacing-l");
        return serviceHealth;
    }
    private HorizontalLayout createHeader(String title, String subtitle) {
        H2 h2 = new H2(title);
        h2.addClassNames(FontSize.XLARGE, Margin.NONE);

        Span span = new Span(subtitle);
        span.addClassNames(TextColor.SECONDARY, FontSize.XSMALL);

        VerticalLayout column = new VerticalLayout(h2, span);
        column.setPadding(false);
        column.setSpacing(false);

        HorizontalLayout header = new HorizontalLayout(column);
        header.setJustifyContentMode(FlexComponent.JustifyContentMode.BETWEEN);
        header.setSpacing(false);
        header.setWidthFull();
        return header;
    }

    private String getStatusDisplayName(ServiceHealth serviceHealth) {
        Status status = serviceHealth.getStatus();
        if (status == Status.OK) {
            return "Ok";
        } else if (status == Status.FAILING) {
            return "Failing";
        } else if (status == Status.EXCELLENT) {
            return "Excellent";
        } else {
            return status.toString();
        }
    }

    private String getStatusTheme(ServiceHealth serviceHealth) {
        Status status = serviceHealth.getStatus();
        String theme = "badge primary small";
        if (status == Status.EXCELLENT) {
            theme += " success";
        } else if (status == Status.FAILING) {
            theme += " error";
        }
        return theme;
    }

}