<template>
	<div class="socket-test-view">
		<div class="test-header">
			<h1>Socket API Test Page</h1>
			<p class="subtitle">Testing Backend Game Socket Handlers</p>
		</div>

		<div class="test-body">
			<!-- Left Column: Controls and Status -->
			<div class="left-column">
				<!-- Connection Status -->
				<div class="test-section">
					<h2>Connection Status</h2>
				<div class="status-info">
					<div class="status-item" :class="{ ready: connected, error: error }">
						<span class="status-label">Socket:</span>
						<span class="status-value">
							{{ connected ? "✓ Connected" : "⚪ Disconnected" }}
						</span>
					</div>
					<div v-if="socket" class="status-item">
						<span class="status-label">Socket ID:</span>
						<span class="status-value code">{{ socket.id }}</span>
					</div>
					<div v-if="error" class="error-message">❌ Error: {{ error }}</div>
				</div>
			</div>

			<!-- Room Management -->
			<div class="test-section">
				<h2>Room Management</h2>
				<div class="room-info">
					<div class="info-item">
						<span class="label">Current Room:</span>
						<span class="value code">{{ currentRoomId || "Not in room" }}</span>
					</div>
					<div v-if="playerColor" class="info-item">
						<span class="label">Player Color:</span>
						<span class="value" :class="playerColor">{{ playerColor }}</span>
					</div>
					<div v-if="currentRoomId" class="info-item">
						<span class="label">Room Admin:</span>
						<span class="value">{{ isAdmin ? "You (Admin)" : "Other player" }}</span>
					</div>
				</div>

				<div class="room-controls">
					<div class="control-group">
						<input
							v-model="nickname"
							type="text"
							placeholder="Nickname"
							class="input-text"
						/>
						<input
							v-model="roomIdInput"
							type="text"
							placeholder="Room ID (leave empty to create)"
							class="input-text"
						/>
					</div>
					<div class="button-group">
						<button
							class="btn btn-primary"
							@click="testJoinRoom"
							:disabled="!connected || currentRoomId !== null"
						>
							Join/Create Room
						</button>
						<button
							class="btn btn-secondary"
							@click="testLeaveRoom"
							:disabled="!currentRoomId"
						>
							Leave Room
						</button>
					</div>
				</div>
			</div>

			<!-- Game State Display -->
			<div class="test-section">
				<h2>Game State</h2>
				<div class="game-info">
					<div class="info-item">
						<span class="label">Game Status:</span>
						<span class="value">{{ gameState.gameStatus || "N/A" }}</span>
					</div>
					<div class="info-item">
						<span class="label">Current Player:</span>
						<span class="value" :class="gameState.currentPlayer">
							{{ gameState.currentPlayer || "N/A" }}
						</span>
					</div>
					<div class="info-item">
						<span class="label">Current Index:</span>
						<span class="value">{{ gameState.currentMoveIndex }}</span>
					</div>
					<div class="info-item">
						<span class="label">Captured (Black):</span>
						<span class="value">{{ gameState.capturedStones.black }}</span>
					</div>
					<div class="info-item">
						<span class="label">Captured (White):</span>
						<span class="value">{{ gameState.capturedStones.white }}</span>
					</div>
				</div>

				<!-- TGN Display -->
				<div v-if="gameState.tgn" class="tgn-display">
					<h3>Current TGN:</h3>
					<pre class="tgn-content">{{ gameState.tgn }}</pre>
				</div>
			</div>

			<!-- Game Actions -->
			<div class="test-section">
				<h2>Game Actions</h2>
				<div class="game-controls">
					<div class="control-group">
						<input
							v-model.number="moveX"
							type="number"
							placeholder="X"
							class="input-number"
							min="0"
							max="4"
						/>
						<input
							v-model.number="moveY"
							type="number"
							placeholder="Y"
							class="input-number"
							min="0"
							max="4"
						/>
						<input
							v-model.number="moveZ"
							type="number"
							placeholder="Z"
							class="input-number"
							min="0"
							max="4"
						/>
						<button
							class="btn btn-primary"
							@click="testMakeMove"
							:disabled="!currentRoomId"
						>
							Make Move
						</button>
					</div>
					<div class="button-group">
						<button
							class="btn btn-secondary"
							@click="testPass"
							:disabled="!currentRoomId"
						>
							Pass
						</button>
						<button
							class="btn btn-warning"
							@click="testResign"
							:disabled="!currentRoomId"
						>
							Resign
						</button>
					</div>
				</div>
			</div>

			<!-- Admin Actions -->
			<div class="test-section admin-section">
				<h2>Admin Actions (Undo/Redo/Reset)</h2>
				<p class="section-desc">Test the new admin APIs</p>
				<div v-if="!isAdmin && currentRoomId" class="admin-warning">
					⚠️ Only the room admin can reset the game
				</div>
				<div class="button-group">
					<button
						class="btn btn-admin"
						@click="testUndo"
						:disabled="!currentRoomId || gameState.currentMoveIndex === 0"
					>
						Undo Move
					</button>
					<button
						class="btn btn-admin"
						@click="testRedo"
						:disabled="!currentRoomId"
					>
						Redo Move
					</button>
				</div>
				<div class="reset-controls">
					<div class="control-group">
						<label class="input-label">Board Shape:</label>
						<input
							v-model.number="boardShapeX"
							type="number"
							placeholder="X"
							class="input-number"
							min="3"
							max="9"
						/>
						<input
							v-model.number="boardShapeY"
							type="number"
							placeholder="Y"
							class="input-number"
							min="3"
							max="9"
						/>
						<input
							v-model.number="boardShapeZ"
							type="number"
							placeholder="Z"
							class="input-number"
							min="3"
							max="9"
						/>
					</div>
					<div v-if="roomPlayers.length === 2" class="control-group">
						<label class="checkbox-label">
							<input type="checkbox" v-model="swapColors" />
							Swap Player Colors (Black ↔ White)
						</label>
					</div>
					<button class="btn btn-danger" @click="testReset" :disabled="!currentRoomId || !isAdmin">
						Reset Game (Admin Only)
					</button>
				</div>
			</div>

			</div>
			<!-- End Left Column -->

			<!-- Right Column: Event Log -->
			<div class="right-column">
				<!-- Event Log -->
				<div class="test-section event-log-section">
					<h2>Event Log</h2>
					<div class="event-log-controls">
						<button class="btn btn-secondary" @click="clearEventLog">Clear Log</button>
						<label class="checkbox-label">
							<input type="checkbox" v-model="autoScroll" />
							Auto-scroll
						</label>
					</div>
					<div class="event-log" ref="eventLogRef">
						<div v-if="eventLog.length === 0" class="empty-state">No events yet</div>
						<div
							v-for="(event, index) in eventLog"
							:key="index"
							class="event-item"
							:class="event.type"
						>
							<span class="event-timestamp">{{ event.timestamp }}</span>
							<span class="event-name">{{ event.name }}</span>
							<span class="event-type-badge">{{ event.type }}</span>
							<pre class="event-data">{{ JSON.stringify(event.data, null, 2) }}</pre>
						</div>
					</div>
				</div>
			</div>
			<!-- End Right Column -->

		</div>
	</div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, onUnmounted, nextTick, watch } from "vue";
