import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;

public class TaxGuiApp extends JFrame {
    private JTextField incomeField;
    private JSlider incomeSlider;
    private JComboBox<String> statusDropdown;
    private JLabel deductionLabel;
    private JLabel taxableLabel;
    private JLabel resultLabel;
    private JLabel rateLabel;

    private static final int SLIDER_MIN = 0;
    private static final int SLIDER_MAX = 250000;
    private static final int SLIDER_INIT = 50000;

    public TaxGuiApp() {
        setTitle("Federal Income Tax Calculator");
        setSize(520, 380);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        
        JPanel mainPanel = new JPanel();
        mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
        mainPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));

        // 1. Status Panel
        JPanel statusPanel = new JPanel(new GridLayout(1, 2, 10, 10));
        JLabel statusLabel = new JLabel("Filing Status:");
        String[] statuses = { "Single", "Married" };
        statusDropdown = new JComboBox<>(statuses);
        statusPanel.add(statusLabel);
        statusPanel.add(statusDropdown);

        // 2. Income Inputs Panel
        JPanel incomePanel = new JPanel(new GridLayout(2, 2, 10, 10));
        JLabel incomeLabel = new JLabel("Gross Income ($):");
        incomeField = new JTextField(String.valueOf(SLIDER_INIT));
        incomeSlider = new JSlider(JSlider.HORIZONTAL, SLIDER_MIN, SLIDER_MAX, SLIDER_INIT);
        incomeSlider.setMajorTickSpacing(50000);
        incomeSlider.setMinorTickSpacing(10000);
        incomeSlider.setPaintTicks(true);
        
        incomePanel.add(incomeLabel);
        incomePanel.add(incomeField);
        incomePanel.add(new JLabel("Slide to adjust (Max $250k):"));
        incomePanel.add(incomeSlider);

        // 3. Action Trigger Button
        JButton calculateButton = new JButton("Calculate Tax Liability");
        calculateButton.setAlignmentX(Component.CENTER_ALIGNMENT);

        // 4. Output Display Grid Panel
        JPanel outputPanel = new JPanel(new GridLayout(4, 2, 8, 8));
        outputPanel.setBorder(BorderFactory.createTitledBorder("Tax Assessment Summary"));
        
        deductionLabel = new JLabel("$0.00");
        taxableLabel = new JLabel("$0.00");
        resultLabel = new JLabel("$0.00");
        resultLabel.setFont(new Font("Arial", Font.BOLD, 13));
        rateLabel = new JLabel("0.00%");
        
        outputPanel.add(new JLabel("Standard Deduction Applied:"));
        outputPanel.add(deductionLabel);
        outputPanel.add(new JLabel("Calculated Taxable Income:"));
        outputPanel.add(taxableLabel);
        outputPanel.add(new JLabel("Total Tax Owed:"));
        outputPanel.add(resultLabel);
        outputPanel.add(new JLabel("Effective Tax Rate (of Gross):"));
        outputPanel.add(rateLabel);

        mainPanel.add(statusPanel);
        mainPanel.add(Box.createRigidArea(new Dimension(0, 15)));
        mainPanel.add(incomePanel);
        mainPanel.add(Box.createRigidArea(new Dimension(0, 15)));
        mainPanel.add(calculateButton);
        mainPanel.add(Box.createRigidArea(new Dimension(0, 15)));
        mainPanel.add(outputPanel);
        add(mainPanel);

        // -----------------------------------------------------------------
        // EVENT SYNCHRONIZATION LISTENERS
        // -----------------------------------------------------------------

        incomeSlider.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                if (incomeSlider.hasFocus()) {
                    incomeField.setText(String.valueOf(incomeSlider.getValue()));
                }
            }
        });

        incomeField.addFocusListener(new FocusAdapter() {
            @Override
            public void focusLost(FocusEvent e) {
                syncSliderWithText();
            }
        });
        incomeField.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                syncSliderWithText();
            }
        });

        calculateButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                try {
                    double grossIncome = Double.parseDouble(incomeField.getText());
                    String selectedStatus = statusDropdown.getSelectedItem().toString();
                    
                    double taxOwed = 0.0;
                    double activeDeduction = 0.0;

                    if (selectedStatus.equalsIgnoreCase("married")) {
                        activeDeduction = TaxCalculator.MARRIED_DEDUCTION;
                        taxOwed = TaxCalculator.calculateMarriedTax(grossIncome);
                    } else {
                        activeDeduction = TaxCalculator.SINGLE_DEDUCTION;
                        taxOwed = TaxCalculator.calculateSingleTax(grossIncome);
                    }

                    // Leverages backend method model rather than duplicating math
                    double taxableIncome = TaxCalculator.applyStandardDeduction(grossIncome, activeDeduction);
                    
                    double effectiveRate = 0.0;
                    if (grossIncome > 0) {
                        effectiveRate = (taxOwed / grossIncome) * 100.0;
                    }

                    double roundedDeduction = Math.round(activeDeduction * 100.0) / 100.0;
                    double roundedTaxable = Math.round(taxableIncome * 100.0) / 100.0;
                    double roundedTaxOwed = Math.round(taxOwed * 100.0) / 100.0;
                    double roundedRate = Math.round(effectiveRate * 100.0) / 100.0;

                    deductionLabel.setText("-$" + roundedDeduction);
                    taxableLabel.setText("$" + roundedTaxable);
                    resultLabel.setText("$" + roundedTaxOwed);
                    rateLabel.setText(roundedRate + "%");

                } catch (NumberFormatException ex) {
                    JOptionPane.showMessageDialog(TaxGuiApp.this, 
                        "Please enter a valid numeric value for income.", 
                        "Input Error", JOptionPane.ERROR_MESSAGE);
                }
            }
        });
    }

    private void syncSliderWithText() {
        try {
            double parsedValue = Double.parseDouble(incomeField.getText());
            int intValue = (int) parsedValue;

            if (intValue < SLIDER_MIN) {
                incomeSlider.setValue(SLIDER_MIN);
            } else if (intValue > SLIDER_MAX) {
                incomeSlider.setValue(SLIDER_MAX);
            } else {
                incomeSlider.setValue(intValue);
            }
        } catch (NumberFormatException ex) {
            // Ignore format errors during live text alterations
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TaxGuiApp().setVisible(true);
            }
        });
    }
}