using Common.Constant;
using log4net;
using Microsoft.AspNetCore.Mvc;
using SicboSub.Web.Helpers;
using SicboSub.Web.Models;
using System.Configuration;
using System.Diagnostics;

namespace SicboSub.Web.Controllers
{
    public class HomeController : BaseController
    {
        private static readonly ILog log = LogManager.GetLogger(typeof(HomeController));
        private readonly ILogger<HomeController> _logger;
        private readonly IConfiguration _configuration;

        public HomeController(ILogger<HomeController> logger, IConfiguration configuration)
        {
            _logger = logger;
            _configuration = configuration;
        }
        public String GetParameter(String key)
        {
            return _configuration.GetSection(key).Value ?? "";
        }
        /// <summary>
        /// Lấy config value
        /// </summary>
        /// <summary>
        /// Trang chủ - Yêu cầu Token để truy cập
        /// Nếu chưa login và không có token URL -> Redirect về trang chủ Sicbo (RedirectUrl)
        /// Nếu có token -> Login -> Success: load trang, Fail: Redirect
        /// </summary>
        /// <summary>
        /// Helper to load exchange config server-side
        /// </summary>
        private async Task<List<ExchangeConfigItem>> LoadExchangeConfigInternal()
        {
            try
            {
                string token = GetToken();
                var request = new ExchangeConfigReq
                {
                    lang = GetLanguage()
                };
                var url = GetParameter("Url") + ApiUrlConstant.ExchangeConfigLoadUrl;
                var resData = await DotnetLib.Rest.RestHandler.SendPostWithAuthen(
                    log,
                    url,
                    request,
                    token,
                    token,
                    "",
                    GetLanguage()
                );

                if (resData != null)
                {
                    ExchangeConfigRes response = new ExchangeConfigRes(resData.data);
                    if (response.errorCode == CommonErrorCode.Success && response.data != null)
                    {
                        return response.data;
                    }
                }
            }
            catch (Exception ex)
            {
                log.Error("LoadExchangeConfigInternal: Exception", ex);
            }
            return new List<ExchangeConfigItem>();
        }

        /// <summary>
        /// Helper to load packages server-side
        /// </summary>
        private async Task<List<PackageInfo>> LoadPackagesInternal()
        {
            try
            {
                string token = GetToken();

                var request = new PackageLoadReq
                {
                    lang = GetLanguage(),
                    pageNumber = 0,
                    pageSize = 100
                };
                var url = GetParameter("Url") + ApiUrlConstant.PackageLoadUrl;
                var resData = await DotnetLib.Rest.RestHandler.SendPostWithAuthen(
                    log,
                    url,
                    request,
                    token,
                    token,
                    "",
                    GetLanguage()
                );

                if (resData != null)
                {
                    PackageLoadRes response = new PackageLoadRes(resData.data);
                    if (response.errorCode == CommonErrorCode.Success && response.data != null)
                    {
                        return response.data
                            .Where(p => !string.IsNullOrEmpty(p.productName) && p.productName.StartsWith("CHARGE"))
                            .OrderBy(p => p.fee)
                            .ToList();
                    }
                }
            }
            catch (Exception ex)
            {
                log.Error("LoadPackagesInternal: Exception", ex);
            }
            return new List<PackageInfo>();
        }

        /// <summary>
        /// Helper to reload account info (refresh session data)
        /// </summary>
        private async Task ReloadAccountInfo()
        {
            try 
            {
                var token = GetToken();
                if (!string.IsNullOrEmpty(token))
                {
                   var request = new AccountInfoReq
                    {
                        msisdn = GetMsisdn(),
                        lang = GetLanguage()
                    };
                    var url = GetParameter("Url") + ApiUrlConstant.UserInfoUrl;
                    // Gọi API xác thực/lấy thông tin
                    var resData = await DotnetLib.Rest.RestHandler.SendPostWithAuthen(
                        log,
                        url,
                        request,
                        token,
                        token,
                        "",
                        GetLanguage()
                    );
                    
                    if (resData != null)
                    {
                        AccountInfoRes response = new AccountInfoRes(resData.data);
                        if (response.errorCode == CommonErrorCode.Success && response.data != null)
                        {
                            // Update Session
                            HttpContext.Session.SetComplexData("winCoin", response.data.winCoin);
                            HttpContext.Session.SetComplexData("betCoin", response.data.betCoin);
                            
                            var currentUser = HttpContext.Session.GetComplexData<TokenLoginData>("userInfo");
                            if(currentUser != null) {
                                currentUser.winCoin = response.data.winCoin;
                                currentUser.betCoin = response.data.betCoin;
                                currentUser.isRegistered = response.data.isRegistered;
                                if(response.data.regPkg != null) {
                                    currentUser.regPkg = new RegInfoData {
                                        RegisterId = response.data.regPkg.RegisterId,
                                        Msisdn = response.data.regPkg.Msisdn,
                                        ProductName = response.data.regPkg.ProductName,
                                        RegisterTime = response.data.regPkg.RegisterTime,
                                        NumberSpin = response.data.regPkg.NumberSpin,
                                        Status = response.data.regPkg.Status,
                                        ExpireTime = response.data.regPkg.ExpireTime,
                                        Renew = response.data.regPkg.Renew
                                    };
                                } else {
                                    currentUser.regPkg = null;
                                }
                                HttpContext.Session.SetComplexData("userInfo", currentUser);
                            }

                            HttpContext.Session.SetComplexData("isRegistered", response.data.isRegistered);
                        }
                    }
                }
            }
            catch(Exception ex)
            {
                log.Error("ReloadAccountInfo: Error", ex);
            }
        }

