using AutoMapper;
using Common.Dtos;
using Common.Dtos.Exper;
using Hushian.Application.Contracts.Persistence;
using Hushian.Application.Models;
using Common.Validation;
using Hushian.Domain.Entites;
using Microsoft.EntityFrameworkCore;

namespace Hushian.Application.Services
{
    public class ExperService
    {
        private readonly IGenericRepository<Company> _CompanyRepository;
        private readonly IGenericRepository<User> _UserRepository;
        private readonly IGenericRepository<Exper> _ExperRepository;
        private readonly VerificationService _VerificationService;
        private readonly IMapper _mapper;

        public ExperService(IGenericRepository<Exper> experRepository, VerificationService verificationService, IMapper mapper, IGenericRepository<Company> companyRepository, IGenericRepository<User> userRepository)
        {
            _ExperRepository = experRepository;
            _VerificationService = verificationService;
            _mapper = mapper;
            _CompanyRepository = companyRepository;
            _UserRepository = userRepository;
        }

        public async Task<ResponseBase<bool>> ADDExper(ADD_ExperDto dto, int CompanyID)
        {
            var Response = new ResponseBase<bool>();

            #region Validation
            bool validate = true;
            var errors = new List<string>();

            validate = dto.Password.CheckLawPassword(ref errors);

            #endregion

            if (validate)
            {
                try
                {
                    string UserName = $"E/{CompanyID.ToString("00")}/{_ExperRepository.Get().Count(c => c.CompanyID == CompanyID).ToString("0000")}";
                    Response.Success = Response.Value = await _ExperRepository.ADDBool(new Exper()
                    {
                        CompanyID = CompanyID,
                        FullName = dto.FullName,
                        Password = dto.Password.GetHash(),
                        UserName = UserName
                    });
                }
                catch (Exception ex)
                {
                    Response.Errors.Add("خطای سیستمی کد 01");
                }

            }
            else
            {
                Response.Errors.AddRange(errors);
            }

            return Response;
        }
        public async Task<Read_ExperDto?> GetInfoExper(int ExperID)
            => _mapper.Map<Read_ExperDto>(await _ExperRepository.Get().FirstOrDefaultAsync(w => w.ID == ExperID));
        public async Task<CurrentUserInfo?> GetCurrentUserInfo(int CompanyID, int? ExperID, int? UserID)
        {
            if (ExperID.HasValue)
            {
                return await _ExperRepository.Get().Where(w => w.ID == ExperID).Select(s => new CurrentUserInfo
                {
                    CompanyID = s.CompanyID,
                    ExperID = ExperID,
                    Username = s.UserName,
                    Role = "Exper"
                }).FirstOrDefaultAsync();
            }
            else if (UserID.HasValue)
            {
                return await _UserRepository.Get().Where(w => w.ID == UserID).Select(s => new CurrentUserInfo
                {
                    CompanyID = 0,
                    UserID = UserID,
                    Username = s.Mobile,
                    Role = "User"
                }).FirstOrDefaultAsync();
            }
            else
            {
                return await _CompanyRepository.Get().Where(w => w.ID == CompanyID).Select(s => new CurrentUserInfo
                {
                    CompanyID = CompanyID,
                    ExperID = null,
                    Username = s.Mobile,
                    Role = "Company"
                }).FirstOrDefaultAsync();
            }
        }

        public async Task<List<Read_ExperDto>> GetExpersInCompany(int companyID)
            => _mapper.Map<List<Read_ExperDto>>(await _ExperRepository.Get().Where(w => w.CompanyID == companyID).ToListAsync());
        public async Task<Read_ExperDto?> GetExpersInGroup(int GroupID)
            => _mapper.Map<Read_ExperDto>(await _ExperRepository.Get().Where(w => w.EG.Any(a => a.GroupID == GroupID)).ToListAsync());
        public async Task<bool> UpdateExper(Update_ExperDto model, int ExperID)
        {
            var exper = await _ExperRepository.Get().FirstOrDefaultAsync(w => w.ID == ExperID);
            exper.FullName = model.FullName;
            return await _ExperRepository.UPDATEBool(exper);
        }
        public async Task<bool> ChangeAvailableExper(int ExperID, int CompanyID, bool Available)
        {
            var exper = await _ExperRepository.Get().FirstOrDefaultAsync(w => w.ID == ExperID && w.CompanyID == CompanyID);
            if (exper == null) return false;
            exper.Available = Available;
            return await _ExperRepository.UPDATEBool(exper);
        }
        public async Task<bool> CheckExperInCompany(int CompanyID, int ExperID)
            => await _ExperRepository.Get().AnyAsync(w => w.ID == ExperID && w.CompanyID == CompanyID);
        public async Task<bool> DeleteExper(int ExperID, int CompanyID)
        {
            var exper = await _ExperRepository.Get().FirstOrDefaultAsync(w => w.ID == ExperID && w.CompanyID == CompanyID);
            if (exper == null) return false;
            return await _ExperRepository.DELETE(exper);
        }
        public async Task<ResponseBase<bool>> ChangePasswordExperFromExper(ChangePasswordDto model, int ExperID)
        {
            ResponseBase<bool> Response = new();

            var exper = await _ExperRepository.Get().FirstOrDefaultAsync(f => f.ID == ExperID);
            if (string.IsNullOrEmpty(model.OldPassWord) || model.OldPassWord.GetHash() != exper.Password)
            {
                Response.Errors.Add("کلمه عبور فعلی صحیح نمی باشد");
            }
            else
            {
                exper.Password = model.NewPassWord.GetHash();
                Response.Value = await _ExperRepository.UPDATEBool(exper);
                if (!Response.Value) Response.Errors.Add("خطا در ذخیره سازی");
                else Response.Success = true;

            }
            return Response;
        }
        public async Task<ResponseBase<bool>> ChangePasswordExperFromCompanyManaget(ChangePasswordDto model, int ExperID, int CompanyID)
        {
            ResponseBase<bool> Response = new();
            var exper = await _ExperRepository.Get().FirstOrDefaultAsync(f => f.ID == ExperID);

            if (exper.CompanyID == CompanyID)
            {
                exper.Password = model.NewPassWord.GetHash();
                Response.Value = await _ExperRepository.UPDATEBool(exper);
                if (!Response.Value) Response.Errors.Add("خطا در ذخیره سازی");
                else Response.Success = true;
            }
            else
            {
                Response.Errors.Add("کاربری یافت نشد");
            }



            return Response;
        }
        public async Task<ResponseBase<int>> ForgetPasswordExper(string UserName)
        {
            ResponseBase<int> Response = new();

            var company = await _ExperRepository.Get().FirstOrDefaultAsync(f => f.UserName == UserName);
            if (company == null)
            {
                Response.Errors.Add("کاربری یافت نشد");
            }
            else
            {
                Response.Value = await _VerificationService.GenerateCodeByForgetPassword(UserName);
                Response.Success = true;
            }
            return Response;
        }
        public async Task<int> GetCompanyIDExper(int ExperID)
        {
            var exper = await _ExperRepository.Get().FirstOrDefaultAsync(w => w.ID == ExperID);
            if (exper == null) return 0;
            return exper.CompanyID;
        }
        public async Task<bool> AvailableExperInCompany(int ExperID)
        {
            return await _ExperRepository.Get().AnyAsync(w => w.ID == ExperID && w.Available);

        }
    }
}
