//using BCryptNet = BCrypt.Net.BCrypt;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;

using Microsoft.EntityFrameworkCore;
using FamilyTreeAPI.Interface;
using FamilyTreeAPI.Entities;

using System;
using FamilyTreeAPI.Models;
using Microsoft.AspNetCore.Http;
using System.Text.Json;


namespace FamilyTreeAPI.Repository;
public class UserServiceRepository : IUserService
{
    private FamilyTreeDBContext _context;
    private IJwtUtils _jwtUtils;
    private readonly IHttpContextAccessor _httpcontext;
    private readonly AppSettings _appSettings;

    public UserServiceRepository(
        FamilyTreeDBContext context,
        IJwtUtils jwtUtils,
         IHttpContextAccessor httpcontext,
        IOptions<AppSettings> appSettings)
    {
        _context = context;
        _jwtUtils = jwtUtils;
        _appSettings = appSettings.Value;
        this._httpcontext = httpcontext;

    }
    public Task<ResultModel<int>> Logout(string token, UserDto user, string remoteIpAddress)
    {
        /*
        int retval = 1;
        int statuscode = 1;
        string str255 = token;
        var histo = await _context.AdminLoginHistories.Where(x => x.UserId == user.Id
        && x.RecordIntegrity == token
        && x.LoginTyped == user.Username).ToListAsync();
        if (histo.Count > 0)
        {
            histo[0].LogoutDatetime = DateTime.Now;
            await _context.SaveChangesAsync();
        }
        */
        var result = new ResultModel<int>()
        {
            Data = 1,
            StatusCode = 1
        };

        return Task.FromResult(result); 
        
    }
    private bool checkLogin(staff user, string email, string password)
    {
        bool result = false;
      //  string dpassword = Ultils.Base64Encode(password);
        result = user.Spassword == password;
        return result;
    }
    public async Task<ResultModel<AuthenticateResponse>> Login(AuthenticateRequest model)
    {
        UserDto myUser = new();
        AuthenticateResponse retval = null;
        string error = "user name is not in DB or user Name profile is not generic";
        int statuscode = 0;
       
        try
        {
            //now check the adminuser table
            myUser.Username = model.Username;
            var user = _context.staff.
                              SingleOrDefault(x => x.Email == model.Username
                               && true == x.Sactive);
            if (user != null)
            {
                bool loginOK = checkLogin(user, model.Username, model.Password);
                if (loginOK)
                {
                   

                    //  myUser.Role = user.RoleType;
                    myUser.Id = user.Id;
                    myUser.Role = user.Srole ?? 0;
                    myUser.Email = user.Email;
                    myUser.Phone = user.Phone;
                    myUser.FirstName = user.Firstname;
                    myUser.LastName = user.Lastname;
                    //myUser.ValidationPointId = user.ValidationPointID ?? 0;
                    statuscode = 1;
                }
                else //not allow
                {
                    statuscode = -1;
                    myUser.Role = 1;
                    myUser.Id = -1;

                    error = "user name cannot login email or password";
                }
                // validate
                //  if (user == null || !BCryptNet.Verify(model.Password, user.PasswordHash))

                // authentication successful so generate jwt token
                if (statuscode == 1)
                {
                    var jwtToken = _jwtUtils.GenerateJwtToken(myUser);
                    retval = new AuthenticateResponse(myUser, jwtToken, myUser.Role);
                    error = "";
                }
            }
            else
            {
                error = "user name or password is not correct";
            }


        }
        catch (Exception ex)
        {
            retval = null;
            error = ex.ToString();
            statuscode = -1;
          
        }
        //writelog for login user.
        // if (myUser != null)
        //   await AddToSession(myUser);
        return new ResultModel<AuthenticateResponse>()
        {
            Data = retval,
            StatusCode = statuscode,
            Message = error
        };

    }
    public async Task<ResultModel<AuthenticateResponse>> LoginApiAD(AuthenticateRequest model, string remoteIpAddress)
    {
        UserDto myUser = new();
        AuthenticateResponse retval = null;
        string error = "user name is not in DB or user Name profile is not generic";
        int statuscode = 0;
        string webAPIUrl = _appSettings.LoginWebAPI;
        //KCO, D204KCO
        //now check the adminuser table
        //ward clerk
        try
        {
            //now check the adminuser table
            myUser.Username = model.Username;
            var user = _context.staff.
                              SingleOrDefault(x => x.Email == model.Username
                               && true == x.Sactive);
            if (user != null)
            {
                bool loginOK = checkLogin(user,model.Username, model.Password);
            if (loginOK)
            {
                    //  myUser.Role = user.RoleType;
                    myUser.Id = user.Id;
                    myUser.Role = user.Srole ?? 0;
                    myUser.Email = user.Email;
                    myUser.Phone = user.Phone;
                    myUser.FirstName = user.Firstname;
                    myUser.LastName = user.Lastname;
                    
                    //myUser.ValidationPointId = user.ValidationPointID ?? 0;
                    statuscode = 1;
                }
                else // allow
                {
                    statuscode = 1;
                    myUser.Role = 1;
                    myUser.Id = -1;
                   
                    //error = "user name does not exist in adminUser";
                }
                // validate
                //  if (user == null || !BCryptNet.Verify(model.Password, user.PasswordHash))

                // authentication successful so generate jwt token
                if (statuscode == 1)
                {
                    var jwtToken = _jwtUtils.GenerateJwtToken(myUser);
                    retval = new AuthenticateResponse(myUser, jwtToken, myUser.Role);
                    error = "";
                }
            }
            else
            {
                error = "user name or password is not correct";
            }


        }
        catch (Exception ex)
        {
            retval = null;
            error = ex.ToString();
            statuscode = -1;
            
        }
        //writelog for login user.
       // if (myUser != null)
        //   await AddToSession(myUser);
        return new ResultModel<AuthenticateResponse>()
        {
            Data = retval,
            StatusCode = statuscode,
            Message = error
        };
        
    }
    //get like this
    private async Task GetCurrentUser()
    {
        await _httpcontext.HttpContext.Session.LoadAsync();

        string userString = _httpcontext.HttpContext.Session.GetString("user");

        if (userString != null && userString != "")
        {
            var user = JsonSerializer.Deserialize<UserDto>(userString);
            if (user != null)
            {
               // return user;
            }
        }
    }
    

   /*
    private User LoginADStaff(ADConfig adConfig, string username, string password)
    {

        ADStaffLink staffLink = new ADStaffLink(adConfig);
        MyADObject myADObj = staffLink.CheckADCredentials(username,password);
        User user = new()
        {
            Username = myADObj.StafflinkNo,
            Email = myADObj.Email,
            FirstName = myADObj.FirstName,
            LastName = myADObj.LastName
        };
        // myADObj.JobTitle;
        return user;

        // return null;
    }
    */
}