        public async Task<IActionResult> Index()
        {
            // 1. Kiểm tra nếu đã đăng nhập từ trước
            if (IsAuthenticated())
            {
                // Refresh account info as requested
                await ReloadAccountInfo();

                // Setup ViewData và hiển thị
                ViewData["IsAuthenticated"] = true;
                ViewData["Msisdn"] = GetMsisdn();
                ViewData["WinCoin"] = HttpContext.Session.GetComplexData<decimal?>("winCoin") ?? 0;
                ViewData["BetCoin"] = HttpContext.Session.GetComplexData<decimal?>("betCoin") ?? 0;
                
                // Load packages server-side
                var packages = await LoadPackagesInternal();
                HttpContext.Session.SetComplexData("Packages", packages); // Store in session as requested
                
                // Load exchange config server-side
                var exchangeConfigs = await LoadExchangeConfigInternal();
                HttpContext.Session.SetComplexData("ExchangeConfig", exchangeConfigs);

                return View();
            }

            // 2. Nếu chưa đăng nhập, kiểm tra Token trên URL
            // Debug logging
            log.Info($"Index: Request QueryString: {Request.QueryString}");
            var tokenKeys = Request.Query.Keys;
            log.Info($"Index: Query Keys: {string.Join(", ", tokenKeys)}");
            
            var token = Request.Query["token"].FirstOrDefault();
            log.Info($"Index: Token extracted: '{token}'");

            if (!string.IsNullOrEmpty(token))
            {
                log.Info($"Index: Token found in URL, attempting login...");
                HttpContext.Session.GetComplexData<string?>("tokenRedirect");
                HttpContext.Session.SetComplexData("tokenRedirect", token);
                try
                {
                    // Tạo request
                    var request = new TokenLoginReq
                    {
                        token = token,
                        language = GetLanguage()
                    };
                    var url = GetParameter("Url") + ApiUrlConstant.AuthLoginUrl;
                    // Gọi API xác thực
                    var resData = await DotnetLib.Rest.RestHandler.SendPostWithAuthen(
                        log,
                        url,
                        request,
                        token,
                        token,
                        "",
                        GetLanguage()
                    );

                    // Parse response
                    if (resData != null)
                    {
                        TokenLoginRes response = new TokenLoginRes(resData.data);
                        
                        if (response.errorCode == CommonErrorCode.Success)
                        {
                            // Login thành công -> Lưu Session
                            CreateAuthToken();
                            HttpContext.Session.SetComplexData("token", token);
                            HttpContext.Session.SetComplexData("msisdn", response.data?.msisdn);
                            HttpContext.Session.SetComplexData("winCoin", response.data?.winCoin);
                            HttpContext.Session.SetComplexData("betCoin", response.data?.betCoin);
                            HttpContext.Session.SetComplexData("userInfo", response.data);
                            HttpContext.Session.SetComplexData("isRegistered", response.data?.isRegistered);

                            log.Info($"Index: Login success, MSISDN = {response.data?.msisdn}");

                            // Redirect lại Index để xóa token khỏi URL (và để lọt vào check IsAuthenticated ở trên)
                            return RedirectToAction("Index");
                        }
                        else
                        {
                            log.Warn($"Index: Login failed - {response.message}");
                        }
                    }
                }
                catch (Exception ex)
                {
                    log.Error("Index: Login exception", ex);
                }
            }

            // 3. Nếu chạy đến đây nghĩa là: Chưa Login Session VÀ (Không có token HOẶC Login Token thất bại)
            // ==> Redirect về trang nguồn (sicbo.vn)
            return RedirectToLogin(_configuration);
        }

