package com.lona.tictactoe.server;

import java.io.PrintWriter;
import java.util.Arrays;

public class GameInstance {
    private final String code;
    private ClientHandler playerX; // Creator
    private ClientHandler playerO; // Joiner
    private final char[][] board = new char[3][3];
    private char currentTurn = 'X';
    private boolean finished = false;

    public GameInstance(String code, ClientHandler creator) {
        this.code = code;
        this.playerX = creator;
        for (char[] row : board) {
            Arrays.fill(row, ' ');
        }
    }

    public synchronized boolean join(ClientHandler joiner) {
        if (playerO != null)
            return false;
        this.playerO = joiner;
        broadcast("START X");
        sendBoard();
        return true;
    }

    public synchronized void move(ClientHandler player, int x, int y) {
        if (finished || playerO == null)
            return;

        char symbol = (player == playerX) ? 'X' : 'O';

        // --- ANTICHEAT / VALIDATION ---
        // 1. Check if correct turn
        if (symbol != currentTurn) {
            player.sendMessage("ERROR: It is not your turn!");
            return;
        }

        // 2. Check bounds
        if (x < 0 || x > 2 || y < 0 || y > 2) {
            player.sendMessage("ERROR: Invalid coordinates!");
            return;
        }

        // 3. Check if cell is empty
        if (board[x][y] != ' ') {
            player.sendMessage("ERROR: Cell occupied!");
            return;
        }

        // Apply move
        board[x][y] = symbol;
        sendBoard();

        if (checkWin(symbol)) {
            finished = true;
            broadcast("WIN " + symbol);
            createEndState();
        } else if (checkDraw()) {
            finished = true;
            broadcast("DRAW");
            createEndState();
        } else {
            currentTurn = (currentTurn == 'X') ? 'O' : 'X';
            broadcast("TURN " + currentTurn);
        }
    }

    public synchronized void surrender(ClientHandler player) {
        if (finished)
            return;
        finished = true;
        char loser = (player == playerX) ? 'X' : 'O';
        char winner = (loser == 'X') ? 'O' : 'X';
        broadcast("WIN " + winner + " (Surrender)");
        createEndState();
    }

    public synchronized void disconnect(ClientHandler player) {
        if (finished)
            return;
        finished = true;
        broadcast("ERROR: Opponent disconnected");
        createEndState();
    }

    private void createEndState() {
        // cleanup if needed
    }

    private boolean checkWin(char s) {
        // Rows & Cols
        for (int i = 0; i < 3; i++) {
            if (board[i][0] == s && board[i][1] == s && board[i][2] == s)
                return true;
            if (board[0][i] == s && board[1][i] == s && board[2][i] == s)
                return true;
        }
        // Diagonals
        if (board[0][0] == s && board[1][1] == s && board[2][2] == s)
            return true;
        if (board[0][2] == s && board[1][1] == s && board[2][0] == s)
            return true;
        return false;
    }

    private boolean checkDraw() {
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                if (board[i][j] == ' ')
                    return false;
            }
        }
        return true;
    }

    private void sendBoard() {
        StringBuilder sb = new StringBuilder("BOARD ");
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                sb.append(board[i][j]);
            }
        }
        broadcast(sb.toString());
    }

    private void broadcast(String msg) {
        if (playerX != null)
            playerX.sendMessage(msg);
        if (playerO != null)
            playerO.sendMessage(msg);
    }
}
