package com.lona.tictactoe.client;

import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.net.Socket;

public class Main extends JFrame {
    private Socket socket;
    private PrintWriter out;
    private BufferedReader in;

    private CardLayout cardLayout = new CardLayout();
    private JPanel mainPanel = new JPanel(cardLayout);

    // Menu Components
    private JTextField joinCodeField = new JTextField(10);

    // Game Components
    private JButton[] buttons = new JButton[9];
    private JLabel statusLabel = new JLabel("Connecting...");
    private JLabel codeLabel = new JLabel("Code: -");
    private boolean myTurn = false;
    private char mySymbol = ' '; // assigned by server implied turn

    public static void main(String[] args) {
        String host = "38.242.130.81";
        int port = 1870;

        if (args.length > 0) {
            host = args[0];
        }
        if (args.length > 1) {
            try {
                port = Integer.parseInt(args[1]);
            } catch (NumberFormatException e) {
                System.err.println("Invalid port number provided, using default 1870");
            }
        }

        final String serverHost = host;
        final int serverPort = port;

        System.out.println("Starting TicTacToe Client...");
        System.out.println("Target Server: " + serverHost + ":" + serverPort);

        SwingUtilities.invokeLater(() -> {
            try {
                Main client = new Main(serverHost, serverPort);
                client.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
                System.err.println("Failed to start GUI: " + e.getMessage());
            }
        });
    }

    // Instance variables
    private final String serverHost;
    private final int serverPort;