        public async Task<IActionResult> Play()
        {
            var token = "";
            // 1. Kiểm tra nếu đã đăng nhập từ trước
            if (IsAuthenticated())
            {
                token = HttpContext.Session.GetComplexData<string>("tokenRedirect");
                log.Info($"Play: token = "+ token);
            }
            var url = GetParameter("RedirectUrl") + "/?token=" + token;
            log.Info($"PlayUrl: url = " + url);
            ClearCache();
            // Không gọi ClearCache() để giữ session login khi user quay lại
            return Redirect(url);
        }

        public IActionResult Privacy()
        {
            if (!IsAuthenticated()) return RedirectToLogin(_configuration);
            return View();
        }

        /// <summary>
        /// Helper to load play history
        /// </summary>
        private async Task<List<PlayHistoryItem>> LoadPlayHistoryInternal()
        {
            try
            {

                var token = GetToken();
                // 3 days ago
                var fromDate = DateTime.Now.AddDays(-3).ToString("dd/MM/yyyy 00:00:00");
                var toDate = DateTime.Now.ToString("dd/MM/yyyy 23:59:59");

                var request = new PlayHistoryReq
                {
                    msisdn = GetMsisdn(),
                    lang = GetLanguage(),
                    fromDate = fromDate,
                    toDate = toDate,
                    pageNumber = 0,
                    pageSize = 100 
                };

                var url = GetParameter("Url") + ApiUrlConstant.PlayHistoryUrl;

                var resData = await DotnetLib.Rest.RestHandler.SendPostWithAuthen(
                    log,
                    url,
                    request,
                    token,
                    token,
                    "",
                    GetLanguage()
                );

                if (resData != null)
                {
                    PlayHistoryRes response = new PlayHistoryRes(resData.data);
                    if (response.errorCode == CommonErrorCode.Success && response.data != null)
                    {
                        return response.data;
                    }
                }
            }
            catch (Exception ex)
            {
                log.Error("LoadPlayHistoryInternal: Error", ex);
            }
            return new List<PlayHistoryItem>();
        }

        /// <summary>
        /// Helper to load purchase history
        /// </summary>
        private async Task<List<PurchaseHistoryItem>> LoadPurchaseHistoryInternal()
        {
            try
            {
                var token = GetToken();
                // 30 days ago for purchase history
                var fromDate = DateTime.Now.AddDays(-30).ToString("dd/MM/yyyy 00:00:00");
                var toDate = DateTime.Now.ToString("dd/MM/yyyy 23:59:59");

                var request = new PurchaseHistoryReq
                {
                    msisdn = GetMsisdn(),
                    lang = GetLanguage(),
                    fromDate = fromDate,
                    toDate = toDate,
                    pageNumber = 0,
                    pageSize = 20
                };

                var url = GetParameter("Url") + ApiUrlConstant.PurchaseHistoryUrl;

                var resData = await DotnetLib.Rest.RestHandler.SendPostWithAuthen(
                    log,
                    url,
                    request,
                    token,
                    token,
                    "",
                    GetLanguage()
                );

                if (resData != null)
                {
                    PurchaseHistoryRes response = new PurchaseHistoryRes(resData.data);
                    if (response.errorCode == CommonErrorCode.Success && response.data != null)
                    {
                        return response.data;
                    }
                }
            }
            catch (Exception ex)
            {
                log.Error("LoadPurchaseHistoryInternal: Error", ex);
            }
            return new List<PurchaseHistoryItem>();
        }

        /// <summary>
        /// Helper to load exchange history
        /// </summary>
        private async Task<List<ExchangeHistoryItem>> LoadExchangeHistoryInternal()
        {
            try
            {
                var token = GetToken();
                // 30 days ago
                var fromDate = DateTime.Now.AddDays(-30).ToString("dd/MM/yyyy 00:00:00");
                var toDate = DateTime.Now.ToString("dd/MM/yyyy 23:59:59");

                var request = new ExchangeHistoryReq
                {
                    msisdn = GetMsisdn(),
                    lang = GetLanguage(),
                    fromDate = fromDate,
                    toDate = toDate,
                    pageNumber = 0,
                    pageSize = 20
                };

                var url = GetParameter("Url") + ApiUrlConstant.ExchangeHistoryUrl;

                var resData = await DotnetLib.Rest.RestHandler.SendPostWithAuthen(
                    log,
                    url,
                    request,
                    token,
                    token,
                    "",
                    GetLanguage()
                );

                if (resData != null)
                {
                    ExchangeHistoryRes response = new ExchangeHistoryRes(resData.data);
                    if (response.errorCode == CommonErrorCode.Success && response.data != null)
                    {
                        return response.data;
                    }
                }
            }
            catch (Exception ex)
            {
                log.Error("LoadExchangeHistoryInternal: Error", ex);
            }
            return new List<ExchangeHistoryItem>();
        }

