package projetMusee.ui;

import projetMusee.backend.DataProcessor;
import projetMusee.backend.Museum;
import projetMusee.backend.enums.*;
import projetMusee.facade.ApplicationFacade;

import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import java.util.*;
import java.util.List;

public class SelectionPanel extends JPanel {
    private JList<String> granulariteList, villeList, themeList;
    private JList<String> selectedVillesPreview, selectedThemesPreview, selectedColorsPreview;
    private JPanel colorPanel;
    private JComboBox<TypeDiagramme> diagramTypeCombo;
    private JComboBox<TypeStatistique> statsTypeCombo;
    private JComboBox<Granularite> granulariteCombo;
    private JButton updateFilterBtn, generateBtn;
    private final ApplicationFacade facade;
    private final List<Museum> allMuseums;
    private final Set<String> selectedVilles = new HashSet<>();
    private final Set<String> selectedThemes = new HashSet<>();
    private final Set<String> selectedColors = new HashSet<>();
    private final Image background = new ImageIcon("data/musee.jpg").getImage();
    private final Map<String, Color> colorMap = new HashMap<>();

    public SelectionPanel() throws Exception {
        try {
            DataProcessor processor = new DataProcessor();
            this.allMuseums = processor.getMusees();
            this.facade = new ApplicationFacade();
            initColorMap();
            initUI();
            setupListeners();
        } catch (Exception e) {
            throw new Exception("Erreur d'initialisation", e);
        }
    }
    
    private void initColorMap() {
        colorMap.put("RED", Color.RED);
        colorMap.put("BLUE", Color.BLUE);
        colorMap.put("GREEN", Color.GREEN);
        colorMap.put("YELLOW", Color.YELLOW);
        colorMap.put("PURPLE", new Color(128, 0, 128));
        colorMap.put("ORANGE", Color.ORANGE);
        colorMap.put("PINK", Color.PINK);
        colorMap.put("BROWN", new Color(139, 69, 19));
        colorMap.put("CYAN", Color.CYAN);
        colorMap.put("MAGENTA", Color.MAGENTA);
        colorMap.put("LIME", new Color(0, 255, 0));
        colorMap.put("TEAL", new Color(0, 128, 128));
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(background, 0, 0, getWidth(), getHeight(), this);
    }

    private void initUI() {
        setLayout(new BorderLayout(15, 15));
        setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
        setOpaque(false);

        // North: Granularity panel with a modern card-like style
        JPanel northPanel = createGranularityPanel();
        northPanel.setBorder(new CompoundBorder(
            new EmptyBorder(10, 10, 10, 10),
            new SoftBevelBorder(BevelBorder.RAISED, Color.LIGHT_GRAY, Color.DARK_GRAY)
        ));
        add(northPanel, BorderLayout.NORTH);

        // Center: Split pane with custom divider
        JSplitPane centerPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
        centerPane.setLeftComponent(createFiltersPanel());
        centerPane.setRightComponent(createSelectionPreviewPanel());
        centerPane.setDividerSize(5);
        centerPane.setDividerLocation(0.5);
        centerPane.setOpaque(false);
        centerPane.setBorder(null);
        centerPane.setUI(new javax.swing.plaf.basic.BasicSplitPaneUI() {
            @Override
            public void paint(Graphics g, JComponent jc) {
                g.setColor(new Color(100, 100, 100, 100));
                g.fillRect(0, 0, ((JSplitPane) jc).getDividerSize(), jc.getHeight());
            }
        });
        add(centerPane, BorderLayout.CENTER);

        // South: Config panel with a clean layout
        JPanel southPanel = createConfigPanel();
        southPanel.setBorder(new CompoundBorder(
            new EmptyBorder(10, 10, 10, 10),
            new SoftBevelBorder(BevelBorder.RAISED, Color.LIGHT_GRAY, Color.DARK_GRAY)
        ));
        add(southPanel, BorderLayout.SOUTH);
    }