    public Main(String host, int port) {
        super("TicTacToe Client");
        this.serverHost = host;
        this.serverPort = port;

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(400, 500);
        setLocationRelativeTo(null);

        try {
            initUI();
            setContentPane(mainPanel);
            connectToServer();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void initUI() {
        // --- MENU PANEL ---
        JPanel menuPanel = new JPanel(new GridBagLayout());
        JButton createBtn = new JButton("Create Game");
        JButton joinBtn = new JButton("Join Game");

        createBtn.addActionListener(e -> send("CREATE"));
        joinBtn.addActionListener(e -> {
            String code = joinCodeField.getText().trim();
            if (!code.isEmpty())
                send("JOIN " + code);
        });

        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(5, 5, 5, 5);
        gbc.gridx = 0;
        gbc.gridy = 0;
        menuPanel.add(createBtn, gbc);

        gbc.gridy = 1;
        menuPanel.add(new JLabel("Enter Code:"), gbc);
        gbc.gridy = 2;
        menuPanel.add(joinCodeField, gbc);
        gbc.gridy = 3;
        menuPanel.add(joinBtn, gbc);

        // --- GAME PANEL ---
        JPanel gamePanel = new JPanel(new BorderLayout());

        JPanel topPanel = new JPanel(new GridLayout(2, 1));
        topPanel.add(statusLabel);
        topPanel.add(codeLabel);
        gamePanel.add(topPanel, BorderLayout.NORTH);

        JPanel boardPanel = new JPanel(new GridLayout(3, 3));
        for (int i = 0; i < 9; i++) {
            int finalI = i;
            buttons[i] = new JButton("");
            buttons[i].setFont(new Font("Arial", Font.BOLD, 40));
            buttons[i].setFocusPainted(false);
            buttons[i].addActionListener(e -> {
                int r = finalI / 3;
                int c = finalI % 3;
                send("MOVE " + r + " " + c);
            });
            boardPanel.add(buttons[i]);
        }
        gamePanel.add(boardPanel, BorderLayout.CENTER);

        // --- BUTTONS PANEL ---
        JPanel buttonPanel = new JPanel(new GridLayout(1, 2, 10, 0));

        JButton leaveBtn = new JButton("Leave Lobby");
        leaveBtn.setBackground(Color.GRAY);
        leaveBtn.setForeground(Color.WHITE);
        leaveBtn.addActionListener(e -> {
            send("LEAVE");
            resetGame();
        });

        JButton surrenderBtn = new JButton("Surrender");
        surrenderBtn.setBackground(new Color(220, 53, 69)); // Bootstrap Danger Red
        surrenderBtn.setForeground(Color.WHITE);
        surrenderBtn.addActionListener(e -> send("SURRENDER"));

        buttonPanel.add(leaveBtn);
        buttonPanel.add(surrenderBtn);

        gamePanel.add(buttonPanel, BorderLayout.SOUTH);

        mainPanel.add(menuPanel, "MENU");
        mainPanel.add(gamePanel, "GAME");
    }

    private void connectToServer() {
        new Thread(() -> {
            try {
                System.out.println("Attempting to connect to " + serverHost + ":" + serverPort);
                socket = new Socket(serverHost, serverPort);
                out = new PrintWriter(socket.getOutputStream(), true);
                in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

                System.out.println("Connected successfully!");
                SwingUtilities.invokeLater(() -> statusLabel.setText("Connected to Server."));

                String line;
                while ((line = in.readLine()) != null) {
                    System.out.println("Received: " + line); // Log received messages
                    processMessage(line);
                }
            } catch (IOException e) {
                System.err.println("Connection Error: " + e.getMessage());
                SwingUtilities.invokeLater(() -> {
                    statusLabel.setText("Connection Failed.");
                    JOptionPane.showMessageDialog(this, "Connection Error: " + e.getMessage());
                    // Don't reset to menu if we can't connect, let user see error
                });
            }
        }).start();
    }

    private void send(String msg) {
        if (out != null)
            out.println(msg);
    }

    private void processMessage(String msg) {
        SwingUtilities.invokeLater(() -> handleMessage(msg));
    }

    private void handleMessage(String msg) {
        String[] parts = msg.split(" ");
        String cmd = parts[0];

        switch (cmd) {
            case "GAME_CREATED":
                cardLayout.show(mainPanel, "GAME");
                if (parts.length > 1) {
                    codeLabel.setText("Code: " + parts[1]);
                    mySymbol = 'X'; // Creator starts as X usually
                    statusLabel.setText("Game Created. Waiting for opponent...");
                }
                break;
            case "JOIN_SUCCESS":
                cardLayout.show(mainPanel, "GAME");
                mySymbol = 'O'; // Joiner is O
                statusLabel.setText("Joined Game.");
                codeLabel.setText("Code: " + joinCodeField.getText());
                break;
            case "START":
                statusLabel.setText("Game Started! X goes first.");
                break;
            case "RESTART":
                // clear board
                for (JButton btn : buttons)
                    btn.setText("");
                statusLabel.setText("Game Restarted! X goes first.");
                break;
            case "BOARD": // BOARD X O X ...
                String boardStr = msg.substring(6); // remove "BOARD "
                for (int i = 0; i < 9 && i < boardStr.length(); i++) {
                    char c = boardStr.charAt(i);
                    buttons[i].setText(String.valueOf(c));
                }
                break;
            case "TURN":
                if (parts.length > 1) {
                    char turn = parts[1].charAt(0);
                    if (turn == mySymbol) {
                        statusLabel.setText("Your Turn (" + mySymbol + ")");
                    } else {
                        statusLabel.setText("Opponent's Turn (" + turn + ")");
                    }
                }
                break;
            case "WIN":
                String winner = msg.substring(4);
                statusLabel.setText("Winner: " + winner);
                int choice = JOptionPane.showConfirmDialog(this,
                        "Winner: " + winner + "\nPlay Again?",
                        "Game Over",
                        JOptionPane.YES_NO_OPTION);

                if (choice == JOptionPane.YES_OPTION) {
                    send("RESTART");
                }
                break;
            case "DRAW":
                statusLabel.setText("Draw!");
                int drawChoice = JOptionPane.showConfirmDialog(this,
                        "Draw!\nPlay Again?",
                        "Game Over",
                        JOptionPane.YES_NO_OPTION);

                if (drawChoice == JOptionPane.YES_OPTION) {
                    send("RESTART");
                }
                break;
            case "OPPONENT_LEFT":
                JOptionPane.showMessageDialog(this, "Opponent left the game.");
                resetGame();
                break;
            case "ERROR:":
                if (msg.contains("It is not your turn")) {
                    statusLabel.setText("Not your turn!");
                } else {
                    JOptionPane.showMessageDialog(this, msg);
                }
                break;
        }
    }

    private void resetGame() {
        cardLayout.show(mainPanel, "MENU");
        for (JButton btn : buttons)
            btn.setText("");
        statusLabel.setText("Connected.");
        codeLabel.setText("Code: -");
    }
}
