using Common.Constant;
using Common.Logic;
using Database.Database;
using log4net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using SicboSub.Api.DTO;
using SicboSub.Api.Singleton;

namespace SicboSub.Api.Business
{
    /// <summary>
    /// Business logic cho Authentication
    /// Xử lý đăng nhập website qua URL token
    /// </summary>
    public interface IAuthBusiness
    {
        /// <summary>
        /// Đăng nhập bằng token từ URL
        /// Website gọi API này khi user truy cập qua URL có ?token=xxx
        /// </summary>
        Task<IActionResult> LoginByToken(HttpRequest httpRequest, TokenLoginReq request);

        /// <summary>
        /// Lấy MSISDN từ token (API nhẹ)
        /// </summary>
        Task<IActionResult> GetMsisdnFromToken(HttpRequest httpRequest, GetMsisdnFromTokenReq request);
    }

    public class AuthBusinessImpl : IAuthBusiness
    {
        private static readonly ILog log = LogManager.GetLogger(typeof(AuthBusinessImpl));

        private readonly ModelContext dbContext;
        private readonly IAuthService authService;
        private readonly IConfiguration configuration;
        string wsUser;
        string wsPass;
        string packageDaily;
        public AuthBusinessImpl(ModelContext _dbContext, IAuthService _authService, IConfiguration _configuration)
        {
            dbContext = _dbContext;
            authService = _authService;
            configuration = _configuration;
            wsUser = GetParameter("wsUser");
            wsPass = GetParameter("wsPass");
            packageDaily = GetParameter("PackageCodeDaily");
        }
        private string GetParameter(string key)
        {
            return configuration.GetSection(key).Value ?? "";
        }
        /// <summary>
        /// Đăng nhập bằng token từ URL
        /// Flow: 
        ///   1. User truy cập website qua URL: https://domain.com?token=abc123
        ///   2. Frontend lấy token từ URL và gọi API này
        ///   3. API xác thực token và trả về thông tin user
        ///   4. Frontend lưu token vào localStorage để dùng cho các request sau
        /// </summary>
        public async Task<IActionResult> LoginByToken(HttpRequest httpRequest, TokenLoginReq request)
        {
            var url = httpRequest.Path;
            var json = JsonConvert.SerializeObject(new { token = "***" }); // Ẩn token trong log
            log.Debug("URL: " + url + " => Request: LoginByToken");

            try
            {
                string lang = CommonLogic.GetLanguage(httpRequest, request.lang);

                // 1. Validate request
                if (string.IsNullOrEmpty(request.token))
                {
                    return DotnetLib.Http.HttpResponse.BuildResponse(
                        log, url, json,
                        CommonErrorCode.InvalidParameter,
                        ConfigManager.Instance.GetConfigWebValue("TOKEN_REQUIRED", lang),
                        new { }
                    );
                }

                // 2. Validate token và lấy thông tin user
                var validationResult = await authService.ValidateTokenWithDetails(request.token);

                if (!validationResult.IsValid)
                {
                    return DotnetLib.Http.HttpResponse.BuildResponse(
                        log, url, json,
                        validationResult.ErrorCode ?? CommonErrorCode.TokenInvalid,
                        ConfigManager.Instance.GetConfigWebValue("TOKEN_INVALID", lang),
                        new { }
                    );
                }

                var user = validationResult.User!;

                // 3. Update last login time
                var userToUpdate = await dbContext.AccountUsers
                    .FirstOrDefaultAsync(u => u.Id == user.Id);
                
                if (userToUpdate != null)
                {
                    userToUpdate.LastLogin = DateTime.Now;
                    await dbContext.SaveChangesAsync();
                }

                log.Info($"LoginByToken success: MSISDN={user.Msisdn}");

                // 4. Check Registration Status
                bool isRegistered = false;
                RegInfoDto? regPkg = null;
                
                string productCode = packageDaily;
                ; // Default
                // Try to get from config if available (assuming ConfigManager has it, or just use default)
                // var cfgCode = ConfigManager.Instance.GetConfigWebValue("PackageCodeDaily");
                // if(!string.IsNullOrEmpty(cfgCode)) productCode = cfgCode;

                var regInfo = await dbContext.RegInfos
                    .Where(r => r.Msisdn == user.Msisdn 
                             && r.ProductName == productCode
                             && r.Renew == 1 
                             && r.Status == 1 
                             && r.ExpireTime > DateTime.Now)
                    .OrderByDescending(r => r.RegisterTime)
                    .FirstOrDefaultAsync();

                if (regInfo != null)
                {
                    isRegistered = true;
                    regPkg = new RegInfoDto
                    {
                        RegisterId = regInfo.RegisterId,
                        Msisdn = regInfo.Msisdn,
                        ProductName = regInfo.ProductName,
                        RegisterTime = regInfo.RegisterTime,
                        NumberSpin = regInfo.NumberSpin,
                        Status = regInfo.Status,
                        ExpireTime = regInfo.ExpireTime,
                        Renew = regInfo.Renew
                    };
                }

                // 5. Return user info
                return DotnetLib.Http.HttpResponse.BuildResponse(
                    log, url, json,
                    CommonErrorCode.Success,
                    ConfigManager.Instance.GetConfigWebValue("LOGIN_SUCCESS", lang),
                    new TokenLoginRes
                    {
                        id = user.Id,
                        msisdn = user.Msisdn,
                        username = user.Username,
                        fullname = user.Fullname,
                        picture = user.Picture,
                        winCoin = user.WinCoin,
                        betCoin = user.BetCoin,
                        point = user.Point,
                        freeSpin = user.FreeSpin,
                        status = user.Status,
                        lastLogin = DateTime.Now,
                        isRegistered = isRegistered,
                        regPkg = regPkg
                    }
                );
            }
            catch (Exception ex)
            {
                log.Error("LoginByToken exception: ", ex);
            }

            return DotnetLib.Http.HttpResponse.BuildResponse(
                log, url, json,
                CommonErrorCode.SystemError,
                ConfigManager.Instance.GetConfigWebValue("SYSTEM_FAILURE"),
                new { }
            );
        }

