using boilerplate.Models;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Validation;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using ClosedXML.Excel;

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"))
            {
                ViewBag.Title = "داشبورد";
            }
            return View();
        }

        // --- User Management Actions ---
        public async Task<ActionResult> Users()
        {
            if (!HasSession("ManageUser")) { return RedirectToAction("Index"); }
            var models = await db.Users.AsNoTracking().Select(x => new UserModel
            {
                Id = x.User_Id,
                Name = x.User_Name,
                Family = x.User_Family,
                Phone = x.User_Phone,
                Role = x.User_Role,
                Status = x.User_Status,
                CreatedDate = x.User_CreatedDateFa
            }).ToListAsync();
            return View(models);
        }

        public new async Task<ActionResult> User(int Id = 0)
        {
            if (!HasSession("ManageUser")) { return new HttpStatusCodeResult(HttpStatusCode.Unauthorized); }

            User model;
            if (Id == 0)
            {
                model = new User() { User_Id = 0, User_Status = 1, User_Image = "dUser.png" };
            }
            else
            {
                model = await db.Users.AsNoTracking().FirstOrDefaultAsync(x => x.User_Id == Id);
                if (model == null) { return RedirectToAction("Users"); }
            }
            return View(model);
        }

        // --- News Management Actions (Reverted to simple version) ---
        public async Task<ActionResult> NewsList()
        {
            if (!HasSession("ManageNews")) { return RedirectToAction("Index"); }

            var news = await db.News.OrderByDescending(n => n.News_Date).ToListAsync();
            return View(news);
        }

        // --- News Management Actions ---
        // --- News Management Actions ---
        public class AddNewsViewModel
        {
            public News News { get; set; }
            public List<Item> AllCategories { get; set; }
            public List<Item> AllTags { get; set; }
        }

        public async Task<ActionResult> AddNews(int id = 0)
        {
            if (!HasSession("ManageNews")) { return RedirectToAction("Index"); }

            var allItems = await db.Items.ToListAsync();
            var categories = allItems.Where(i => i.Item_Type == "1").ToList();
            var tags = allItems.Where(i => i.Item_Type == "2").ToList();

            var viewModel = new AddNewsViewModel
            {
                AllCategories = categories,
                AllTags = tags
            };

            if (id == 0)
            {
                ViewBag.PageTitle = "افزودن خبر جدید";
                viewModel.News = new News { News_Date = DateTime.Now };
            }
            else
            {
                var news = await db.News.FindAsync(id);
                if (news == null) { return HttpNotFound(); }
                ViewBag.PageTitle = "ویرایش خبر";
                viewModel.News = news;
            }

            return View(viewModel);
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        [ValidateInput(false)]
        public async Task<ActionResult> AddNews(AddNewsViewModel viewModel, HttpPostedFileBase imageFile, string[] selectedCategories, string[] selectedTags)
        {
            if (!HasSession("ManageNews")) { return RedirectToAction("Index"); }

            // Join multiple selections into comma-separated strings
            viewModel.News.News_Category = selectedCategories != null ? string.Join(",", selectedCategories) : "";
            viewModel.News.News_Tag = selectedTags != null ? string.Join(",", selectedTags) : "";

            // *** ADDED: Server-side validation for required fields ***
            if (viewModel.News.News_ID == 0 && (imageFile == null || imageFile.ContentLength == 0))
            {
                ModelState.AddModelError("imageFile", "لطفاً یک تصویر برای خبر انتخاب کنید.");
            }
            if (selectedCategories == null || !selectedCategories.Any())
            {
                ModelState.AddModelError("selectedCategories", "انتخاب حداقل یک دسته‌بندی الزامی است.");
            }
            if (selectedTags == null || !selectedTags.Any())
            {
                ModelState.AddModelError("selectedTags", "انتخاب حداقل یک تگ الزامی است.");
            }

            try
            {
                if (ModelState.IsValid)
                {
                    var model = viewModel.News;
                    if (imageFile != null && imageFile.ContentLength > 0)
                    {
                        var uploadDir = "~/Media/News";
                        if (!Directory.Exists(Server.MapPath(uploadDir)))
                        {
                            Directory.CreateDirectory(Server.MapPath(uploadDir));
                        }
                        var fileName = Guid.NewGuid().ToString() + Path.GetExtension(imageFile.FileName);
                        var path = Path.Combine(Server.MapPath(uploadDir), fileName);
                        imageFile.SaveAs(path);
                        model.News_IMG = fileName;
                    }

                    if (model.News_ID == 0)
                    {
                        model.News_CreateDate = DateTime.Now;
                        model.News_Date = DateTime.Now;
                        db.News.Add(model);
                    }
                    else
                    {
                        model.News_EditDate = DateTime.Now;
                        db.Entry(model).State = EntityState.Modified;
                        if (imageFile == null)
                        {
                            db.Entry(model).Property(x => x.News_IMG).IsModified = false;
                        }
                    }

                    await db.SaveChangesAsync();
                    return RedirectToAction("NewsList");
                }
            }
            catch (Exception ex)
            {
                ModelState.AddModelError("", "یک خطای پیش‌بینی نشده رخ داد: " + ex.Message);
            }

            // If we get here, something failed. Repopulate the dropdowns.
            var allItems = await db.Items.ToListAsync();
            viewModel.AllCategories = allItems.Where(i => i.Item_Type == "1").ToList();
            viewModel.AllTags = allItems.Where(i => i.Item_Type == "2").ToList();
            return View(viewModel);
        }


        [HttpPost]
        public async Task<JsonResult> DeleteNews(int id)
        {
            if (!HasSession("ManageNews")) { return Json(new { success = false }); }

            var news = await db.News.FindAsync(id);
            if (news != null)
            {
                var imagePath = Server.MapPath("~/Media/News/" + news.News_IMG);
                if (System.IO.File.Exists(imagePath))
                {
                    System.IO.File.Delete(imagePath);
                }

                db.News.Remove(news);
                await db.SaveChangesAsync();
                return Json(new { success = true });
            }
            return Json(new { success = false });
        }

        // --- Item (Category/Tag) Management Actions ---
        public async Task<ActionResult> Items(int id)
        {
            if (!HasSession("ManageItems")) { return RedirectToAction("Index"); }

            string itemTypeString = id.ToString();
            ViewBag.ItemType = id;
            ViewBag.PageTitle = (id == 1) ? "مدیریت دسته‌بندی‌ها" : "مدیریت تگ‌ها";
            ViewBag.NewItemLabel = (id == 1) ? "نام دسته‌بندی جدید" : "نام تگ جدید";

            var items = await db.Items.Where(i => i.Item_Type == itemTypeString).ToListAsync();
            return View(items);
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> AddItem(Item model)
        {
            if (!HasSession("ManageItems")) { return RedirectToAction("Index"); }

            if (ModelState.IsValid && !string.IsNullOrWhiteSpace(model.Item_Title))
            {
                bool exists = await db.Items.AnyAsync(i => i.Item_Title == model.Item_Title && i.Item_Type == model.Item_Type);
                if (!exists)
                {
                    db.Items.Add(model);
                    await db.SaveChangesAsync();
                }
            }
            return RedirectToAction("Items", new { id = Convert.ToInt32(model.Item_Type) });
        }

        [HttpPost]
        public async Task<JsonResult> DeleteItem(int id)
        {
            if (!HasSession("ManageItems")) { return Json(new { success = false }); }

            var item = await db.Items.FindAsync(id);
            if (item != null)
            {
                db.Items.Remove(item);
                await db.SaveChangesAsync();
                return Json(new { success = true });
            }
            return Json(new { success = false });
        }

        // --- Settings Action ---
        [Route("~/panel/Setting")]
        public async Task<ActionResult> Setting()
        {
            if (!HasSession("ManageSetting")) { return RedirectToAction("Index"); }

            var model = await db.Settings.AsNoTracking().FirstOrDefaultAsync();

            if (model == null)
            {
                model = new Setting();
            }

            return View(model);
        }

        // --- Authentication and Session Management ---
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<JsonResult> Login(LoginModel model)
        {
            StatusModel statusModel = new StatusModel() { Status = "Success", RedirectUrl = "" };
            try
            {
                if (ModelState.IsValid && !string.IsNullOrEmpty(model.Username) && !string.IsNullOrEmpty(model.Password))
                {
                    var user = await db.Users.FirstOrDefaultAsync(x => x.User_Phone == model.Username);

                    if (user != null && user.User_Status == 1)
                    {
                        if (string.Equals(user.User_Role, "Admin", StringComparison.OrdinalIgnoreCase) &&
                            user.User_Password == functions.HashPassword(model.Password + user.User_CreatedDate))
                        {
                            Session["User"] = user;
                            SetCookie("UserId", $"{user.User_Id}");
                            SetCookie("Token", functions.GenerateToken());
                            statusModel.RedirectUrl = "/Panel/Index";
                        }
                        else { statusModel.Status = "Wrong"; }
                    }
                    else if (user != null) { statusModel.Status = "Block"; }
                    else { statusModel.Status = "NoExist"; }
                }
                else { statusModel.Status = "Empty"; }
            }
            catch { statusModel.Status = "Error"; }

            return Json(statusModel);
        }

        bool UserSessionExists()
        {
            try
            {
                string tokenFromCookie = GetCookie("Token");
                string userIdFromCookie = GetCookie("UserId");

                if (string.IsNullOrEmpty(tokenFromCookie) || string.IsNullOrEmpty(userIdFromCookie))
                {
                    return false;
                }

                if (!int.TryParse(userIdFromCookie, out int userId))
                {
                    return false;
                }

                var user = db.Users.FirstOrDefault(x => x.User_Id == userId && x.User_Token == tokenFromCookie && x.User_Status == 1);

                if (user != null && user.User_Role != null && string.Equals(user.User_Role.Trim(), "Admin", StringComparison.OrdinalIgnoreCase))
                {
                    Session["User"] = user;
                    return true;
                }
                else
                {
                    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("~/Panel/Logout")]
        public async Task Logout()
        {
            Session.Clear();
            Session.Abandon();
            SetCookie("UserId", "", -1);
            SetCookie("Token", "", -1);
            Response.Redirect("~/Panel/Login");
        }

        [Route("~/Login")]
        [Route("Login")]
        public ActionResult Login(string Return = "")
        {
            ViewBag.Return = Return;
            if (UserSessionExists()) { Response.Redirect("~/panel/Index"); }
            return View();
        }

        [HttpGet]
        public ActionResult Complete(int User, string Token)
        {
            var user = db.Users.FirstOrDefault(u => u.User_Id == User && u.User_Token == Token);
            if (user != null)
            {
                Session["User"] = user;
                SetCookie("UserId", user.User_Id.ToString());
                SetCookie("Token", user.User_Token);
                return new HttpStatusCodeResult(HttpStatusCode.OK);
            }
            return new HttpStatusCodeResult(HttpStatusCode.Unauthorized);
        }

        string SetCookie(string Key, string Value, int ExpireDay = 365)
        {
            var cookie = new HttpCookie(Key, Value)
            {
                Expires = DateTime.Now.AddDays(ExpireDay),
                Path = "/",
                SameSite = SameSiteMode.Lax
            };
            Response.Cookies.Add(cookie);
            return Value;
        }

        string GetCookie(string Key)
        {
            var cookie = Request.Cookies[Key];
            return cookie?.Value ?? string.Empty;
        }

        [HttpPost]
        public async Task<JsonResult> UpdateItem(int id, string newTitle)
        {
            if (!HasSession("ManageItems")) { return Json(new { success = false, message = "Unauthorized" }); }

            if (string.IsNullOrWhiteSpace(newTitle))
            {
                return Json(new { success = false, message = "نام آیتم نمی‌تواند خالی باشد." });
            }

            var item = await db.Items.FindAsync(id);
            if (item != null)
            {
                // بررسی برای جلوگیری از ثبت نام تکراری
                bool exists = await db.Items.AnyAsync(i => i.Item_Title == newTitle && i.Item_Type == item.Item_Type && i.Item_Id != id);
                if (exists)
                {
                    return Json(new { success = false, message = "این نام قبلاً ثبت شده است." });
                }

                item.Item_Title = newTitle;
                await db.SaveChangesAsync();
                return Json(new { success = true });
            }
            return Json(new { success = false, message = "آیتم یافت نشد." });
        }



        public async Task<ActionResult> ClientManagement()
        {
            if (!HasSession("ManageClients")) { return RedirectToAction("Index"); }
            var clients = await db.Clients.ToListAsync();
            return View(clients);
        }

    }
}