    private JPanel createGranularityPanel() {
        JPanel panel = createTitledPanel("Granularité (*)",new FlowLayout(FlowLayout.CENTER, 150, 10));
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(8, 8, 8, 8);
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.anchor = GridBagConstraints.WEST;

        granulariteCombo = new JComboBox<>(Granularite.values());
        granulariteCombo.setPreferredSize(new Dimension(220, 40));
        granulariteCombo.setFont(new Font("Roboto", Font.BOLD, 16));
        granulariteCombo.setBackground(new Color(255, 255, 255, 220));
        granulariteCombo.setBorder(BorderFactory.createLineBorder(Color.GRAY, 1, true));
        gbc.gridx = 0;
        gbc.gridy = 0;
        panel.add(granulariteCombo, gbc);

        granulariteList = createList(6);
        JScrollPane scroll = new JScrollPane(granulariteList);
        scroll.setPreferredSize(new Dimension(400, 100));
        scroll.setBorder(BorderFactory.createEmptyBorder());
        gbc.gridy = 1;
        panel.add(scroll, gbc);

        updateFilterBtn = new JButton("Mettre à jour") {
            @Override
            protected void paintComponent(Graphics g) {
                if (getModel().isRollover()) {
                    g.setColor(new Color(70, 130, 180, 200));
                } else {
                    g.setColor(new Color(70, 130, 180, 150));
                }
                g.fillRoundRect(0, 0, getWidth(), getHeight(), 15, 25);
                super.paintComponent(g);
            }
        };
        updateFilterBtn.setPreferredSize(new Dimension(220, 40));
        updateFilterBtn.setFont(new Font("Roboto", Font.BOLD, 16));
        updateFilterBtn.setForeground(Color.WHITE);
        updateFilterBtn.setContentAreaFilled(false);
        updateFilterBtn.setBorder(BorderFactory.createEmptyBorder());
        gbc.gridy = 2;
        panel.add(updateFilterBtn, gbc);

        return panel;
    }

    private JPanel createFiltersPanel() {
        JPanel panel = createTitledPanel("Filtres disponibles", new FlowLayout(FlowLayout.CENTER, 5, 10));
        panel.setBorder(new EmptyBorder(10, 10, 10, 10));

        villeList = createList(20);
        themeList = createList(20);

        panel.add(createListPanel("Villes", villeList));
        panel.add(createListPanel("Thèmes", themeList));

        return panel;
    }

    private JPanel createSelectionPreviewPanel() {
        JPanel panel = createTitledPanel("Sélections actuelles", new GridLayout(1, 2, 10, 0));
        panel.setOpaque(false);
        
        // Panel pour les villes
        JPanel villesPanel = new JPanel(new BorderLayout());
        villesPanel.setOpaque(false);
        selectedVillesPreview = createList(4);
        villesPanel.add(createListPanel("Villes sélectionnées", selectedVillesPreview), BorderLayout.CENTER);
        villesPanel.add(createDeleteButton("Supprimer ville sélectionnée", selectedVillesPreview, selectedVilles), BorderLayout.SOUTH);
        
        // Panel pour les thèmes
        JPanel themesPanel = new JPanel(new BorderLayout());
        themesPanel.setOpaque(false);
        selectedThemesPreview = createList(4);
        themesPanel.add(createListPanel("Thèmes sélectionnés", selectedThemesPreview), BorderLayout.CENTER);
        themesPanel.add(createDeleteButton("Supprimer thème sélectionné", selectedThemesPreview, selectedThemes), BorderLayout.SOUTH);
        
        panel.add(villesPanel);
        panel.add(themesPanel);
        
        return panel;
    }