import { useSocket } from "@/composables/useSocket";

// Socket composable
const { socket, connected, error } = useSocket();

// Room state
const currentRoomId = ref<string | null>(null);
const playerColor = ref<string | null>(null);
const nickname = ref("TestUser");
const roomIdInput = ref("");
const isAdmin = ref(false);
const roomPlayers = ref<string[]>([]);
const playerColorAssignments = reactive<{ [playerId: string]: "black" | "white" }>({});
const swapColors = ref(false);

// Game state
const gameState = reactive({
	currentPlayer: null as string | null,
	currentMoveIndex: 0,
	capturedStones: { black: 0, white: 0 },
	gameStatus: null as string | null,
	tgn: "" as string
});

// Move inputs
const moveX = ref(0);
const moveY = ref(0);
const moveZ = ref(0);

// Board shape inputs for reset
const boardShapeX = ref(5);
const boardShapeY = ref(5);
const boardShapeZ = ref(5);

// Event log
const eventLog = ref<
	Array<{
		timestamp: string;
		name: string;
		type: "sent" | "received" | "error";
		data: any;
	}>
>([]);
const eventLogRef = ref<HTMLElement | null>(null);
const autoScroll = ref(true);

// Helper to log events
function logEvent(name: string, data: any, type: "sent" | "received" | "error" = "received") {
	const timestamp = new Date().toLocaleTimeString();
	eventLog.value.push({ timestamp, name, type, data });

	if (autoScroll.value) {
		nextTick(() => {
			if (eventLogRef.value) {
				eventLogRef.value.scrollTop = eventLogRef.value.scrollHeight;
			}
		});
	}
}

