import { HttpException, HttpStatus, Injectable, Res } from '@nestjs/common';
import { User } from 'src/users/entities/user.entity';
import { UsersService } from 'src/users/users.service';
import { Chatroom } from './entities/chatroom.entity';
import { Repository } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import { createRoomDto } from './dto/createRoom.dto';
import { joinRoomDto } from './dto/joinRoom.dto';
import { messagesDto } from './dto/messages.dto';

@Injectable()
export class ChatService {

	constructor(
		private usersService: UsersService,
		@InjectRepository(User)
		private readonly userRepository: Repository<User>,
		@InjectRepository(Chatroom)
		private readonly chatroomRepository: Repository<Chatroom>,
	) { }


	// temp for test
	sleep(ms) {
		return new Promise(resolve => setTimeout(resolve, ms));
	}


	/* GETTERS ************************************************
	*/

	async getMyRooms(username: string)
	{
		console.log("-- in getMyRooms service");
		const rooms = await this.chatroomRepository
			.createQueryBuilder('chatroom')
			.where('chatroom.users LIKE :user_name', { user_name: `%${username}%` })
			.getMany();

		console.log("-- out getMyRooms service");
		return rooms;
	}

	async getAllRooms()
	{
		console.log("-- in getAllRooms service");
		const rooms = await this.chatroomRepository
			.createQueryBuilder('chatroom')
			.getMany();

		console.log("-- out getAllRooms service");
		return rooms;
	}

	async getAllNotMyRooms(username: string)
	{
		console.log("-- in getAllNotMyRooms service");
		const user_db = await this.getUserByName(username);
		//const user_db = await this.usersService.findOne(username);
		const rooms = await this.chatroomRepository
			.createQueryBuilder('chatroom')
			.where('chatroom.type != :type', { type: 'private' })
			.andWhere('chatroom.users NOT LIKE :user_name', { user_name: `%${username}%` })
			.getMany();
		//const users = await this.getAllUsers();
		//let allRooms = [...rooms, ...users];

		console.log("-- out getAllNotMyRooms service");
		return rooms;
	}

	async getMessagesFromCurrentRoom(username: string)
	{
		console.log("-- in getMessagesFromCurrentRoom service");
		const user_db = await this.getUserByName(username);
		//const user_db = await this.usersService.findOne(username);
		const currentRoom = await this.getRoomByName(user_db.currentRoom);

		console.log("-- out getMessagesFromCurrentRoom service");
		return currentRoom.messages;
	}

	async getCurrentRoomName(username: string)
	{
		console.log("-- in getCurrentRoomName service");
		console.log('username:', username);
		const user_db = await this.getUserByName(username);
		//const user_db = await this.usersService.findOne(username);

		console.log("-- out getCurrentRoomName service");
		return user_db.currentRoom;
	}

	async getRoomByName(room_name: string)
	{
		console.log("-- in getRoomByName service");
		const room = await this.chatroomRepository
			.createQueryBuilder('chatroom')
			.where('chatroom.name = :name', { name: room_name })
			.getOne();

		console.log("-- out getRoomByName service");
		return room;
	}

	async getRoomById(id: number)
	{
		console.log("-- in getRoomById service");
		const room = await this.chatroomRepository
			.createQueryBuilder('chatroom')
			.where('chatroom.id = :id', { id: id })
			.getOne();

		console.log("-- out getRoomById service");
		return room;
	}


	/* SETTERS ************************************************
	*/

	async setCurrentRoom(username: string, room_name: string)
	{
		console.log("-- in setCurrentRoom service");
		const user_db = await this.getUserByName(username);
		//const user_db = await this.usersService.findOne(username);
		user_db.currentRoom = room_name;
		this.userRepository.save(user_db);
		
		console.log("-- out setCurrentRoom service");
		return `room "${room_name}" is now current room`;
	}


	/* ADDERS *************************************************
	*/

	async addUserToNewRoom(username: string, createRoomDto: createRoomDto)
	{
		console.log("-- in addUserToNewRoom service");
		const room = await this.getRoomByName(createRoomDto.room_name);
		if (room)
			throw new HttpException(`This room already exist`, HttpStatus.CONFLICT);

		// create chatroom
		const newChatroom = new Chatroom();
		newChatroom.name = createRoomDto.room_name;
		newChatroom.type = createRoomDto.room_type;
		newChatroom.owner = username;
		newChatroom.users = [username];
		newChatroom.messages = [{ name: "SERVER", message: `creation of room ${createRoomDto.room_name}` }];
		this.chatroomRepository.save(newChatroom);

		console.log("-- out addUserToNewRoom service");
		return "successfull room creation";
	}

	async addUserToRoom(username: string, room_name: string)
	{
		console.log("-- in addUserToRoom service");
		const room = await this.getRoomByName(room_name);
		if (room.users.includes(username))
			throw new HttpException(`your have already join this room`, HttpStatus.CONFLICT);

		// update room with new user
		room.users.push(username);
		this.chatroomRepository.save(room);

		await this.setCurrentRoom(username, room_name);

		console.log("-- out addUserToRoom service");
		return "successfully joining room";
	}

	async addMessageToRoom(room_name: string, username: string, message: string)
	{
		console.log("-- in addMessageToRoom service");
		//const user_db = await this.getUserByName(username);
		//const user_db = await this.usersService.findOne(username);
		//console.log("user_db:", user_db);
		const currentRoom = await this.getRoomByName(room_name);
		let chat_message = {
			name: username,
			message: message,
		};
		currentRoom.messages.push(chat_message);
		this.chatroomRepository.save(currentRoom);

		console.log("-- out addMessageToRoom service");
	}


	/* REMOVERS ***********************************************
	*/

	async removeUserFromRoom(username: string, room_name: string)
	{
		console.log("-- in removeUserFromRoom service");
		const room = await this.getRoomByName(room_name);
		if (!room.users.includes(username))
			throw new HttpException(`your are not in this room`, HttpStatus.CONFLICT);

		// delete user from room
		room.users.push(username);
		room.users = room.users.filter(name => name !== username);
		this.chatroomRepository.save(room);

		// set current room to nothing
		await this.setCurrentRoom(username, "");

		console.log("-- out removeUserFromRoom service");
		return "successfully leaving room";
	}


	/* SEARCH IN USER *****************************************
	*/

	async getUserByName(username: string)
	{
		console.log("-- in getUserByName service");
		const user = await this.userRepository
			.createQueryBuilder('user')
			.where('user.username = :name', { name: username })
			.getOne();

		console.log("-- out getUserByName service");
		return user;
	}

}

