using boilerplate.Models;
using Microsoft.Ajax.Utilities;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Core.Common.CommandTrees.ExpressionBuilder;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.SqlServer;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using System.Web.UI.WebControls;

namespace boilerplate.Controllers
{
    public class PanelController : Controller
    {
        boilerplateEntities db = new boilerplateEntities();
        readonly Functions functions = new Functions();

        public async Task<ActionResult> Index()
        {
            if (!HasSession()) { return RedirectToAction("Login"); }
            if (HasSession("ManageDashboard"))
            {
                var user = Session["User"] as User;

                ViewBag.Title = "داشبورد";
                ViewBag.Counter1 = db.Users.Count();
                ViewBag.Counter2 = db.Users.Count();
                ViewBag.Counter3 = db.Users.Count();
                ViewBag.Counter4 = db.Users.Count();
                ViewBag.Counter5 = db.Users.Count();
                ViewBag.Counter6 = db.Users.Count();
            }
            return View();
        }

        public async Task<ActionResult> Users()
        {
            List<UserModel> models = new List<UserModel>();

            if (!HasSession("ManageUser")) { return RedirectToAction("Index"); }
            models = db.Users.AsNoTracking().Select(x => new UserModel
            {
                Id = x.User_Id,
                Name = x.User_Name,
                Family = x.User_Family,
                Phone = x.User_Phone,
                Code = x.User_Code,
                Status = x.User_Status,
                Role = x.User_Role,
                CreatedDate = x.User_CreatedDateFa
            }).ToList();

            return View(models);
        }

        public new async Task<ActionResult> User(int Id = 0)
        {
            if (!HasSession("ManageUser")) { return new HttpStatusCodeResult(HttpStatusCode.Unauthorized); }
            var model = new User()
            {
                User_Id = Id,
                User_Status = 1,
                User_Image = "dUser.png"
            };
            if (Id != 0)
            {


                model = db.Users.AsNoTracking().Where(x => x.User_Id == Id).FirstOrDefault();
                if (model == null) { return RedirectToAction("Users"); }

            }

            return View(model);
        }

        [Route("~/panel/Setting")]
        public async Task<ActionResult> Setting()
        {

            var model = new Setting()
            {
                Setting_Id = 1,
                Setting_Social = "[]",
                Setting_Send = false,
            };
            if (!HasSession("ManageSetting")) { return RedirectToAction("Index"); }

            model = db.Settings.AsNoTracking().FirstOrDefault();

            return View(model);
        }

        [Route("~/panel/SaveSettings")]
        [HttpPost]
        public async Task<JsonResult> SaveSettings()
        {
            StatusModel statusModel = new StatusModel() { Status = "Success" };

            try
            {
                if (HasSession())
                {
                    var User = Session["User"] as User;
                    if (HasSession("ManageSetting")
)
                    {
                        SettingModel model = JsonConvert.DeserializeObject<SettingModel>(Request.Form["Model"]);
                        var Settings = await db.Settings.FirstOrDefaultAsync();
                        if (Settings != null)
                        {
                            Settings.Setting_Name = model.Name;
                            Settings.Setting_Title = model.Title;
                            Settings.Setting_Discount = model.Discount;
                            Settings.Setting_Description = model.Description;
                            Settings.Setting_Keywords = model.Keywords;
                            Settings.Setting_Footer = model.Footer;
                            Settings.Setting_Header = model.Header;
                            Settings.Setting_Social = JsonConvert.SerializeObject(model.Socials);
                            Settings.Setting_Username = model.SmsUsername;
                            Settings.Setting_Password = model.SmsPassword;
                            Settings.Setting_FromNumber = model.SmsFromNumber;
                            Settings.Setting_PaternLogin = model.SmsPaternLogin;
                            Settings.Setting_Address = model.address;
                            Settings.Setting_PostCode = model.postcode;
                            Settings.Setting_Phone = model.phone;
                            Settings.Setting_Website = model.website;
                            db.Entry(Settings).State = EntityState.Modified;
                            for (int i = 0; i < Request.Files.Count; i++)
                            {
                                switch (Request.Files.AllKeys[i])
                                {
                                    case "Logo":
                                        Request.Files[i].SaveAs(Server.MapPath($"~/Media/logo.png"));
                                        break;
                                    case "Icon":
                                        Request.Files[i].SaveAs(Server.MapPath($"~/Media/favicon.ico"));
                                        break;
                                }
                            }
                        }
                    }
                }
                else { statusModel.Status = "Auth"; }
            }
            catch { statusModel.Status = "Error"; }
            return Json(statusModel);
        }



        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<JsonResult> Login(LoginModel model)
        {
            StatusModel statusModel = new StatusModel() { Status = "Success" };
            try
            {
                if (ModelState.IsValid)
                {
                    if (!string.IsNullOrEmpty(model.Username) && !string.IsNullOrEmpty(model.Password))
                    {
                        var User = await db.Users.Where(x => x.User_Phone == model.Username && x.User_Role == "Admin").FirstOrDefaultAsync();
                        if (User != null)
                        {
                            if (User.User_Status == 1)
                            {
                                if (User.User_Password == functions.HashPassword(model.Password + User.User_CreatedDate))
                                {
                                    DateTime Now = DateTime.Now;
                                    string Token = functions.GenerateToken();
                                    User.User_LoginDate = Now;
                                    User.User_LoginDateFa = functions.ConvertToPersianDate(Now);
                                    User.User_Token = Token;
                                    await db.SaveChangesAsync();
                                    Session["User"] = User;
                                    SetCookie("UserId", $"{User.User_Id}");
                                    SetCookie("Token", Token);


                                }
                                else { statusModel.Status = "Wrong"; }
                            }
                            else { statusModel.Status = "Block"; }
                        }
                        else { statusModel.Status = "NoExist"; }
                    }
                    else { statusModel.Status = "Empty"; }
                }
                else { statusModel.Status = "NotValid"; }
            }
            catch { statusModel.Status = "Error"; }
            return Json(statusModel);
        }