        /// <summary>
        /// Lấy MSISDN từ token (API nhẹ cho các tác vụ đơn giản)
        /// </summary>
        public async Task<IActionResult> GetMsisdnFromToken(HttpRequest httpRequest, GetMsisdnFromTokenReq request)
        {
            var url = httpRequest.Path;
            var json = JsonConvert.SerializeObject(new { token = "***" });
            log.Debug("URL: " + url + " => Request: GetMsisdnFromToken");

            try
            {
                if (string.IsNullOrEmpty(request.token))
                {
                    return DotnetLib.Http.HttpResponse.BuildResponse(
                        log, url, json,
                        CommonErrorCode.InvalidParameter,
                        "Token is required",
                        new GetMsisdnFromTokenRes { isValid = false }
                    );
                }

                var msisdn = await authService.GetMsisdnFromToken(request.token);

                if (string.IsNullOrEmpty(msisdn))
                {
                    return DotnetLib.Http.HttpResponse.BuildResponse(
                        log, url, json,
                        CommonErrorCode.TokenInvalid,
                        "Token invalid",
                        new GetMsisdnFromTokenRes { isValid = false }
                    );
                }

                return DotnetLib.Http.HttpResponse.BuildResponse(
                    log, url, json,
                    CommonErrorCode.Success,
                    "Success",
                    new GetMsisdnFromTokenRes 
                    { 
                        msisdn = msisdn,
                        isValid = true 
                    }
                );
            }
            catch (Exception ex)
            {
                log.Error("GetMsisdnFromToken exception: ", ex);
            }

            return DotnetLib.Http.HttpResponse.BuildResponse(
                log, url, json,
                CommonErrorCode.SystemError,
                "System error",
                new GetMsisdnFromTokenRes { isValid = false }
            );
        }
    }
}