function clearEventLog() {
	eventLog.value = [];
}

// Room management
function testJoinRoom() {
	const data = {
		roomId: roomIdInput.value || undefined,
		nickname: nickname.value
	};
	logEvent("joinRoom", data, "sent");

	socket.emit("joinRoom", data, (response: any) => {
		logEvent("joinRoom:response", response, response.success ? "received" : "error");

		if (response.success) {
			currentRoomId.value = response.roomId;
			playerColor.value = response.playerColor;
			isAdmin.value = response.isAdmin || false;

			// Initialize room players from response
			if (response.players) {
				roomPlayers.value = Object.keys(response.players);
				// Initialize player color assignments
				for (const [playerId, playerInfo] of Object.entries(response.players) as any) {
					playerColorAssignments[playerId] = playerInfo.color;
				}
			}

			// Update game state
			if (response.gameState) {
				Object.assign(gameState, response.gameState);

				// Update board shape inputs
				if (response.gameState.boardShape) {
					boardShapeX.value = response.gameState.boardShape.x;
					boardShapeY.value = response.gameState.boardShape.y;
					boardShapeZ.value = response.gameState.boardShape.z;
				}
			}
		}
	});
}

function testLeaveRoom() {
	logEvent("leaveRoom", {}, "sent");
	socket.emit("leaveRoom");

	// Reset local state
	currentRoomId.value = null;
	playerColor.value = null;
	Object.assign(gameState, {
		currentPlayer: null,
		currentMoveIndex: 0,
		capturedStones: { black: 0, white: 0 },
		gameStatus: null,
		tgn: ""
	});
}

// Game actions
function testMakeMove() {
	const data = { x: moveX.value, y: moveY.value, z: moveZ.value };
	logEvent("makeMove", data, "sent");
	socket.emit("makeMove", data);
}

function testPass() {
	logEvent("pass", {}, "sent");
	socket.emit("pass");
}

function testResign() {
	if (!confirm("Are you sure you want to resign?")) return;
	logEvent("resign", {}, "sent");
	socket.emit("resign");
}

// Admin actions
function testUndo() {
	logEvent("undoMove", {}, "sent");
	socket.emit("undoMove", (response: any) => {
		logEvent("undoMove:response", response, response.success ? "received" : "error");
	});
}

function testRedo() {
	logEvent("redoMove", {}, "sent");
	socket.emit("redoMove", (response: any) => {
		logEvent("redoMove:response", response, response.success ? "received" : "error");
	});
}

function testReset() {
	if (!confirm("Reset entire game?")) return;
	const data: any = {
		boardShape: {
			x: boardShapeX.value,
			y: boardShapeY.value,
			z: boardShapeZ.value
		}
	};

	// Apply color swap if checkbox is checked
	if (swapColors.value && roomPlayers.value.length === 2) {
		const [player1, player2] = roomPlayers.value;
		const color1 = playerColorAssignments[player1];
		const color2 = playerColorAssignments[player2];

		// Swap the colors
		data.playerColors = {
			[player1]: color2,
			[player2]: color1
		};
	}

	logEvent("resetGame", data, "sent");
	socket.emit("resetGame", data, (response: any) => {
		logEvent("resetGame:response", response, response.success ? "received" : "error");
	});
}

