package vassistent.ui;

import vassistent.util.ConfigLoader;

import javax.swing.*;
import java.awt.*;
import java.util.Locale;
import java.util.Properties;

/**
 * Main Swing frame containing streaming and dashboard tabs plus status indicators.
 */
public class AppWindow extends JFrame {

    private static final int EXPANDED_DASHBOARD_WIDTH = 460;
    private static final int EXPANDED_DIVIDER_SIZE = 8;

    private static final Properties config =
            ConfigLoader.loadProperties(
                    "config/application.properties"
            );

    private PixelStreamingView streamingView;
    private DashboardView dashboardView;
    private JTabbedPane tabs;
    private JSplitPane driveSplitPane;
    private JPanel dashboardCard;
    private JToggleButton dashboardToggleButton;

    private JLabel mqttStatusLabel;
    private JLabel problemLevelLabel;

    /**
     * Creates and initializes the main application window and its child views.
     */
    public AppWindow() {

        setTitle("Virtueller Gesundheitsassistent");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setMinimumSize(new Dimension(1280, 720));
        setSize(1700, 900);
        setLocationRelativeTo(null);
        getContentPane().setBackground(new Color(15, 19, 26));

        setLayout(new BorderLayout(12, 12));

        String streamUrl =
                normalizeConfigValue(
                        config.getProperty("streaming.url", "http://localhost")
                );

        streamingView = new PixelStreamingView(
                streamUrl,
                false,
                false
        );

        dashboardView = new DashboardView();

        add(createHeaderPanel(), BorderLayout.NORTH);
        tabs = createTabPane();
        add(tabs, BorderLayout.CENTER);
        add(createStatusBar(), BorderLayout.SOUTH);
        SwingUtilities.invokeLater(() -> setDashboardVisible(false));

        Font uiFont = new Font("Segoe UI", Font.PLAIN, 16);
        UIManager.put("Label.font", uiFont);
        UIManager.put("TabbedPane.font", uiFont);
    }

    /**
     * Creates the tabbed pane that hosts streaming and dashboard views.
     *
     * @return configured tabbed pane
     */
    private JTabbedPane createTabPane() {

        JTabbedPane tabs = new JTabbedPane();
        tabs.setBorder(BorderFactory.createEmptyBorder(0, 10, 6, 10));
        tabs.setFocusable(false);
        tabs.putClientProperty("JTabbedPane.tabHeight", 38);
        tabs.putClientProperty("JTabbedPane.hideTabAreaWithOneTab", true);
        tabs.addTab("Drive View", createDriveViewPanel());

        return tabs;
    }

    /**
     * Creates the center-display optimized drive panel.
     *
     * @return drive panel with large assistant stream and compact dashboard
     */
    private JPanel createDriveViewPanel() {
        JPanel drivePanel = new JPanel(new BorderLayout());
        drivePanel.setOpaque(false);
        drivePanel.setBorder(BorderFactory.createEmptyBorder(6, 0, 0, 0));

        JPanel streamCard = createCardPanel();
        streamCard.setLayout(new BorderLayout(0, 12));
        streamCard.add(
                createSectionHeader(
                        "Virtual Health Assistant",
                        null
                ),
                BorderLayout.NORTH
        );
        streamCard.add(streamingView, BorderLayout.CENTER);

        dashboardCard = createCardPanel();
        dashboardCard.setLayout(new BorderLayout(0, 12));
        dashboardCard.add(
                createSectionHeader(
                        "Health Overview",
                        "Live trend and current risk level"
                ),
                BorderLayout.NORTH
        );
        dashboardCard.add(dashboardView, BorderLayout.CENTER);
        dashboardCard.setPreferredSize(new Dimension(EXPANDED_DASHBOARD_WIDTH, 0));
        dashboardCard.setMinimumSize(new Dimension(380, 0));

        driveSplitPane =
                new JSplitPane(
                        JSplitPane.HORIZONTAL_SPLIT,
                        streamCard,
                        dashboardCard
                );

        driveSplitPane.setBorder(null);
        driveSplitPane.setOpaque(false);
        driveSplitPane.setContinuousLayout(true);
        driveSplitPane.setOneTouchExpandable(false);
        driveSplitPane.setDividerSize(EXPANDED_DIVIDER_SIZE);
        driveSplitPane.setResizeWeight(0.72);
        driveSplitPane.setDividerLocation(0.72);

        drivePanel.add(driveSplitPane, BorderLayout.CENTER);

        return drivePanel;
    }