        public async Task<IActionResult> History()
        {
            if (!IsAuthenticated()) return RedirectToLogin(_configuration);
            
            var gameHistory = await LoadPlayHistoryInternal();
            // User requested: "history prize then pass its msisdn and it is Daily prize"
            var prizeHistory = await LoadRankingInternal("DAILY", GetMsisdn());
            var purchaseHistory = await LoadPurchaseHistoryInternal();
            var exchangeHistory = await LoadExchangeHistoryInternal();
            
            var model = new HistoryViewModel
            {
                GameHistory = gameHistory,
                PrizeHistory = prizeHistory,
                PurchaseHistory = purchaseHistory,
                ExchangeHistory = exchangeHistory
            };
            
            ViewData["Msisdn"] = GetMsisdn();
            return View(model);
        }

        public IActionResult Winner()
        {
            if (!IsAuthenticated()) return RedirectToLogin(_configuration);
            return View();
        }

        /// <summary>
        /// Helper to load ranking history
        /// </summary>
        /// <summary>
        /// Helper to load ranking history
        /// </summary>
        private async Task<List<RankingHistoryItem>> LoadRankingInternal(string rankType, string msisdn = null, string specificDate = null)
        {
            try 
            {
                var token = GetToken();
                // Calculate date range based on rankType
                string fromDate = "";
                string toDate = DateTime.Now.ToString("dd/MM/yyyy");

                if (!string.IsNullOrEmpty(specificDate))
                {
                    if (rankType == "MONTHLY" || rankType == "MONTHLYCOIN")
                    {
                        // Expected input: yyyy-MM
                        if (DateTime.TryParseExact(specificDate, "yyyy-MM", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out DateTime parsedMonth))
                        {
                             var firstDay = new DateTime(parsedMonth.Year, parsedMonth.Month, 1);
                             var lastDay = firstDay.AddMonths(1).AddDays(-1);
                             
                             fromDate = firstDay.ToString("dd/MM/yyyy 00:00:00");
                             toDate = lastDay.ToString("dd/MM/yyyy 23:59:59");
                        }
                        else
                        {
                             // Fallback try basic parsing
                             if (DateTime.TryParse(specificDate, out DateTime parsed)) {
                                 var firstDay = new DateTime(parsed.Year, parsed.Month, 1);
                                 var lastDay = firstDay.AddMonths(1).AddDays(-1);
                                 fromDate = firstDay.ToString("dd/MM/yyyy 00:00:00");
                                 toDate = lastDay.ToString("dd/MM/yyyy 23:59:59");
                             }
                        }
                    }
                    else if (rankType == "DAILYCOIN")
                    {
                        if (DateTime.TryParseExact(specificDate, "yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out DateTime parsedDate))
                        {
                            fromDate = parsedDate.ToString("dd/MM/yyyy 00:00:00");
                            toDate = parsedDate.ToString("dd/MM/yyyy 23:59:59");
                        }
                        else
                        {
                            // Fallback try basic parsing
                            if (DateTime.TryParse(specificDate, out DateTime parsed))
                            {
                                fromDate = parsed.ToString("dd/MM/yyyy 00:00:00");
                                toDate = parsed.ToString("dd/MM/yyyy 23:59:59");
                            }
                        }
                    } else
                    {
                        // DAILY - Exact Date
                        // Convert yyyy-MM-dd to dd/MM/yyyy HH:mm:ss
                        // Input expected: yyyy-MM-dd (from HTML5 date input)
                        if (DateTime.TryParseExact(specificDate, "yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out DateTime parsedDate))
                        {
                            fromDate = parsedDate.ToString("dd/MM/yyyy 00:00:00");
                            toDate = parsedDate.ToString("dd/MM/yyyy 23:59:59");
                        }
                        else
                        {
                            // Fallback: try to just append time if it looks like a date
                            fromDate = specificDate + " 00:00:00";
                            toDate = specificDate + " 23:59:59";
                        }
                    }
                }
                else
                {
                    if (rankType == "DAILY" || rankType == "DAILYCOIN")
                    {
                        fromDate = DateTime.Now.ToString("dd/MM/yyyy 00:00:00");
                        toDate = DateTime.Now.ToString("dd/MM/yyyy 23:59:59");
                    }
                    else if (rankType == "MONTHLY" || rankType == "MONTHLYCOIN")
                    {
                        var firstDay = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
                        var lastDay = firstDay.AddMonths(1).AddDays(-1);
                        fromDate = firstDay.ToString("dd/MM/yyyy 00:00:00");
                        toDate = lastDay.ToString("dd/MM/yyyy 23:59:59");
                    }
                }

                var request = new RankingHistoryReq
                {
                    msisdn = msisdn, // Pass specific msisdn or null/empty
                    lang = GetLanguage(),
                    rankType = (rankType == "DAILY" || rankType == "DAILYCOIN") ? "DAILY" : "MONTHLY",
                    fromDate = fromDate,
                    toDate = toDate,
                    pageNumber = 0,
                    pageSize = (rankType == "DAILY" || rankType == "DAILYCOIN" || rankType == "MONTHLYCOIN") ? 50 : 5
                };
                
                var url = GetParameter("Url") + ApiUrlConstant.RankingHistoryUrl;
                
                var resData = await DotnetLib.Rest.RestHandler.SendPostWithAuthen(
                    log,
                    url,
                    request,
                    token,
                    token,
                    "",
                    GetLanguage()
                );
                
                if (resData != null)
                {
                     RankingHistoryRes response = new RankingHistoryRes(resData.data);
                     if (response.errorCode == CommonErrorCode.Success && response.data != null)
                     {
                         string currentMsisdn = GetMsisdn();
                         foreach (var item in response.data)
                         {
                             if (item.msisdn != currentMsisdn)
                             {
                                 item.msisdn = MaskMsisdn(item.msisdn);
                             }
                         }
                         return response.data;
                     }
                }
            }
            catch(Exception ex)
            {
                log.Error($"LoadRankingInternal ({rankType}): Error", ex);
            }
            return new List<RankingHistoryItem>();
        }

        [HttpPost]
        public async Task<IActionResult> GetRankingCoinData([FromBody] RankingHistoryReq request)
        {
            if (!IsAuthenticated()) return Json(new { errorCode = CommonErrorCode.UnauthorizedAccess });

            try
            {
                string rankType = request?.rankType ?? "MONTHLYCOIN";

                var specificDate = rankType == "DAILYCOIN" ? DateTime.Now.ToString("yyyy-MM-dd") : DateTime.Now.ToString("yyyy-MM");
                
                var globalRankings = await LoadRankingCoinHistoryInternal(rankType, null, specificDate);
                var userRanking = await LoadRankingCoinHistoryInternal(rankType, GetMsisdn(), specificDate);
                var currentUserItem = userRanking?.FirstOrDefault(x => x.msisdn == GetMsisdn());

                return Json(new { 
                    errorCode = CommonErrorCode.Success, 
                    data = new { global = globalRankings, user = currentUserItem } 
                });
            }
            catch (Exception ex)
            {
                log.Error("GetRankingCoinData: Error", ex);
                return Json(new { errorCode = CommonErrorCode.SystemError });
            }
        }


        private async Task<List<RankingHistoryItem>> LoadRankingCoinHistoryInternal(string rankType, string msisdn = null, string specificDate = null)
        {
            try
            {
                var token = GetToken();
                // Calculate date range based on rankType
                string fromDate = "";
                string toDate = DateTime.Now.ToString("dd/MM/yyyy");

                if (!string.IsNullOrEmpty(specificDate))
                {
                    if (rankType == "MONTHLYCOIN")
                    {
                        // Expected input: yyyy-MM
                        if (DateTime.TryParseExact(specificDate, "yyyy-MM", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out DateTime parsedMonth))
                        {
                            var firstDay = new DateTime(parsedMonth.Year, parsedMonth.Month, 1);
                            var lastDay = firstDay.AddMonths(1).AddDays(-1);

                            fromDate = firstDay.ToString("dd/MM/yyyy 00:00:00");
                            toDate = lastDay.ToString("dd/MM/yyyy 23:59:59");
                        }
                        else
                        {
                            // Fallback try basic parsing
                            if (DateTime.TryParse(specificDate, out DateTime parsed))
                            {
                                var firstDay = new DateTime(parsed.Year, parsed.Month, 1);
                                var lastDay = firstDay.AddMonths(1).AddDays(-1);
                                fromDate = firstDay.ToString("dd/MM/yyyy 00:00:00");
                                toDate = lastDay.ToString("dd/MM/yyyy 23:59:59");
                            }
                        }
                    }
                    else if (rankType == "DAILYCOIN")
                    {
                        if (DateTime.TryParseExact(specificDate, "yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out DateTime parsedDate))
                        {
                            fromDate = parsedDate.ToString("dd/MM/yyyy 00:00:00");
                            toDate = parsedDate.ToString("dd/MM/yyyy 23:59:59");
                        }
                        else
                        {
                            // Fallback try basic parsing
                            if (DateTime.TryParse(specificDate, out DateTime parsed))
                            {
                                fromDate = parsed.ToString("dd/MM/yyyy 00:00:00");
                                toDate = parsed.ToString("dd/MM/yyyy 23:59:59");
                            }
                        }
                    }
                    
                }
                else
                {
                    if (rankType == "DAILYCOIN")
                    {
                        fromDate = DateTime.Now.ToString("dd/MM/yyyy 00:00:00");
                        toDate = DateTime.Now.ToString("dd/MM/yyyy 23:59:59");
                    }
                    else if (rankType == "MONTHLYCOIN")
                    {
                        var firstDay = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
                        var lastDay = firstDay.AddMonths(1).AddDays(-1);
                        fromDate = firstDay.ToString("dd/MM/yyyy 00:00:00");
                        toDate = lastDay.ToString("dd/MM/yyyy 23:59:59");
                    }
                }

                var request = new RankingHistoryReq
                {
                    msisdn = msisdn, // Pass specific msisdn or null/empty
                    lang = GetLanguage(),
                    rankType = (rankType == "DAILY" || rankType == "DAILYCOIN") ? "DAILY" : "MONTHLY",
                    fromDate = fromDate,
                    toDate = toDate,
                    pageNumber = 0,
                    pageSize = (rankType == "DAILY" || rankType == "DAILYCOIN" || rankType == "MONTHLYCOIN") ? 50 : 5
                };

                var url = GetParameter("Url") + ApiUrlConstant.RankingCointHistoryUrl;

                var resData = await DotnetLib.Rest.RestHandler.SendPostWithAuthen(
                    log,
                    url,
                    request,
                    token,
                    token,
                    "",
                    GetLanguage()
                );

                if (resData != null)
                {
                    RankingHistoryRes response = new RankingHistoryRes(resData.data);
                    if (response.errorCode == CommonErrorCode.Success && response.data != null)
                    {
                        string currentMsisdn = GetMsisdn();
                        foreach (var item in response.data)
                        {
                            if (item.msisdn != currentMsisdn)
                            {
                                item.msisdn = MaskMsisdn(item.msisdn);
                            }
                        }
                        return response.data;
                    }
                }
            }
            catch (Exception ex)
            {
                log.Error($"LoadRankingInternal ({rankType}): Error", ex);
            }
            return new List<RankingHistoryItem>();
        }

        public async Task<IActionResult> DailyRanking(string date = null)
        {
            if (!IsAuthenticated()) return RedirectToLogin(_configuration);
            
            // For Global Daily Ranking, we don't pass MSISDN implies global list
            var data = await LoadRankingInternal("DAILY", null, date);
            ViewData["RankingType"] = "DAILY";
            ViewData["SelectedDate"] = date; 
            return View(data);
        }

        public async Task<IActionResult> MonthlyRanking(string date = null)
        {
            if (!IsAuthenticated()) return RedirectToLogin(_configuration);
            
            var data = await LoadRankingInternal("MONTHLY", null, date);
            ViewData["RankingType"] = "MONTHLY";
            ViewData["SelectedDate"] = date;
            return View(data);
        }

        public async Task<IActionResult> Account()
        {
            if (!IsAuthenticated()) return RedirectToLogin(_configuration);

            // Refresh account info to get latest balance
            await ReloadAccountInfo();

            // Get user info from session
            var userInfo = HttpContext.Session.GetComplexData<TokenLoginData>("userInfo");
            
            ViewData["UserInfo"] = userInfo;
            ViewData["Msisdn"] = GetMsisdn();
            ViewData["WinCoin"] = HttpContext.Session.GetComplexData<decimal?>("winCoin") ?? 0;
            ViewData["BetCoin"] = HttpContext.Session.GetComplexData<decimal?>("betCoin") ?? 0;
            
            // TODO: Retrieve actual values for Today/Month from API when available
            ViewData["TotalValueToday"] = 0;
            ViewData["TotalValueMonth"] = 0;

            return View();
        }

        /// <summary>
        /// Đăng xuất
        /// </summary>
        public IActionResult Logout()
        {
            ClearCache();
            return RedirectToLogin(_configuration);
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }


        /// <summary>
        /// Đăng ký gói (Register)
        /// </summary>
        [HttpPost]
        public async Task<IActionResult> Register()
        {
            // 1. Check Authentication (server-side check)
            if (!IsAuthenticated())
            {
                return Json(new { errorCode = CommonErrorCode.UnauthorizedAccess, message = "Unauthorized" });
            }

            try
            {
                // 2. Prepare request data
                string? msisdn = GetMsisdn();
                string? token = GetToken();
                // Default package for daily registration
                string packageCode = GetParameter("PackageCodeDaily"); 
                // Default fallback if config missing
                if (string.IsNullOrEmpty(packageCode)) packageCode = "SICBO_DAY";

                var request = new RegisterReq
                {
                    msisdn = msisdn,
                    packageCode = packageCode,
                    lang = GetLanguage()
                };

                // 3. Call API
                var url = GetParameter("Url") + ApiUrlConstant.RegisterUrl;
                
                var resData = await DotnetLib.Rest.RestHandler.SendPostWithAuthen(
                    log,
                    url,
                    request,
                    token,
                    token,
                    "",
                    GetLanguage()
                );

                // 4. Handle Response
                if (resData != null)
                {
                    RegisterRes response = new RegisterRes(resData.data);
                    
                    if (response.errorCode == CommonErrorCode.Success)
                    {
                        // Refresh info to get latest balance
                        await ReloadAccountInfo();
                        
                        // Update response data with latest session info
                        if (response.data == null) response.data = new RegisterData();
                        
                        response.data.winCoin = HttpContext.Session.GetComplexData<decimal?>("winCoin");
                        response.data.betCoin = HttpContext.Session.GetComplexData<decimal?>("betCoin");

                        return Json(response);
                    }
                    else
                    {
                        return Json(new { errorCode = response.errorCode, message = response.message });
                    }
                }
                
                return Json(new { errorCode = CommonErrorCode.Error, message = "System Error" });
            }
            catch (Exception ex)
            {
                log.Error("Register: Exception", ex);
                return Json(new { errorCode = CommonErrorCode.SystemError, message = "Exception" });
            }
        }

        /// <summary>
        /// Mua thêm lượt (Buy More)
        /// </summary>
        [HttpPost]
        public async Task<IActionResult> BuyMore([FromBody] BuyMoreReq reqBody)
        {
            // 1. Check Authentication
            if (!IsAuthenticated())
            {
                return Json(new { errorCode = CommonErrorCode.UnauthorizedAccess, message = "Unauthorized" });
            }

            try
            {
                // 2. Prepare Request
                string msisdn = GetMsisdn();
                string token = GetToken();
                
                var request = new BuyMoreReq
                {
                    msisdn = msisdn,
                    packageCode = reqBody.packageCode,
                    lang = GetLanguage()
                };

                // 3. Call API
                var url = GetParameter("Url") + ApiUrlConstant.BuyMoreUrl;
                
                var resData = await DotnetLib.Rest.RestHandler.SendPostWithAuthen(
                    log,
                    url,
                    request,
                    token,
                    token,
                    "",
                    GetLanguage()
                );

                // 4. Handle Response
                if (resData != null)
                {
                    BuyMoreRes response = new BuyMoreRes(resData.data);

                    if (response.errorCode == CommonErrorCode.Success)
                    {
                        // Refresh info to get latest balance
                        await ReloadAccountInfo();

                        // Update response data with latest session info
                        if (response.data == null) response.data = new BuyMoreData();

                        response.data.winCoin = HttpContext.Session.GetComplexData<decimal?>("winCoin");
                        response.data.betCoin = HttpContext.Session.GetComplexData<decimal?>("betCoin");
                        
                        return Json(response);
                    }
                    else
                    {
                        return Json(new { errorCode = response.errorCode, message = response.message });
                    }
                }

                return Json(new { errorCode = CommonErrorCode.Error, message = "System Error" });
            }
            catch (Exception ex)
            {
                log.Error("BuyMore: Exception", ex);
                return Json(new { errorCode = CommonErrorCode.SystemError, message = "Exception" });
            }
        }

        /// <summary>
        /// Request Withdraw OTP
        /// </summary>
        [HttpPost]
        public async Task<IActionResult> RequestWithdrawOtp([FromBody] ExchangeRequestOtpReq reqBody)
        {
            if (!IsAuthenticated())
            {
                return Json(new { errorCode = CommonErrorCode.UnauthorizedAccess, message = "Unauthorized" });
            }

            try
            {
                
                string msisdn = GetMsisdn();
                string token = GetToken();
                
                var request = new ExchangeRequestOtpReq
                {
                    msisdn = msisdn,
                    configId = reqBody.configId,
                    lang = GetLanguage()
                };

                // Call API
                var url = GetParameter("Url") + ApiUrlConstant.ExchangeRequestOtpUrl;
                
                var resData = await DotnetLib.Rest.RestHandler.SendPostWithAuthen(
                    log,
                    url,
                    request,
                    token,
                    token,
                    "",
                    GetLanguage()
                );

                if (resData != null)
                {
                    ExchangeRequestOtpRes response = new ExchangeRequestOtpRes(resData.data);
                    return Json(new { errorCode = response.errorCode, message = response.message, data = response.data });
                }
                
                return Json(new { errorCode = CommonErrorCode.Error, message = "System Error" });
            }
            catch (Exception ex)
            {
                log.Error("RequestWithdrawOtp: Exception", ex);
                return Json(new { errorCode = CommonErrorCode.SystemError, message = "Exception" });
            }
        }

        /// <summary>
        /// Confirm Withdraw OTP
        /// </summary>
        [HttpPost]
        public async Task<IActionResult> ConfirmWithdrawOtp([FromBody] ExchangeVerifyOtpReq reqBody)
        {
             // 1. Check Authentication
            if (!IsAuthenticated())
            {
                return Json(new { errorCode = CommonErrorCode.UnauthorizedAccess, message = "Unauthorized" });
            }

            try
            {
                string msisdn = GetMsisdn();
                string token = GetToken();
                
                var request = new ExchangeVerifyOtpReq
                {
                    msisdn = msisdn,
                    otpCode = reqBody.otpCode,
                    lang = GetLanguage()
                };

                // Call API
                var url = GetParameter("Url") + ApiUrlConstant.ExchangeVerifyOtpUrl;
                
                var resData = await DotnetLib.Rest.RestHandler.SendPostWithAuthen(
                    log,
                    url,
                    request,
                    token,
                    token,
                    "",
                    GetLanguage()
                );

                if (resData != null)
                {
                    ExchangeVerifyOtpRes response = new ExchangeVerifyOtpRes(resData.data);
                    if (response.errorCode == CommonErrorCode.Success)
                    {
                        // Refresh Account Info
                        await ReloadAccountInfo();
                        
                        // Get updated fields
                        var winCoin = HttpContext.Session.GetComplexData<decimal?>("winCoin");
                        var betCoin = HttpContext.Session.GetComplexData<decimal?>("betCoin");

                        return Json(new { errorCode = response.errorCode, message = response.message, data = new { winCoin, betCoin } });
                    }
                    
                    return Json(new { errorCode = response.errorCode, message = response.message, data = response.data });
                }
                
                return Json(new { errorCode = CommonErrorCode.Error, message = "System Error" });
            }
            catch (Exception ex)
            {
                log.Error("ConfirmWithdrawOtp: Exception", ex);
                return Json(new { errorCode = CommonErrorCode.SystemError, message = "Exception" });
            }
        }

        /// <summary>
        /// Lấy danh sách gói cước (Packages)
        /// </summary>
        [HttpPost]
        public async Task<IActionResult> GetPackages()
        {
            // 1. Check Authentication
            if (!IsAuthenticated())
            {
                return Json(new { errorCode = CommonErrorCode.UnauthorizedAccess, message = "Unauthorized" });
            }
            var packages = await LoadPackagesInternal();
            return Json(new { errorCode = CommonErrorCode.Success, data = packages });
        }

        private string MaskMsisdn(string msisdn)
        {
            if (string.IsNullOrEmpty(msisdn)) return msisdn;
            
            int len = msisdn.Length;
            if (len <= 5) return msisdn;
            
            if (len == 10)
            {
                return msisdn.Substring(0, 3) + "xxxxx" + msisdn.Substring(8);
            }
            else if (len == 11)
            {
                return msisdn.Substring(0, 3) + "xxxxx" + msisdn.Substring(8);
            }
            else
            {
                if (len > 5) {
                    int maskStart = (len - 5) / 2;
                    return msisdn.Substring(0, maskStart) + "xxxxx" + msisdn.Substring(maskStart + 5);
                }
                return msisdn;
            }
        }
    }
}
