using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AyCode.Database.DataLayers;
using AyCode.Database.DataLayers.Users;
using AyCode.Database.DbSets.Users;
using AyCode.Entities.Users;
using Microsoft.EntityFrameworkCore;
using TIAM.Database.DbContexts.Users;
using TIAM.Database.DbSets.Users;
using TIAM.Entities.Addresses;
using TIAM.Entities.Profiles;
using TIAM.Entities.ServiceProviders;
using TIAM.Entities.Users;
using TIAM.Models.Dtos.Users;

namespace TIAM.Database.DataLayers.Users
{
    public class UserDal : AcUserDalBase<UserDbContext, User, Profile, UserToken, TiamServiceProvider, UserToServiceProvider, Address>
    {
        
        public UserDal() : base()
        {
        }

        public UserDal(UserDbContext _object)
        {
        }

        public UserModelDto? GetUserModelDtoById(Guid userId) => Session(x => x.GetUserModelDtoById(userId));
        public Task<UserModelDto?> GetUserModelDtoByIdAsync(Guid userId) => SessionAsync(x => x.GetUserModelDtoById(userId));
        public Task<UserModelDto?> GetUserModelDtoByEmailAsync(string email) => SessionAsync(x => x.GetUserModelDtoByEmail(email));
        public Task<List<UserModelDto>> GetAllUsersModelDtoAsync() => SessionAsync(x => x.GetAllUsersModelDto().ToList());

        public Task<User?> GetUserByPhoneNumberAsync(string phoneNumber)
        {
            Console.WriteLine($"Getting user from db {phoneNumber}");
            var phoneNumberLower = phoneNumber.ToLower();
            return Context.Users.SingleOrDefaultAsync(x=>x.PhoneNumber.Equals(phoneNumberLower, StringComparison.CurrentCultureIgnoreCase));
        }

        public Task<User?> GetUserByEmailOrPhoneNumberAsync(string emailOrPhoneNumber)
        {
            Console.WriteLine($"Getting user from db {emailOrPhoneNumber}");
            var emailOrPhoneNumberLower = emailOrPhoneNumber.ToLower();
            return Context.Users.SingleOrDefaultAsync(x=>x.EmailAddress.Equals(emailOrPhoneNumberLower, StringComparison.CurrentCultureIgnoreCase) || x.PhoneNumber.Equals(emailOrPhoneNumberLower, StringComparison.CurrentCultureIgnoreCase));
        }

        ////get user by Id
        //public Task<User?> GetUserByIdAsync(Guid id)
        //{
        //    Console.WriteLine($"Getting user from db {id}");
        //    return Context.Users.SingleOrDefaultAsync(x=>x.Id == id);
        //}

        public async Task<bool> CreateUserAsync(User user)
        {
            Context.Users.Add(user);
            Console.WriteLine($"Saving user to db {user.Id}, {user.EmailAddress}, {user.PhoneNumber}, {user.Password}");
            return await Context.SaveChangesAsync() > 0;
        }


        public async Task<bool> UpdateJwtRefreshTokenAsync(string email, string refreshToken)
        {
            Console.WriteLine("UserDal Update refresh token");
            var existingUser = Context.Users.FirstOrDefault(u => u.EmailAddress == email);
            if (existingUser != null)
            {
                //user.Modified = DateTime.UtcNow; //ezt nem kell megadni, a háttérben ezt magától megcsinálja a DbContextBase - J.
                existingUser.RefreshToken = refreshToken;

                Context.Users.Update(existingUser);
                return await Context.SaveChangesAsync() > 0;
            }
            else
            {
                throw new Exception("User not found");
            }
        }

        public async Task<bool> UpdateUserAsync(User user)
        {
            var existingUser = await Context.Users.CountAsync(u => u.EmailAddress == user.EmailAddress);
            if (existingUser == 1)
            {
                //user.Modified = DateTime.UtcNow; //ezt nem kell megadni, a háttérben ezt magától megcsinálja a DbContextBase - J.
                Context.Users.Update(user);
                return await Context.SaveChangesAsync() > 0;
            }
            else
            {
                throw new Exception("User not found");
            }
        }
    }
}