// Socket event listeners
onMounted(() => {
	// Listen to gameUpdate
	socket.on("gameUpdate", (data: any) => {
		logEvent("gameUpdate", data, "received");

		// Update local game state
		if (data.currentPlayer !== undefined) gameState.currentPlayer = data.currentPlayer;
		if (data.currentMoveIndex !== undefined) gameState.currentMoveIndex = data.currentMoveIndex;
		if (data.capturedStones !== undefined) gameState.capturedStones = data.capturedStones;
		if (data.tgn !== undefined) gameState.tgn = data.tgn;
	});

	// Listen to gameReset
	socket.on("gameReset", (data: any) => {
		logEvent("gameReset", data, "received");

		// Reset local game state
		gameState.currentPlayer = data.currentPlayer;
		gameState.currentMoveIndex = 0;
		gameState.capturedStones = { black: 0, white: 0 };
		gameState.tgn = data.tgn || "";

		// Update board shape inputs
		if (data.boardShape) {
			boardShapeX.value = data.boardShape.x;
			boardShapeY.value = data.boardShape.y;
			boardShapeZ.value = data.boardShape.z;
		}

		// Update player list and colors if provided
		if (data.players) {
			roomPlayers.value = Object.keys(data.players);
			// Initialize player color assignments
			for (const [playerId, playerInfo] of Object.entries(data.players) as any) {
				playerColorAssignments[playerId] = playerInfo.color;
			}

			// Update current player's color display
			if (data.players[socket.id]) {
				playerColor.value = data.players[socket.id].color;
			}
		}
	});

	// Listen to gameEnded
	socket.on("gameEnded", (data: any) => {
		logEvent("gameEnded", data, "received");
		gameState.gameStatus = "finished";
	});

	// Listen to playerJoined
	socket.on("playerJoined", (data: any) => {
		logEvent("playerJoined", data, "received");

		// Add the new player to the room players list
		if (data.playerId && !roomPlayers.value.includes(data.playerId)) {
			roomPlayers.value.push(data.playerId);
			// Default the new player to white (second player)
			playerColorAssignments[data.playerId] = "white";
		}
	});

	// Listen to playerLeft
	socket.on("playerLeft", (data: any) => {
		logEvent("playerLeft", data, "received");
	});

	// Listen to nicknameChanged
	socket.on("nicknameChanged", (data: any) => {
		logEvent("nicknameChanged", data, "received");
	});

	// Listen to error events
	socket.on("error", (data: any) => {
		logEvent("error", data, "error");
	});
});

onUnmounted(() => {
	// Clean up listeners
	socket.off("gameUpdate");
	socket.off("gameReset");
	socket.off("gameEnded");
	socket.off("playerJoined");
	socket.off("playerLeft");
	socket.off("nicknameChanged");
	socket.off("error");
});
</script>