    private JButton createDeleteButton(String text, JList<String> list, Set<String> targetSet) {
        JButton btn = new JButton(text);
        btn.setForeground(Color.WHITE);
        btn.setBackground(new Color(220, 53, 69)); // Rouge vif
        btn.setFont(new Font("Roboto", Font.BOLD, 12));
        btn.setFocusPainted(false);
        btn.setBorder(new CompoundBorder(
            new LineBorder(new Color(200, 35, 51), 2, true),
            new EmptyBorder(5, 15, 5, 15)
        ));
        
        // Effet de survol
        btn.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseEntered(java.awt.event.MouseEvent evt) {
                btn.setBackground(new Color(200, 35, 51));
            }
            public void mouseExited(java.awt.event.MouseEvent evt) {
                btn.setBackground(new Color(220, 53, 69));
            }
        });
        
        btn.addActionListener(e -> {
            List<String> selected = list.getSelectedValuesList();
            if(!selected.isEmpty()) {
                targetSet.removeAll(selected);
                updatePreview(list, targetSet);
            }
        });
        
        return btn;
    }

    // Modification de la méthode updatePreview pour accepter JList
    private void updatePreview(JList<String> previewList, Set<String> items) {
        DefaultListModel<String> model = new DefaultListModel<>();
        items.stream().sorted().forEach(model::addElement);
        previewList.setModel(model);
    }

    private JPanel createConfigPanel() {
        JPanel panel = new JPanel(new BorderLayout(15, 15));
        panel.setOpaque(false);

        JPanel configPanel = createTitledPanel("Configuration", new FlowLayout(FlowLayout.CENTER, 20, 10));
        configPanel.setOpaque(false);

        diagramTypeCombo = new JComboBox<>(TypeDiagramme.values());
        diagramTypeCombo.setPreferredSize(new Dimension(420, 40));
        diagramTypeCombo.setFont(new Font("Roboto", Font.BOLD, 16));
        diagramTypeCombo.setBackground(new Color(255, 255, 255, 220));
        diagramTypeCombo.setBorder(BorderFactory.createLineBorder(Color.GRAY, 1, true));
        diagramTypeCombo.setSelectedItem(TypeDiagramme.CAMEMBERT);

        statsTypeCombo = new JComboBox<>(TypeStatistique.values());
        statsTypeCombo.setPreferredSize(new Dimension(420, 40));
        statsTypeCombo.setFont(new Font("Roboto", Font.BOLD, 16));
        statsTypeCombo.setBackground(new Color(255, 255, 255, 220));
        statsTypeCombo.setBorder(BorderFactory.createLineBorder(Color.GRAY, 1, true));
        statsTypeCombo.setSelectedItem(TypeStatistique.PAR_REGION);

        configPanel.add(createComboPanel("Type de diagramme", diagramTypeCombo));
        configPanel.add(createComboPanel("Type de statistique", statsTypeCombo));

        generateBtn = new JButton("Générer le diagramme") {
            @Override
            protected void paintComponent(Graphics g) {
                if (getModel().isRollover()) {
                    g.setColor(new Color(34, 139, 34, 200));
                } else {
                    g.setColor(new Color(34, 139, 34, 150));
                }
                g.fillRoundRect(0, 0, getWidth(), getHeight(), 15, 15);
                super.paintComponent(g);
            }
        };
        generateBtn.setPreferredSize(new Dimension(220, 50));
        generateBtn.setFont(new Font("Roboto", Font.BOLD, 18));
        generateBtn.setForeground(Color.WHITE);
        generateBtn.setContentAreaFilled(false);
        generateBtn.setBorder(BorderFactory.createEmptyBorder());

        JPanel colorPalette = createColorPalette();
        colorPalette.setOpaque(false);

        panel.add(configPanel, BorderLayout.NORTH);
        panel.add(colorPalette, BorderLayout.CENTER);
        panel.add(generateBtn, BorderLayout.SOUTH);

        return panel;
    }

    private JPanel createColorPalette() {
        JPanel panel = createTitledPanel("Palette de couleurs pour le diagramme", new FlowLayout(FlowLayout.CENTER, 5, 10));
        panel.setOpaque(false);
        panel.setPreferredSize(new Dimension(600, 100));

        String[] colors = {"RED", "BLUE", "GREEN", "YELLOW", "PURPLE", "ORANGE", 
        "PINK", "BROWN", "CYAN", "MAGENTA", "LIME", "TEAL"};
        
        for (String color : colors) {
            JButton colorButton = new JButton() {
                @Override
                protected void paintComponent(Graphics g) {
                    Graphics2D g2 = (Graphics2D) g.create();
                    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                    g2.setColor(colorMap.get(color));
                    g2.fillOval(0, 0, 30, 30);
                    if (selectedColors.contains(color)) {
                        g2.setColor(Color.BLACK);
                        g2.setStroke(new BasicStroke(2));
                        g2.drawOval(0, 0, 30, 30);
                    }
                    g2.dispose();
                    super.paintComponent(g);
                }
            };
            colorButton.setText(color);
            colorButton.setPreferredSize(new Dimension(100, 40));
            colorButton.setFont(new Font("Roboto", Font.PLAIN, 14));
            colorButton.setForeground(Color.BLACK);
            colorButton.setContentAreaFilled(false);
            colorButton.setBorder(BorderFactory.createEmptyBorder(0, 40, 0, 0));
            colorButton.addActionListener(e -> {
                if (selectedColors.contains(color)) {
                    selectedColors.remove(color);
                } else {
                    selectedColors.add(color);
                }
                colorButton.repaint();
                updatePreview(selectedColorsPreview, selectedColors);
            });
            panel.add(colorButton);
        }
        return panel;
    }

    private JList<String> createList(int visibleRows) {
        JList<String> list = new JList<String>() {
            @Override
            public void paintComponent(Graphics g) {
                Graphics2D g2 = (Graphics2D) g.create();
                g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                g2.setColor(new Color(255, 255, 255, 50));
                g2.fillRoundRect(0, 0, getWidth(), getHeight(), 10, 10);
                super.paintComponent(g2);
                g2.dispose();
            }
        };
        list.setVisibleRowCount(visibleRows);
        list.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
        list.setFont(new Font("Roboto", Font.BOLD, 16));
        list.setOpaque(false);
        list.setBackground(new Color(0, 0, 0, 0));
        list.setForeground(Color.BLACK);
        list.setSelectionBackground(new Color(70, 130, 180, 100));
        list.setSelectionForeground(Color.WHITE);
        return list;
    }

    private JPanel createTitledPanel(String title, LayoutManager layout) {
        JPanel panel = new JPanel(layout) {
            @Override
            protected void paintComponent(Graphics g) {
                Graphics2D g2 = (Graphics2D) g.create();
                g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                g2.setColor(new Color(255, 255, 255, 180));
                g2.fillRoundRect(0, 0, getWidth(), getHeight(), 15, 15);
                super.paintComponent(g2);
                g2.dispose();
            }
        };
        panel.setBorder(new TitledBorder(
            BorderFactory.createEmptyBorder(),
            title,
            TitledBorder.LEADING,
            TitledBorder.TOP,
            new Font("Roboto", Font.BOLD, 18),
            Color.BLACK
        ));
        panel.setOpaque(false);
        return panel;
    }

    private JPanel createListPanel(String title, JList<String> list) {
        JPanel panel = new JPanel(new BorderLayout(5, 5)) {
            @Override
            protected void paintComponent(Graphics g) {
                Graphics2D g2 = (Graphics2D) g.create();
                g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                g2.setColor(new Color(255, 255, 255, 100));
                g2.fillRoundRect(0, 0, getWidth(), getHeight(), 10, 10);
                super.paintComponent(g2);
                g2.dispose();
            }
        };
        JLabel label = new JLabel(title);
        label.setFont(new Font("Roboto", Font.BOLD, 16));
        label.setForeground(Color.BLACK);
        panel.add(label, BorderLayout.NORTH);
        JScrollPane scroll = new JScrollPane(list);
        scroll.setOpaque(false);
        scroll.getViewport().setOpaque(false);
        scroll.setBorder(BorderFactory.createEmptyBorder());
        panel.add(scroll, BorderLayout.CENTER);
        panel.setOpaque(false);
        return panel;
    }

    private JPanel createComboPanel(String title, JComboBox<?> combo) {
        JPanel panel = new JPanel(new BorderLayout(5, 5));
        panel.setOpaque(false);
        JLabel label = new JLabel(title);
        label.setFont(new Font("Roboto", Font.BOLD, 16));
        label.setForeground(Color.BLACK);
        panel.add(label, BorderLayout.NORTH);
        panel.add(combo, BorderLayout.CENTER);
        return panel;
    }

    private void setupListeners() {
        villeList.addListSelectionListener(e -> {
            if (!e.getValueIsAdjusting()) {
                selectedVilles.addAll(villeList.getSelectedValuesList());
                updatePreview(selectedVillesPreview, selectedVilles);
            }
        });

        themeList.addListSelectionListener(e -> {
            if (!e.getValueIsAdjusting()) {
                selectedThemes.addAll(themeList.getSelectedValuesList());
                updatePreview(selectedThemesPreview, selectedThemes);
            }
        });

        updateFilterBtn.addActionListener(e -> updateFilters());

        generateBtn.addActionListener(this::generateDiagram);

        granulariteCombo.addActionListener(e -> {
            Granularite selected = (Granularite) granulariteCombo.getSelectedItem();
            updateGranularityList(selected);
        });
    }

    private void updateGranularityList(Granularite granularite) {
        DefaultListModel<String> model = new DefaultListModel<>();
        Collection<String> data = switch (granularite) {
            case DEPARTEMENT -> facade.getDepartments(allMuseums);
            case REGION -> facade.getRegions(allMuseums);
        };
        data.stream().sorted().forEach(model::addElement);
        granulariteList.setModel(model);

        selectedVilles.clear();
        selectedThemes.clear();
        selectedColors.clear();
        villeList.setModel(new DefaultListModel<>());
        themeList.setModel(new DefaultListModel<>());
        selectedVillesPreview.setModel(new DefaultListModel<>());
        selectedThemesPreview.setModel(new DefaultListModel<>());
        selectedColorsPreview.setModel(new DefaultListModel<>());
    }

    private void updateFilters() {
        try {
            List<String> selected = granulariteList.getSelectedValuesList();
            if (selected.isEmpty()) {
                JOptionPane.showMessageDialog(this,
                        "Sélectionnez au moins un élément",
                        "Information",
                        JOptionPane.INFORMATION_MESSAGE);
                return;
            }

            Granularite granularite = (Granularite) granulariteCombo.getSelectedItem();
            Map<CritereFiltrage, List<String>> criteria = new EnumMap<>(CritereFiltrage.class);
            criteria.put(granularite == Granularite.DEPARTEMENT ? CritereFiltrage.DEPARTEMENT : CritereFiltrage.REGION,
                    selected);

            List<Museum> filtered = facade.getFilteredMuseums(criteria, allMuseums);

            updateListModel(villeList, facade.getCities(filtered));
            updateListModel(themeList, facade.getThemes(filtered));
        } catch (Exception ex) {
            showError("Erreur de filtrage", ex.getMessage());
        }
    }

    private void updateListModel(JList<String> list, Set<String> data) {
        DefaultListModel<String> model = new DefaultListModel<>();
        data.stream().sorted().forEach(model::addElement);
        list.setModel(model);
    }

    private void generateDiagram(ActionEvent e) {
        try {
            Map<CritereFiltrage, List<String>> criteria = new EnumMap<>(CritereFiltrage.class);
            Granularite granularite = (Granularite) granulariteCombo.getSelectedItem();
            
            // Critère principal
            criteria.put(granularite == Granularite.DEPARTEMENT ? 
                    CritereFiltrage.DEPARTEMENT : CritereFiltrage.REGION,
                    granulariteList.getSelectedValuesList());
    
            // Filtres optionnels
            if (!selectedVilles.isEmpty()) {
                criteria.put(CritereFiltrage.VILLE, new ArrayList<>(selectedVilles));
            }

            if (!selectedThemes.isEmpty()) {
                criteria.put(CritereFiltrage.THEME, new ArrayList<>(selectedThemes));
            }

            List<Museum> filtered = facade.getFilteredMuseums(criteria, allMuseums);
            
            if (filtered.isEmpty()) {
                showWarning("Aucun musée ne correspond aux critères");
                return;
            }

            // Vérifie que l'utilisateur a bien sélectionné des valeurs principales
            List<String> selectedGranularite = granulariteList.getSelectedValuesList();
            if (selectedGranularite.isEmpty()) {
                showWarning("Veuillez sélectionner au moins une région ou un département.");
                return;
            }

            TypeDiagramme diagramType = (TypeDiagramme) diagramTypeCombo.getSelectedItem();
            TypeStatistique statType = (TypeStatistique) statsTypeCombo.getSelectedItem();

            String[] colors = selectedColors.toArray(new String[0]);
            facade.generateDiagramme(diagramType, filtered, statType, colors);
            
            PreviewPanel preview = new PreviewPanel(filtered, diagramType, statType, criteria, this);

            JFrame topFrame = (JFrame) SwingUtilities.getWindowAncestor(this);
            topFrame.setContentPane(preview);
            topFrame.revalidate();
            topFrame.repaint();

            //preview.setVisible(true);
    
        } catch (IOException ex) {
            showError("Erreur de génération", ex.getMessage());
            ex.printStackTrace();
        }
    }

    private void showError(String title, String message) {
        JOptionPane.showMessageDialog(this, message, title, JOptionPane.ERROR_MESSAGE);
    }

    private void showWarning(String message) {
        JOptionPane.showMessageDialog(this, message, "Attention", JOptionPane.WARNING_MESSAGE);
    }

    public List<String> getSelectedColors() {
        return new ArrayList<>(selectedColors);
    }

}