        [Route("~/Panel/Logout")]
        public async Task Logout()
        {
            if (Session["User"] != null)
            {
                var UserModel = Session["User"] as User;
                var Single = await db.Users.FindAsync(UserModel.User_Id);
                if (Single != null)
                {
                    Single.User_Token = null;
                    await db.SaveChangesAsync();
                }
            }
            Session.Clear();
            Session.Abandon();
            SetCookie("UserId", "", -1);
            SetCookie("UserToken", "", -1);
            Response.Redirect("~/Panel/Login");
        }
        [Route("~/Login")]
        [Route("Login")]
        public async Task<ActionResult> Login(string Return = "")
        {
            ViewBag.Return = Return;
            if (Session["User"] != null)
            {
                Response.Redirect("~/panel/index");
            }
            else if (UserSessionExists()) { Response.Redirect("~/panel/Index"); }
            return View();
        }

        bool UserSessionExists()
        {
            try
            {
                string Token = GetCookie("Token");
                decimal.TryParse(GetCookie("UserId"), out decimal UserId);
                if (!string.IsNullOrEmpty(Token) && UserId != 0)
                {
                    var Single = db.Users.Where(x => x.User_Id == UserId && x.User_Token == Token && x.User_Status == 1 && x.User_Role == "Admin").FirstOrDefault();
                    if (Single != null)
                    {
                        Session["User"] = Single;
                    }
                    else
                    {
                        SetCookie("Token", "", -1);
                        SetCookie("UserId", "", -1);
                    }
                    if (Session["User"] != null) { return true; }
                }
                SetCookie("Token", "", -1);
                SetCookie("UserId", "", -1);
                return false;
            }
            catch { return false; }
        }

        bool HasSession(string Access = "")
        {
            if (Session["User"] == null && !UserSessionExists()) return false;
            return string.IsNullOrEmpty(Access) || functions.HasAccess((Session["User"] as User).User_Access, Access);
        }

        [Route("~/Verify")]
        [Route("Verify")]
        public ActionResult Verify(string Phone = "", string Return = "")
        {
            ViewBag.Return = Return;
            if (Session["User"] != null)
            {
                Response.Redirect("~/Index");
            }
            if (Phone == "")
            {
                Response.Redirect("~/Login");
            }
            else
            {
                ViewBag.Phone = Phone;
            }
            return View();
        }
        //set session and cookies afte login
        [HttpGet]
        [Route("Complete")]
        [Route("~/Complete")]
        public ActionResult Complete()
        {
            try
            {
                // Log query parameters
                var user = Request.QueryString["User"];
                var token = Request.QueryString["Token"];

                if (string.IsNullOrEmpty(user) || string.IsNullOrEmpty(token))
                {
                    Console.WriteLine("User or Token is missing in the query string.");
                    return new HttpStatusCodeResult(400, "Bad Request: User or Token missing.");
                }

                // Log the query parameters
                Console.WriteLine($"User: {user}, Token: {token}");

                var currentuser = db.Users
                    .Where(x => x.User_Id.ToString() == user && x.User_Token.ToString() == token)
                    .FirstOrDefault();

                if (currentuser != null)
                {
                    // Perform necessary actions, like setting session and cookies
                    Session["User"] = currentuser;
                    SetCookie("UserId", $"{currentuser.User_Id}");
                    SetCookie("Token", currentuser.User_Token);

                    // Log success
                    Console.WriteLine("User authenticated and session updated.");
                }
                else
                {
                    // Log if user is not found
                    Console.WriteLine("User not found.");
                    return new HttpStatusCodeResult(404, "User not found.");
                }
            }
            catch (Exception ex)
            {
                // Log error details
                Console.WriteLine($"Error in Complete: {ex.Message}");
                return new HttpStatusCodeResult(500, "Internal Server Error: " + ex.Message);
            }

            // Return a success response or redirect
            return new HttpStatusCodeResult(200, "Request completed successfully.");
        }

        string SetCookie(string Key, string Value, int ExpireDay = 365)
        {
            try
            {
                Response.Cookies.Add(new HttpCookie(Key, Value) { Expires = DateTime.Now.AddDays(ExpireDay) });
            }
            catch { }
            return Value;
        }

        string GetCookie(string Key)
        {
            string value = string.Empty;
            try
            {
                var cookie = Request.Cookies[Key];
                if (cookie != null)
                {
                    if (string.IsNullOrWhiteSpace(cookie.Value))
                    {
                        return value;
                    }
                    value = cookie.Value;
                }
            }
            catch { }
            return value;
        }


    }
}