<style scoped>
.socket-test-view {
	max-width: 1200px;
	margin: 0 auto;
	padding: 20px;
	font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

.test-header {
	text-align: center;
	margin-bottom: 30px;
	padding-bottom: 20px;
	border-bottom: 2px solid #e0e0e0;
}

.test-header h1 {
	margin: 0 0 10px 0;
	font-size: 2em;
	color: #333;
}

.subtitle {
	margin: 0;
	color: #666;
	font-size: 1.1em;
}

.test-body {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 20px;
	overflow: auto;
	max-height: calc(100vh - 200px);
}

.left-column {
	display: flex;
	flex-direction: column;
	gap: 20px;
	overflow-y: auto;
}

.right-column {
	display: flex;
	flex-direction: column;
	min-height: 0;
}

.event-log-section {
	display: flex;
	flex-direction: column;
	height: 100%;
	min-height: 0;
}

.test-section {
	background: #f9f9f9;
	border: 1px solid #ddd;
	border-radius: 8px;
	padding: 20px;
}

.test-section h2 {
	margin: 0 0 15px 0;
	font-size: 1.5em;
	color: #333;
}

.section-desc {
	margin: -10px 0 15px 0;
	color: #666;
	font-size: 0.9em;
}

.admin-section {
	background: #fff8e1;
	border-color: #ffd54f;
}

/* Status */
.status-info,
.room-info,
.game-info {
	display: flex;
	flex-direction: column;
	gap: 10px;
	margin-bottom: 15px;
}

.status-item,
.info-item {
	display: flex;
	gap: 10px;
	align-items: center;
	padding: 8px;
	background: white;
	border-radius: 4px;
}

.status-item.ready {
	background: #e8f5e9;
}

.status-item.error {
	background: #ffebee;
}

.status-label,
.label {
	font-weight: 600;
	min-width: 120px;
}

.status-value,
.value {
	flex: 1;
}

.value.black {
	color: #000;
	font-weight: bold;
}

.value.white {
	color: #999;
	font-weight: bold;
}

.code {
	font-family: "Courier New", monospace;
	background: #f0f0f0;
	padding: 2px 6px;
	border-radius: 3px;
	font-size: 0.9em;
}

.error-message {
	padding: 10px;
	background: #ffebee;
	border: 1px solid #ef5350;
	border-radius: 4px;
	color: #c62828;
}

/* Controls */
.room-controls,
.game-controls {
	display: flex;
	flex-direction: column;
	gap: 10px;
}

.control-group,
.button-group {
	display: flex;
	gap: 10px;
	flex-wrap: wrap;
	align-items: center;
}

.reset-controls {
	display: flex;
	flex-direction: column;
	gap: 10px;
	margin-top: 10px;
}

.input-label {
	font-weight: 600;
	margin-right: 5px;
}

.input-text,
.input-number,
.input-select {
	padding: 8px 12px;
	border: 1px solid #ddd;
	border-radius: 4px;
	font-size: 1em;
	flex: 1;
	min-width: 150px;
}

.input-number {
	min-width: 80px;
	max-width: 100px;
}

.input-select {
	min-width: 200px;
	cursor: pointer;
	background: white;
}

.admin-warning {
	padding: 10px;
	background: #fff8e1;
	border: 1px solid #ffd54f;
	border-radius: 4px;
	color: #f57c00;
	font-weight: 500;
	margin-bottom: 10px;
}

.btn {
	padding: 10px 20px;
	border: none;
	border-radius: 4px;
	font-size: 1em;
	cursor: pointer;
	transition: background 0.2s;
	font-weight: 500;
}

.btn:disabled {
	opacity: 0.5;
	cursor: not-allowed;
}

.btn-primary {
	background: #2196f3;
	color: white;
}

.btn-primary:hover:not(:disabled) {
	background: #1976d2;
}

.btn-secondary {
	background: #757575;
	color: white;
}

.btn-secondary:hover:not(:disabled) {
	background: #616161;
}

.btn-warning {
	background: #ff9800;
	color: white;
}

.btn-warning:hover:not(:disabled) {
	background: #f57c00;
}

.btn-danger {
	background: #f44336;
	color: white;
}

.btn-danger:hover:not(:disabled) {
	background: #d32f2f;
}

.btn-admin {
	background: #9c27b0;
	color: white;
}

.btn-admin:hover:not(:disabled) {
	background: #7b1fa2;
}

.checkbox-label {
	display: flex;
	align-items: center;
	gap: 5px;
	cursor: pointer;
}

/* Event Log */
.event-log-controls {
	display: flex;
	gap: 10px;
	align-items: center;
	margin-bottom: 10px;
}

.event-log {
	flex: 1;
	overflow-y: auto;
	background: white;
	border: 1px solid #ddd;
	border-radius: 4px;
	padding: 10px;
	min-height: 0;
}

.empty-state {
	text-align: center;
	color: #999;
	padding: 20px;
}

/* TGN Display */
.tgn-display {
	margin-top: 15px;
}

.tgn-display h3 {
	margin: 0 0 10px 0;
	font-size: 1.1em;
	color: #333;
}

.tgn-content {
	background: white;
	border: 1px solid #ddd;
	border-radius: 4px;
	padding: 10px;
	margin: 0;
	font-family: "Courier New", monospace;
	font-size: 0.9em;
	overflow-x: auto;
	white-space: pre-wrap;
	word-wrap: break-word;
	max-height: 200px;
	overflow-y: auto;
}

.event-item {
	margin-bottom: 10px;
	padding: 10px;
	border-radius: 4px;
	border-left: 4px solid #2196f3;
	background: #f5f5f5;
}

.event-item.sent {
	border-left-color: #4caf50;
	background: #e8f5e9;
}

.event-item.error {
	border-left-color: #f44336;
	background: #ffebee;
}

.event-timestamp {
	font-size: 0.85em;
	color: #666;
	margin-right: 10px;
}

.event-name {
	font-weight: 600;
	margin-right: 10px;
}

.event-type-badge {
	display: inline-block;
	padding: 2px 8px;
	border-radius: 12px;
	font-size: 0.75em;
	font-weight: 600;
	text-transform: uppercase;
}

.event-item.sent .event-type-badge {
	background: #4caf50;
	color: white;
}

.event-item.received .event-type-badge {
	background: #2196f3;
	color: white;
}

.event-item.error .event-type-badge {
	background: #f44336;
	color: white;
}

.event-data {
	margin: 10px 0 0 0;
	padding: 10px;
	background: white;
	border: 1px solid #ddd;
	border-radius: 4px;
	font-size: 0.85em;
	overflow-x: auto;
	white-space: pre-wrap;
	word-wrap: break-word;
}
</style>