    /**
     * Creates a top banner with project title and context.
     *
     * @return header panel
     */
    private JPanel createHeaderPanel() {
        JPanel header = new JPanel(new BorderLayout(12, 0));
        header.setBorder(BorderFactory.createEmptyBorder(12, 16, 0, 16));
        header.setOpaque(false);

        JLabel title = new JLabel("Virtueller Gesundheitsassistent");
        title.setFont(new Font("Segoe UI Semibold", Font.PLAIN, 30));
        title.setForeground(new Color(238, 244, 255));

        JPanel textStack = new JPanel();
        textStack.setLayout(new BoxLayout(textStack, BoxLayout.Y_AXIS));
        textStack.setOpaque(false);
        title.setAlignmentX(Component.LEFT_ALIGNMENT);
        textStack.add(title);
        textStack.add(Box.createVerticalStrut(4));

        header.add(textStack, BorderLayout.WEST);
        header.add(createDashboardToggleButton(), BorderLayout.EAST);

        return header;
    }

    /**
     * Creates the status bar with MQTT and problem-level indicators.
     *
     * @return configured status bar panel
     */
    private JPanel createStatusBar() {

        JPanel statusBar = new JPanel(new FlowLayout(FlowLayout.LEFT, 12, 8));
        statusBar.setBackground(new Color(13, 16, 23));

        statusBar.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createMatteBorder(1, 0, 0, 0, new Color(54, 64, 78)),
                BorderFactory.createEmptyBorder(6, 12, 8, 12)
        ));

        mqttStatusLabel = createStatusChip("MQTT: Disconnected");
        problemLevelLabel = createStatusChip("Problem: NONE");

        statusBar.add(mqttStatusLabel);
        statusBar.add(problemLevelLabel);

        return statusBar;
    }

    /**
     * Updates the MQTT connection status label.
     *
     * @param connected whether MQTT is currently connected
     */
    public void updateMqttStatus(boolean connected) {
        mqttStatusLabel.setText("MQTT: "
                + (connected ? "Connected" : "Disconnected"));
        mqttStatusLabel.setBackground(
                connected ? new Color(30, 101, 70) : new Color(108, 47, 47)
        );
    }

    /**
     * Updates the currently displayed problem level label.
     *
     * @param level problem level name to display
     */
    public void updateProblemLevel(String level) {
        problemLevelLabel.setText("Problem: " + level);
        problemLevelLabel.setBackground(getProblemChipColor(level));
    }

    /**
     * Returns the dashboard view component.
     *
     * @return dashboard view
     */
    public DashboardView getDashboardView() {
        return dashboardView;
    }

    /**
     * Returns the pixel streaming view component.
     *
     * @return streaming view
     */
    public PixelStreamingView getStreamingView() {
        return streamingView;
    }

    /**
     * Returns the main tabbed pane.
     *
     * @return tab container
     */
    public JTabbedPane getTabs() {
        return tabs;
    }

    /**
     * Creates a panel with a subtle border and dark background.
     *
     * @return styled card panel
     */
    private JPanel createCardPanel() {
        JPanel card = new JPanel();
        card.setOpaque(true);
        card.setBackground(new Color(24, 31, 41));
        card.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createLineBorder(new Color(61, 74, 92)),
                BorderFactory.createEmptyBorder(12, 12, 12, 12)
        ));
        return card;
    }

    /**
     * Creates a section heading with title and subtitle text.
     *
     * @param title section title
     * @param subtitle section subtitle
     * @return heading panel
     */
    private JPanel createSectionHeader(String title, String subtitle) {
        JPanel panel = new JPanel();
        panel.setOpaque(false);
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));

        JLabel titleLabel = new JLabel(title);
        titleLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
        titleLabel.setFont(new Font("Segoe UI Semibold", Font.PLAIN, 20));
        titleLabel.setForeground(new Color(233, 241, 255));

        JLabel subtitleLabel = new JLabel(subtitle);
        subtitleLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
        subtitleLabel.setFont(new Font("Segoe UI", Font.PLAIN, 13));
        subtitleLabel.setForeground(new Color(143, 159, 182));

        panel.add(titleLabel);
        panel.add(Box.createVerticalStrut(2));
        panel.add(subtitleLabel);

        return panel;
    }

    /**
     * Creates one status label used in the bottom status bar.
     *
     * @param text initial status text
     * @return styled status label
     */
    private JLabel createStatusChip(String text) {
        JLabel label = new JLabel(text);
        label.setOpaque(true);
        label.setFont(new Font("Segoe UI Semibold", Font.PLAIN, 14));
        label.setForeground(new Color(237, 244, 255));
        label.setBackground(new Color(56, 66, 83));
        label.setBorder(BorderFactory.createEmptyBorder(5, 12, 5, 12));
        return label;
    }

    /**
     * Returns a status chip background color for the current problem level.
     *
     * @param level problem level name
     * @return matching background color
     */
    private Color getProblemChipColor(String level) {
        if (level == null) {
            return new Color(56, 66, 83);
        }

        String normalized = level.trim().toUpperCase(Locale.ROOT);

        switch (normalized) {
            case "WARNING":
                return new Color(134, 104, 29);
            case "HIGH":
                return new Color(168, 92, 31);
            case "DISASTER":
                return new Color(140, 49, 49);
            default:
                return new Color(46, 99, 61);
        }
    }

    /**
     * Creates the button used to toggle dashboard visibility.
     *
     * @return configured toggle button
     */
    private JToggleButton createDashboardToggleButton() {
        dashboardToggleButton = new JToggleButton("Dashboard einblenden");
        dashboardToggleButton.setFocusable(false);
        dashboardToggleButton.setFont(new Font("Segoe UI Semibold", Font.PLAIN, 14));
        dashboardToggleButton.setForeground(new Color(233, 241, 255));
        dashboardToggleButton.setBackground(new Color(39, 77, 57));
        dashboardToggleButton.setBorder(BorderFactory.createEmptyBorder(8, 14, 8, 14));
        dashboardToggleButton.addActionListener(
                event -> setDashboardVisible(dashboardToggleButton.isSelected())
        );
        return dashboardToggleButton;
    }

    /**
     * Shows or hides the dashboard side panel in drive view.
     *
     * @param visible whether dashboard should be visible
     */
    private void setDashboardVisible(boolean visible) {
        if (driveSplitPane == null || dashboardCard == null || dashboardToggleButton == null) {
            return;
        }

        dashboardCard.setVisible(visible);
        driveSplitPane.setDividerSize(visible ? EXPANDED_DIVIDER_SIZE : 0);

        if (visible) {
            dashboardToggleButton.setSelected(true);
            dashboardToggleButton.setText("Dashboard ausblenden");
            dashboardToggleButton.setBackground(new Color(69, 86, 109));

            SwingUtilities.invokeLater(() -> {
                int width = driveSplitPane.getWidth();
                if (width <= 0) {
                    driveSplitPane.setDividerLocation(0.72);
                    return;
                }

                int dividerLocation = Math.max(
                        (int) (width * 0.55),
                        width - EXPANDED_DASHBOARD_WIDTH
                );
                driveSplitPane.setDividerLocation(dividerLocation);
            });
        } else {
            dashboardToggleButton.setSelected(false);
            dashboardToggleButton.setText("Dashboard einblenden");
            dashboardToggleButton.setBackground(new Color(39, 77, 57));

            SwingUtilities.invokeLater(() -> {
                int width = driveSplitPane.getWidth();
                if (width > 0) {
                    driveSplitPane.setDividerLocation(width);
                } else {
                    driveSplitPane.setDividerLocation(1.0d);
                }
            });
        }

        driveSplitPane.revalidate();
        driveSplitPane.repaint();
    }

    /**
     * Trims a config value and strips optional wrapping quotes.
     *
     * @param value raw config value
     * @return normalized value or {@code null}
     */
    private static String normalizeConfigValue(String value) {
        if (value == null) {
            return null;
        }

        String trimmed = value.trim();

        if ((trimmed.startsWith("\"") && trimmed.endsWith("\""))
                || (trimmed.startsWith("'") && trimmed.endsWith("'"))) {
            return trimmed.substring(1, trimmed.length() - 1);
        }

        return trimmed;
    }
}
