using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using MongoDB.Driver;
using Unity.UOS.Func.Stateless.Core.Attributes;
using UnityEngine;
using UOS.FuncStateless.MongoDB;

namespace CloudService
{

    public class LoginResult
    {
        public bool Ok { get; set; }
        public string Message { get; set; }
        public User User { get; set; }
    }

    public class User
    {
        public string Id { get; set; }
        public string Username { get; set; }
        public string Nickname { get; set; }
        public string Password { get; set; }
        public int Diamonds { get; set; }
        public int Coins { get; set; }
        public int LuckPoints { get; set; }
        public int DrawCounts { get; set; }
        public List<Item> DrawPool { get; set; }
        public Dictionary<string, Item> Heroes { get; set; }
        public Dictionary<string, Item> Props { get; set; }
    }

    [CloudService]
    public class LoginService
    {
        [CloudFunc]
        public async Task<LoginResult> Login(string username, string password)
        {
            var conn = await MongoConnectionManager.GetConnection();
            var database = conn.GetDatabase(MongoConfig.DBName);
            var collection = database.GetCollection<User>(MongoConfig.CollectionName);
            Debug.Log($"username={username}, password={password}");
            if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
            {
                return new LoginResult
                {
                    Ok = false,
                    Message = "cannot found username or password"
                };
            }

            var filter = Builders<User>.Filter.Eq(u => u.Username, username);
            var projection = Builders<User>.Projection
                .Include("_id")
                .Include(u => u.Nickname)
                .Include(u => u.Password)
                .Include(u => u.Diamonds)
                .Include(u => u.Coins);
            var userDocument = await collection.Find(filter).Project(projection).FirstOrDefaultAsync();
            if (userDocument != null)
            {
                if (password == userDocument["Password"].AsString)
                    return new LoginResult
                    {
                        Ok = true,
                        User = new User
                        {
                            Id = userDocument["_id"].ToString(),
                            Nickname = userDocument["Nickname"].AsString,
                            Diamonds = userDocument["Diamonds"].AsInt32,
                            Coins = userDocument["Coins"].AsInt32
                        }
                    };
                Debug.Log("username or password is not correct");
                return new LoginResult
                {
                    Ok = false,
                    Message = "username or password is not correct"
                };

            }

            // not found, initialize an account, and return nickname, id
            // init user info, inventory, pool
            var newUser = new User
            {
                Id = Guid.NewGuid().ToString(),
                Username = username,
                Nickname = username + Helper.GetRandomEmoji(),
                Password = password,
                Diamonds = 500,
                Coins = 0,
                LuckPoints = 0,
                DrawCounts = 0,
                DrawPool = Helper.NewDrawPool(),
                Heroes = new Dictionary<string, Item>(),
                Props = new Dictionary<string, Item>(),
            };

            await collection.InsertOneAsync(newUser);
            return new LoginResult
            {
                Ok = true,
                User = new User
                {
                    Id = newUser.Id,
                    Nickname = newUser.Nickname,
                    Diamonds = newUser.Diamonds,
                    Coins = newUser.Coins
                }
            };
        }
    }
}
