using Azure.Core;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.VisualStudio.Web.CodeGenerators.Mvc.Templates.BlazorIdentity.Pages;
using Mono.TextTemplating;
using Newtonsoft.Json;
using PSTW_CentralSystem.Areas.Inventory.Models;
using PSTW_CentralSystem.DBContext;
using PSTW_CentralSystem.Models;
using System.ComponentModel.Design;
using System.Data;
using System.Diagnostics;
using System.Reflection;
using static System.Collections.Specialized.BitVector32;
using System.Data.SqlClient;

namespace PSTW_CentralSystem.Controllers.API.Inventory
{
    [ApiController]
    [Route("[controller]")]

    public class InvMainAPI : Controller
    {
        private readonly ILogger<InvMainAPI> _logger;
        private readonly CentralSystemContext _centralDbContext;
        private readonly UserManager<UserModel> _userManager;

        public InvMainAPI(ILogger<InvMainAPI> logger, CentralSystemContext centralDbContext, UserManager<UserModel> userManager)
        {
            _logger = logger;
            _centralDbContext = centralDbContext;
            _userManager = userManager;
        }

        public class DepartmentCompany
        {
            public int DepartmentId { get; set; }
            public string? DepartmentName { get; set; }
            public int CompanyId { get; set; }
            public string? CompanyName { get; set; }
            public string? DepartmentCode { get; set; }
        }

        public async Task<List<DepartmentCompany>> GetDepartmentWithCompanyList()
        {
            var departmentList = await _centralDbContext.Departments.ToListAsync();
            var companyList = await _centralDbContext.Companies.ToListAsync();

            // Create a new list to store departments with their company name
            var departmentWithCompanyList = departmentList.Select(department => new DepartmentCompany
            {
                DepartmentId = department.DepartmentId,
                DepartmentName = department.DepartmentName,
                CompanyId = department.CompanyId,
                CompanyName = companyList.FirstOrDefault(company => company.CompanyId == department.CompanyId)?.CompanyName
            }).ToList();

            // Return the constructed list as JSON
            return departmentWithCompanyList;
        }
        public async Task<DepartmentCompany> GetDepartmentWithCompany(int companyId, int departmentId)
        {
            var departmentList = await _centralDbContext.Departments.FirstOrDefaultAsync(d => d.DepartmentId == departmentId );
            var companyList = await _centralDbContext.Companies.FirstOrDefaultAsync(c => c.CompanyId == companyId);

            // Create a new list to store departments with their company name
            var departmentWithCompany = new DepartmentCompany
            {
                DepartmentId = departmentList!.DepartmentId,
                DepartmentName = departmentList.DepartmentName,
                CompanyId = departmentList.CompanyId,
                CompanyName = companyList?.CompanyName,
                DepartmentCode = departmentList.DepartmentCode,
            };

            // Return the constructed list as JSON
            return departmentWithCompany;
        }

        #region Manufacturer

        [HttpPost("ManufacturerList")]
        public async Task<IActionResult> ManufacturerList()
        {
            var manifacturerList = await _centralDbContext.Manufacturers.ToListAsync();
            return Json(manifacturerList);
        }

        [HttpPost("AddManufacturer")]
        public async Task<IActionResult> AddManufacturer([FromBody] ManufacturerModel manufacturer)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            try
            {
                _centralDbContext.Manufacturers.Add(new ManufacturerModel
                {
                    ManufacturerName = manufacturer.ManufacturerName,
                });
                await _centralDbContext.SaveChangesAsync();
                var updatedList = await _centralDbContext.Manufacturers.ToListAsync();
                return Json(updatedList);
            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }
        }

        [HttpPost("EditManufacturer")]
        public async Task<IActionResult> EditManufacturer([FromBody] ManufacturerModel updatedManufacturer)
        {
            if (updatedManufacturer == null || updatedManufacturer.ManufacturerId == 0)
            {
                return BadRequest(new { success = false, message = "Invalid manufacturer data." });
            }

            try
            {
                // Find the existing manufacturer
                var manufacturer = await _centralDbContext.Manufacturers
                    .FirstOrDefaultAsync(m => m.ManufacturerId == updatedManufacturer.ManufacturerId);

                if (manufacturer == null)
                {
                    return NotFound(new { success = false, message = "Manufacturer not found." });
                }

                // Update fields
                manufacturer.ManufacturerName = updatedManufacturer.ManufacturerName;

                // Save changes
                await _centralDbContext.SaveChangesAsync();

                return Ok(new { success = true, message = "Manufacturer updated successfully." });
            }
            catch (Exception ex)
            {
                // Optional: Log the error
                return StatusCode(500, new { success = false, message = "Internal server error: " + ex.Message });
            }
        }


        [HttpDelete("DeleteManufacturer/{id}")]
        public async Task<IActionResult> DeleteManufacturer(int id)
        {
            var manufacturer = await _centralDbContext.Manufacturers.FindAsync(id);
            if (manufacturer == null)
            {
                return NotFound(new { success = false, message = "Manufacturer not found." });
            }

            try
            {
                _centralDbContext.Manufacturers.Remove(manufacturer);
                await _centralDbContext.SaveChangesAsync();

                return Ok(new { success = true, message = "Manufacturer deleted successfully." });
            }
            catch (Microsoft.EntityFrameworkCore.DbUpdateException ex)
            {
                Console.Error.WriteLine($"DbUpdateException: {ex.Message}");
                if (ex.InnerException != null)
                {
                    Console.Error.WriteLine($"Inner Exception: {ex.InnerException.Message}");
                    // Using the newer Microsoft.Data.SqlClient namespace
                    if (ex.InnerException is Microsoft.Data.SqlClient.SqlException sqlEx && sqlEx.Number == 547)
                    {
                        return BadRequest(new { success = false, message = "This manufacturer cannot be deleted as it is associated with other items (e.g., products). Please remove all associated items first." });
                    }
                }
                return BadRequest(new { success = false, message = "This manufacturer cannot be deleted due to existing related data." });
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine($"General Exception: {ex.Message}");
                return StatusCode(500, new { success = false, message = "An error occurred while deleting the manufacturer: " + ex.Message });
            }
        }

        #endregion Manufacturer

        #region Product

        [HttpPost("ProductList")]
        public async Task<IActionResult> ProductList()
        {
            var productList = await _centralDbContext.Products.Include("Manufacturer").ToListAsync();
            return Json(productList);
        }

        [HttpPost("ProductListWithItem")]
        public async Task<IActionResult> ProductListWithItem()
        {
            var productList = await _centralDbContext.Products
                .Include(p => p.Items) // Include related items
                .Include(p => p.Manufacturer) // Include related manufacturer
                .ToListAsync();

            return Json(productList);
        }


        [HttpPost("AddProduct")]
        public async Task<IActionResult> AddProduct([FromBody] ProductModel product)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }
            if (product == null)
            {
                return NotFound("Product is null");
            }

            try
            {
                product.QuantityProduct = 0;
                var productImage = product.ImageProduct; 
                if (!string.IsNullOrEmpty(product.ImageProduct))
                {
                    var bytes = Convert.FromBase64String(product.ImageProduct);
                    var filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/media/inventory/images", product.ModelNo + ".jpg");
                    await System.IO.File.WriteAllBytesAsync(filePath, bytes);
                    product.ImageProduct = "/media/inventory/images/" + product.ModelNo + ".jpg";
                }
                _centralDbContext.Products.Add(product);
                await _centralDbContext.SaveChangesAsync();
                var updatedList = await _centralDbContext.Products.Include("Manufacturer").Where(x => x.ManufacturerId == x.ManufacturerId).ToListAsync();
                return Json(updatedList);
            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }
        }

        [HttpPost("EditProduct")]
        public async Task<IActionResult> EditProduct([FromBody] ProductModel editedProduct)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }
            var product = await _centralDbContext.Products.FindAsync(editedProduct.ProductId);
            if (product == null)
            {
                return NotFound("Product is null");
            }

            try
            {
                var productImage = editedProduct.ImageProduct; // Save image to wwwroot/media/inventory/images | Images name is product.ModelNo | product.ImageProduct is in base64 string
                if (product.ImageProduct != editedProduct.ImageProduct)
                {
                    var bytes = Convert.FromBase64String(editedProduct.ImageProduct);
                    var filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/media/inventory/images", editedProduct.ModelNo + ".jpg");
                    await System.IO.File.WriteAllBytesAsync(filePath, bytes);
                    editedProduct.ImageProduct = "/media/inventory/images/" + editedProduct.ModelNo + ".jpg";
                }

                product.ProductName = editedProduct.ProductName;
                product.ProductShortName = editedProduct.ProductShortName;
                product.ManufacturerId = editedProduct.ManufacturerId;
                product.Category = editedProduct.Category;
                product.ModelNo = editedProduct.ModelNo;
                product.ImageProduct = editedProduct.ImageProduct;


                _centralDbContext.Products.Update(product);
                await _centralDbContext.SaveChangesAsync();

                var updatedList = await _centralDbContext.Products.Include("Manufacturer").Where(x => x.ManufacturerId == x.ManufacturerId).ToListAsync();
                return Json(updatedList);
            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }
        }

        [HttpDelete("DeleteProduct/{id}")]
        public async Task<IActionResult> DeleteProduct(int id)
        {
            var Product = await _centralDbContext.Products.FindAsync(id);
            if (Product == null)
            {
                return NotFound(new { success = false, message = "Product not found" });
            }

            _centralDbContext.Products.Remove(Product);
            await _centralDbContext.SaveChangesAsync();

            return Ok(new { success = true, message = "Product deleted successfully" });
        }

        #endregion Product

        #region Supplier

        [HttpPost("SupplierList")]
        public async Task<IActionResult> SupplierList()
        {
            var supplierList = await _centralDbContext.Suppliers.ToListAsync();
            return Json(supplierList);
        }

        [HttpPost("AddSupplier")]
        public async Task<IActionResult> AddSupplier([FromBody] SupplierModel supplier)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            try
            {
                _centralDbContext.Suppliers.Add(supplier);
                await _centralDbContext.SaveChangesAsync();
                var updatedList = await _centralDbContext.Suppliers.ToListAsync();
                return Json(updatedList);
            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }
        }

        [HttpPost("EditSupplier")]
        public async Task<IActionResult> EditSupplier([FromBody] SupplierModel editedSupplier)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }
            var supplier = await _centralDbContext.Suppliers.FindAsync(editedSupplier.SupplierId);
            if (supplier == null)
            {
                return NotFound("Supplier is null");
            }

            try
            {
                supplier.SupplierCompName = editedSupplier.SupplierCompName;
                supplier.SupplierAddress = editedSupplier.SupplierAddress;
                supplier.SupplierPIC = editedSupplier.SupplierPIC;
                supplier.SupplierEmail = editedSupplier.SupplierEmail;
                supplier.SupplierPhoneNo = editedSupplier.SupplierPhoneNo;



                _centralDbContext.Suppliers.Update(supplier);
                await _centralDbContext.SaveChangesAsync();

                return Json(supplier);
            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }
        }

        [HttpDelete("DeleteSupplier/{id}")]
        public async Task<IActionResult> DeleteSupplier(int id)
        {
            var supplier = await _centralDbContext.Suppliers.FindAsync(id);
            if (supplier == null)
            {
                return NotFound(new { success = false, message = "Supplier not found" });
            }

            _centralDbContext.Suppliers.Remove(supplier);
            await _centralDbContext.SaveChangesAsync();

            return Ok(new { success = true, message = "Supplier deleted successfully" });
        }
        #endregion Supplier


        #region Item

        [HttpPost("ItemList")]
        public async Task<IActionResult> ItemList()
        {
            try
            {
                var user = await _userManager.GetUserAsync(User);
                if (user == null)
                {
                    return BadRequest("User not found");
                }
                else
                {
                    user.departmentId = user.departmentId != null ? user.departmentId : 0;
                }

                var userRole = await _userManager.GetRolesAsync(user);
                var isAdmin = userRole.Contains("SystemAdmin") || userRole.Contains("SuperAdmin") || userRole.Contains("Finance");
                List<ItemModel> itemList = new List<ItemModel>();

                // Get the item list
                if (isAdmin)
                {
                    itemList = await _centralDbContext.Items
                        .AsNoTracking()
                        .Include("CreatedBy")
                        .Include("Department")
                        .Include("Product")
                        .Include(i => i.Movement)
                        .ThenInclude(m => m!.FromStore)
                        .Include(i => i.Movement)
                        .ThenInclude(m => m!.FromStation)
                        .Include(i => i.Movement)
                        .ThenInclude(m => m!.FromUser)
                        .ToListAsync();
                }
                else
                {
                    itemList = await _centralDbContext.Items
                        .AsNoTracking()
                        .Include("CreatedBy")
                        .Include("Department")
                        .Include("Product")
                        .Include(i => i.Movement)
                        .ThenInclude(m => m!.FromStore)
                        .Include(i => i.Movement)
                        .ThenInclude(m => m!.FromStation)
                        .Include(i => i.Movement)
                        .ThenInclude(m => m!.FromUser)
                        .Where(i => i.DepartmentId == user.departmentId)
                        .ToListAsync();

                }

                // Get the departments list (DepartmentId references Departments)
                var departments = await _centralDbContext.Departments.ToListAsync();

                // Now join items with users and departments manually
                var itemListWithDetails = itemList.Select(item => new
                {
                    // Add CreatedDate and ModifiedDate here for the response
                    item.CreatedDate, // Include CreatedDate
                    item.ModifiedDate, // Include ModifiedDate
                    item.ItemID,
                    item.UniqueID,
                    item.CompanyId,
                    item.DepartmentId,
                    item.ProductId,
                    item.SerialNumber,
                    item.Quantity,
                    item.Supplier,
                    PurchaseDate = item.PurchaseDate.ToString("dd/MM/yyyy"),
                    item.PONo,
                    item.DONo,
                    item.Currency,
                    item.InvoiceNo,
                    item.TeamType,
                    item.DefaultPrice,
                    item.CurrencyRate,
                    item.ConvertPrice,
                    item.DODate,
                    item.Warranty,
                    item.PartNumber,
                    EndWDate = item.EndWDate.ToString("dd/MM/yyyy"),
                    InvoiceDate = item.InvoiceDate?.ToString("dd/MM/yyyy"),
                    item.Department?.DepartmentName,
                    CreatedBy = item.CreatedBy!.UserName,
                    item.Product!.ProductName,
                    item.Product!.ProductShortName,
                    item.Product!.Category,
                    FromUser = item.Movement?.ToUser,
                    FromStore = item.Movement?.ToStore,
                    FromStation = item.Movement?.ToStation,
                    CurrentUser = item.Movement?.FromUser?.UserName,
                    CurrentStore = item.Movement?.FromStore?.StoreName,
                    CurrentStation = item.Movement?.FromStation?.StationName,
                    QRString = $"{HttpContext.Request.Scheme}://{HttpContext.Request.Host.Value}/I/{item.UniqueID}" // Generate QR String
                }).ToList();

                return Json(itemListWithDetails);
            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }
        }

        [HttpPost("GenerateItemQr/{id}")]
        public IActionResult GenerateItemQr(string id)
        {
            // Retrieve the request's host and scheme
            var request = HttpContext.Request;
            string domain = $"{request.Scheme}://{request.Host.Value}";

            // Append the QR path and item ID
            string QRString = $"{domain}/Inventory/ItemInformation/{id}";
            return Json(QRString);
        }

        [HttpPost("AddItem")]
        public async Task<IActionResult> AddItem([FromBody] ItemModel item)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            try
            {
                var product = await _centralDbContext.Products.FirstOrDefaultAsync(p => p.ProductId == item.ProductId) ?? throw new Exception("Product not found");
                var inventoryMaster = await _centralDbContext.InventoryMasters.Include("User").FirstOrDefaultAsync(i => i.UserId == item.CreatedByUserId) ?? new InventoryMasterModel { UserId = item.CreatedByUserId };

                if (product.Category == "Disposable")
                {
                    product.QuantityProduct += item.Quantity;
                    item.SerialNumber = null;
                }
                else if (product.Category == "Asset" || product.Category == "Part")
                {
                    product.QuantityProduct = (product.QuantityProduct ?? 0) + 1;
                    item.Quantity = 1;
                }

                // Set CreatedDate when adding a new item
                item.CreatedDate = DateTime.Now;
                // Explicitly set ModifiedDate to null for a new item
                item.ModifiedDate = null; // <--- CHANGE IS HERE

                _centralDbContext.Items.Add(item);
                _centralDbContext.Products.Update(product);

                await _centralDbContext.SaveChangesAsync();

                ItemMovementModel itemMovement = new ItemMovementModel
                {
                    ItemId = item.ItemID,
                    ToUser = inventoryMaster.UserId,
                    ToStore = inventoryMaster.StoreId,
                    LastStore = inventoryMaster.StoreId,
                    LastUser = inventoryMaster.UserId,
                    LatestStatus = "Ready To Deploy",
                    Quantity = item.Quantity,
                    Action = "Register",
                    Date = DateTime.Now,
                    MovementComplete = true,
                };

                _centralDbContext.ItemMovements.Add(itemMovement);
                await _centralDbContext.SaveChangesAsync();

                var savedItem = await _centralDbContext.Items.FirstOrDefaultAsync(i => i.ItemID == item.ItemID);
                var savedMovement = await _centralDbContext.ItemMovements.FirstOrDefaultAsync(im => im.Id == itemMovement.Id);

                if (savedItem != null)
                {
                    var companyDepartment = await GetDepartmentWithCompany(item.CompanyId, item.DepartmentId);
                    var itemProduct = _centralDbContext.Products.Where(p => p.ProductId == item.ProductId).FirstOrDefault();

                    string? companyInitial = companyDepartment!.CompanyName?.ToString().Substring(0, 1).ToUpper();
                    string? departmentInitial = companyDepartment!.DepartmentName?.ToString().Substring(0, 1).ToUpper();
                    string? deptCode = companyDepartment!.DepartmentCode?.ToString();
                    char? initialCategory = itemProduct!.Category.ToString().Substring(0, 1).ToUpper().FirstOrDefault();
                    string? productId = itemProduct!.ProductId.ToString("D3");
                    string? itemIdString = item.ItemID.ToString("D5");
                    var uniqueId = $"{deptCode}{initialCategory}{productId}{itemIdString}".ToUpper();
                    savedItem.UniqueID = uniqueId;
                    savedItem.MovementId = savedMovement?.Id;

                    _centralDbContext.Items.Update(savedItem);
                    await _centralDbContext.SaveChangesAsync();
                }

                var updatedItem = new
                {
                    savedItem!.ItemID,
                    savedItem.UniqueID,
                    savedItem.CompanyId,
                    savedItem.DepartmentId,
                    savedItem.ProductId,
                    savedItem.SerialNumber,
                    savedItem.Quantity,
                    savedItem.Supplier,
                    savedItem.PurchaseDate,
                    savedItem.PONo,
                    savedItem.Currency,
                    savedItem.DefaultPrice,
                    savedItem.CurrencyRate,
                    savedItem.ConvertPrice,
                    savedItem.DODate,
                    savedItem.Warranty,
                    savedItem.EndWDate,
                    savedItem.InvoiceDate,
                    savedItem.PartNumber,
                    savedItem.CreatedDate,
                    savedItem.ModifiedDate // This will now be null for new items
                };
                return Json(updatedItem);
            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }
        }


        [HttpPost("EditItem")]
        public async Task<IActionResult> EditItem([FromBody] ItemModel item)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            try
            {
                var savedItem = await _centralDbContext.Items
                                                 .Include(i => i.Product)
                                                 .FirstOrDefaultAsync(i => i.ItemID == item.ItemID);
                if (savedItem == null)
                {
                    return NotFound(new { success = false, message = "Item not found" });
                }

                var oldProduct = savedItem.Product;
                var newProduct = await _centralDbContext.Products.FirstOrDefaultAsync(p => p.ProductId == item.ProductId) ?? throw new Exception("New Product not found");

                // Quantity adjustment logic based on category changes
                if (oldProduct?.Category == "Disposable" && newProduct.Category == "Disposable")
                {
                    int quantityDifference = item.Quantity - savedItem.Quantity;
                    newProduct.QuantityProduct += quantityDifference;
                }
                else if ((oldProduct?.Category == "Asset" || oldProduct?.Category == "Part") && newProduct.Category == "Disposable")
                {
                    if (oldProduct != null && oldProduct.QuantityProduct > 0)
                    {
                        oldProduct.QuantityProduct = (oldProduct.QuantityProduct ?? 0) - 1;
                        _centralDbContext.Products.Update(oldProduct);
                    }
                    newProduct.QuantityProduct += item.Quantity;
                }
                else if (oldProduct?.Category == "Disposable" && (newProduct.Category == "Asset" || newProduct.Category == "Part"))
                {
                    if (oldProduct != null)
                    {
                        oldProduct.QuantityProduct = (oldProduct.QuantityProduct ?? 0) - savedItem.Quantity;
                        if (oldProduct.QuantityProduct < 0) oldProduct.QuantityProduct = 0;
                        _centralDbContext.Products.Update(oldProduct);
                    }
                    newProduct.QuantityProduct = (newProduct.QuantityProduct ?? 0) + 1;
                    item.Quantity = 1;
                }
                else if ((oldProduct?.Category == "Asset" || oldProduct?.Category == "Part") && (newProduct.Category == "Asset" || newProduct.Category == "Part"))
                {
                    if (savedItem.ProductId != item.ProductId)
                    {
                        if (oldProduct != null && oldProduct.QuantityProduct > 0)
                        {
                            oldProduct.QuantityProduct = (oldProduct.QuantityProduct ?? 0) - 1;
                            _centralDbContext.Products.Update(oldProduct);
                        }
                        newProduct.QuantityProduct = (newProduct.QuantityProduct ?? 0) + 1;
                    }
                    item.Quantity = 1;
                }

                // Handle serial number based on the new product's category
                if (newProduct.Category == "Disposable")
                {
                    item.SerialNumber = null;
                }

                // Update savedItem properties from item model
                savedItem.DefaultPrice = item.DefaultPrice;
                savedItem.CompanyId = item.CompanyId;
                savedItem.DepartmentId = item.DepartmentId;
                savedItem.ProductId = item.ProductId;
                savedItem.SerialNumber = item.SerialNumber;
                savedItem.TeamType = item.TeamType;
                savedItem.Quantity = item.Quantity;
                savedItem.Supplier = item.Supplier;
                savedItem.PurchaseDate = item.PurchaseDate;
                savedItem.PONo = item.PONo;
                savedItem.Currency = item.Currency;
                savedItem.CurrencyRate = item.CurrencyRate;
                savedItem.ConvertPrice = item.ConvertPrice;
                savedItem.DONo = item.DONo;
                savedItem.DODate = item.DODate;
                savedItem.Warranty = item.Warranty;
                savedItem.EndWDate = item.EndWDate;
                savedItem.InvoiceNo = item.InvoiceNo;
                savedItem.InvoiceDate = item.InvoiceDate;
                savedItem.PartNumber = item.PartNumber;

                // Set ModifiedDate when editing an item
                savedItem.ModifiedDate = DateTime.Now;

                // Re-generate UniqueID based on updated fields (if PartNumber is part of it)
                var companyDepartment = await GetDepartmentWithCompany(savedItem.CompanyId, savedItem.DepartmentId);
                string? deptCode = companyDepartment!.DepartmentCode?.ToString();
                char? initialCategory = newProduct!.Category.ToString().Substring(0, 1).ToUpper().FirstOrDefault();
                string? productId = newProduct!.ProductId.ToString("D3");
                string? itemIdString = savedItem.ItemID.ToString("D5");
                savedItem.UniqueID = $"{deptCode}{initialCategory}{productId}{itemIdString}".ToUpper();

                _centralDbContext.Products.Update(newProduct);
                _centralDbContext.Items.Update(savedItem);

                await _centralDbContext.SaveChangesAsync();

                var updatedItem = new
                {
                    savedItem!.ItemID,
                    savedItem.UniqueID,
                    savedItem.CompanyId,
                    savedItem.DepartmentId,
                    savedItem.ProductId,
                    savedItem.SerialNumber,
                    savedItem.Quantity,
                    savedItem.Supplier,
                    savedItem.PurchaseDate,
                    savedItem.PONo,
                    savedItem.Currency,
                    savedItem.DefaultPrice,
                    savedItem.CurrencyRate,
                    savedItem.ConvertPrice,
                    savedItem.DODate,
                    savedItem.Warranty,
                    savedItem.EndWDate,
                    savedItem.InvoiceDate,
                    savedItem.PartNumber,
                    savedItem.CreatedDate, // Include in response
                    savedItem.ModifiedDate // Include in response
                };
                return Json(updatedItem);
            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }
        }

        [HttpDelete("DeleteItem/{id}")]
        public async Task<IActionResult> DeleteItem(int id)
        {
            var item = await _centralDbContext.Items.FindAsync(id);
            if (item == null)
            {
                return NotFound(new { success = false, message = "Item not found" });
            }

            var products = _centralDbContext.Products
                .FirstOrDefault(i => i.ProductId == item.ProductId);

            products.QuantityProduct = products.QuantityProduct - item.Quantity;

            // Get related item movements
            var itemMovements = await _centralDbContext.ItemMovements
                .Where(i => i.ItemId == item.ItemID)
                .ToListAsync();

            // Remove all related item movements
            if (itemMovements.Any())
            {
                _centralDbContext.ItemMovements.RemoveRange(itemMovements);
                await _centralDbContext.SaveChangesAsync();
            }

            //Handle Rules kalau itemMovement dia xde kat store

            _centralDbContext.Products.Update(products);

            // Remove the item itself
            _centralDbContext.Items.Remove(item);
            await _centralDbContext.SaveChangesAsync();

            return Ok(new { success = true, message = "Item deleted successfully" });
        }


        [HttpPost("GetItem/{id}")] // Endpoint to retrieve an item by its ID
        public async Task<IActionResult> GetItem(string id)
        {
            var item = await _centralDbContext.Items
                                        .Include("CreatedBy")
                                        .Include("Department")
                                        .Include("Product")
                                        .Include("Movement")
                                        .Include(i => i.Movement)
                                        .ThenInclude(m => m!.FromStore)
                                        .Include(i => i.Movement)
                                        .ThenInclude(m => m!.FromStation)
                                        .Include(i => i.Movement)
                                        .ThenInclude(m => m!.FromUser)
                                        .Include(i => i.Movement)
                                        .ThenInclude(m => m!.NextStore)
                                        .Include(i => i.Movement)
                                        .ThenInclude(m => m!.NextStation)
                                        .Include(i => i.Movement)
                                        .ThenInclude(m => m!.NextUser).FirstOrDefaultAsync(i => i.UniqueID == id);
            if (item == null)
            {
                return NotFound(new { success = false, message = "Item not found" });
            }
            var singleItem = new
            {
                item.Movement?.Id,
                item.ItemID,
                item.MovementId,
                item.UniqueID,
                item.CompanyId,
                item.DepartmentId,
                item.ProductId,
                item.SerialNumber,
                item.Quantity,
                item.Supplier,
                PurchaseDate = item.PurchaseDate.ToString("dd/MM/yyyy"),
                item.PONo,
                item.Currency,
                item.DefaultPrice,
                item.CurrencyRate,
                item.ConvertPrice,
                item.DODate,
                item.Warranty,
                item.PartNumber,
                EndWDate = item.EndWDate.ToString("dd/MM/yyyy"),
                InvoiceDate = item.InvoiceDate?.ToString("dd/MM/yyyy"),
                item.Department?.DepartmentName,
                item.CreatedBy!.UserName,
                item.Product!.ProductName,
                item.Product!.ProductShortName,
                item.Product!.ImageProduct,
                Category = item.Product!.Category,
                CurrentUser = item.Movement?.FromUser?.UserName,
                CurrentUserFullName = item.Movement?.FromUser?.FullName,
                CurrentUserId = item.Movement?.FromUser?.Id,
                CurrentStore = item.Movement?.FromStore?.StoreName,
                CurrentStoreId = item.Movement?.FromStore?.Id,
                CurrentStation = item.Movement?.FromStation?.StationName,
                CurrentStationId = item.Movement?.FromStation?.StationId,
                ToUser = item.Movement?.ToUser,
                ToUserName = item.Movement?.NextUser?.UserName,
                ToStore = item.Movement?.ToStore,
                ToStoreName = item.Movement?.NextStore?.StoreName,
                ToStation = item.Movement?.ToStation,
                ToStationName = item.Movement?.NextStation?.StationName,
                item.Movement?.ToOther,
                item.Movement?.LatestStatus,
                item.Movement?.LastUser,
                item.Movement?.LastStore,
                item.Movement?.MovementComplete,
                remark = item.Movement?.Remark,
                QRString = $"{HttpContext.Request.Scheme}://{HttpContext.Request.Host.Value}/I/{item.UniqueID}", // Generate QR String
                item.CreatedDate, // Include in response
                item.ModifiedDate // Include in response
            };
            return Json(singleItem);
        }

        #endregion Item

        #region ItemMovement

        [HttpPost("ItemMovementList")]
        public async Task<IActionResult> ItemMovementList()
        {

            var itemMovementList = await _centralDbContext.ItemMovements
                                        .Include(i => i.Item)
                                        .ThenInclude(i => i.Product)
                                        .Include(i => i.FromStore)
                                        .Include(i => i.FromStation)
                                        .Include(i => i.FromUser)
                                        .Include(i => i.NextStore)
                                        .Include(i => i.NextStation)
                                        .Include(i => i.NextUser)
                                        .Include(i => i.NextUser)
                                        .ToListAsync();

            // if use qr, need to use this. else do simple return json. datatable qr will read dom and replace element with id=qr{qrstring} with qr image.
            // then need dynamic numbering for qr even if item movement is repeated by the same item
            //int itemrow = 0;
            //var itemMovementListWithQR = itemMovementList.Select(item => new
            //{
            //    id = itemrow++,
            //    item, // Includes all properties of the original item
            //    QRString = $"{HttpContext.Request.Scheme}://{HttpContext.Request.Host.Value}/I/{item.ItemId}", // Generate QR String
            //    ProductName = item.Item?.Product?.ProductName,
            //    toUserName = item.NextUser?.FullName,
            //    lastUserName = item.FromUser?.FullName
            //}).ToList();
            //Console.WriteLine(Json(itemMovementListWithQR));


            return Json(itemMovementList.Select(i => new
            {
                i.Id,
                i.ItemId,
                i.ToStation,
                i.ToStore,
                i.ToUser,
                UniqueID = i.Item?.UniqueID,
                ProductName = i.Item?.Product?.ProductName,
                ProductCategory = i.Item?.Product?.Category,
                LastUserName = i.FromUser?.FullName,
                LastStoreName = i.FromStore?.StoreName,
                LastStationName = i.FromStation?.StationName,
                ToUserName = i.NextUser?.FullName,
                ToStoreName = i.NextStore?.StoreName,
                ToStationName = i.NextStation?.StationName,
                ProductImage = i.Item?.Product?.ImageProduct,
                i.ToOther,
                i.sendDate,
                i.Action,
                i.Quantity,
                i.Remark,
                i.ConsignmentNote,
                i.Date,
                i.LastUser,
                i.LastStore,
                i.LastStation,
                i.LatestStatus,
                i.receiveDate,
                i.MovementComplete
            }));
        }

        [HttpPost("AddItemMovement")]
        public async Task<IActionResult> AddItemMovement([FromBody] ItemMovementModel itemmovement)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            try
            {
                var inventoryMaster = await _centralDbContext.InventoryMasters.Include("User").FirstOrDefaultAsync(i => i.UserId == itemmovement.ToUser);
                if (inventoryMaster != null)
                {
                    itemmovement.ToStore = inventoryMaster.StoreId;
                }


                if (!string.IsNullOrEmpty(itemmovement.ConsignmentNote))
                {
                    var bytes = Convert.FromBase64String(itemmovement.ConsignmentNote);
                    string filePath = "";

                    string uniqueName = $"{itemmovement.ItemId}_{Guid.NewGuid()}";

                    if (IsImage(bytes))
                    {
                        filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/media/inventory/itemmovement", uniqueName + itemmovement.ItemId + "_Request.jpg");
                        itemmovement.ConsignmentNote = "/media/inventory/itemmovement/" + uniqueName + itemmovement.ItemId + "_Request.jpg";
                    }
                    else if (IsPdf(bytes))
                    {
                        filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/media/inventory/itemmovement", uniqueName + itemmovement.ItemId + "_Request.pdf");
                        itemmovement.ConsignmentNote = "/media/inventory/itemmovement/" + uniqueName + itemmovement.ItemId + "_Request.pdf";
                    }
                    else
                    {
                        return BadRequest("Unsupported file format.");
                    }

                    await System.IO.File.WriteAllBytesAsync(filePath, bytes);
                }

                _centralDbContext.ItemMovements.Add(itemmovement);

                await _centralDbContext.SaveChangesAsync(); // This generates the auto-incremented ItemID 

                var updateItem = await _centralDbContext.Items.FindAsync(itemmovement.ItemId); //only access after it have its own itemmovent  

                if (updateItem != null)
                {
                    if (itemmovement.ToOther == "On Delivery")
                    {
                        updateItem.ItemStatus = 2;
                    }
                    else if (itemmovement.ToOther == "Repair" || itemmovement.ToOther == "Calibration")
                    {
                        updateItem.ItemStatus = 4;
                    }
                    else if (itemmovement.ToOther == "Faulty")
                    {
                        updateItem.ItemStatus = 8;
                    }
                    // Handle quantity update for disposable items here
                    // This is crucial: if it's a disposable item, decrement the Item's Quantity
                    // You'll need to fetch the Product to know if it's Disposable
                    var product = await _centralDbContext.Products.FindAsync(updateItem.ProductId);
                    if (product != null && product.Category == "Disposable" && itemmovement.Quantity.HasValue)
                    {
                        updateItem.Quantity -= itemmovement.Quantity.Value;
                        if (updateItem.Quantity < 0)
                        {
                            updateItem.Quantity = 0; // Prevent negative quantity
                        }
                    }


                    updateItem.MovementId = itemmovement.Id;
                    _centralDbContext.Items.Update(updateItem);
                    await _centralDbContext.SaveChangesAsync(); // save changes for table item - movementid 


                }
                return Json(new
                {
                    itemmovement.Id,
                    itemmovement.ItemId,
                    itemmovement.ToStation,
                    itemmovement.ToStore,
                    itemmovement.ToUser,
                    itemmovement.ToOther,
                    itemmovement.sendDate,
                    itemmovement.Action,
                    itemmovement.Quantity,
                    itemmovement.Remark,
                    itemmovement.ConsignmentNote,
                    itemmovement.Date,
                    itemmovement.LastUser,
                    itemmovement.LastStore,
                    itemmovement.LastStation,
                    itemmovement.LatestStatus,
                    itemmovement.receiveDate,
                    itemmovement.MovementComplete
                });

            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }

        }

        [HttpPost("UpdateItemMovementMaster")]
        public async Task<IActionResult> UpdateItemMovementMaster([FromBody] ItemMovementModel receiveMovement)
        {

            try
            {

                var updatedList = await _centralDbContext.ItemMovements.FindAsync(receiveMovement.Id);

                if (updatedList == null)
                {
                    return NotFound("Item movement record not found.");
                }

                updatedList.LastUser = receiveMovement.LastUser;
                updatedList.LatestStatus = receiveMovement.LatestStatus;
                updatedList.receiveDate = receiveMovement.receiveDate;
                updatedList.Remark = receiveMovement.Remark;
                updatedList.MovementComplete = true;

                _centralDbContext.ItemMovements.Update(updatedList);
                await _centralDbContext.SaveChangesAsync();

                //var receiveItems = await _centralDbContext.Items.FindAsync(receiveMovement.ItemId);

                //if (receiveItems != null)
                //{
                //    receiveItems.ItemStatus = 3;
                //    _centralDbContext.Items.Update(receiveItems);

                //    await _centralDbContext.SaveChangesAsync(); // Simpan perubahan
                //}

                return Json(updatedList);
            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }
        }

        [HttpPost("UpdateItemQuantity")]
        public async Task<IActionResult> UpdateItemQuantity([FromBody] ItemQuantityUpdateModel model)
        {
            try
            {
                // Find the item
                var item = await _centralDbContext.Items
                    .Include(i => i.Product) // Include product for category check
                    .FirstOrDefaultAsync(i => i.ItemID == model.ItemId);

                if (item == null)
                {
                    return NotFound("Item not found.");
                }

                // Only process if it's a disposable item
                if (item.Product?.Category == "Disposable")
                {
                    // Get the original movement to find the exact quantity that was assigned
                    var originalMovement = await _centralDbContext.ItemMovements
                        .FirstOrDefaultAsync(m => m.Id == model.MovementId);

                    if (originalMovement == null)
                    {
                        return BadRequest("Original movement record not found.");
                    }

                    // The quantity to return is the original movement's quantity
                    var quantityToReturn = originalMovement.Quantity ?? 1;

                    // Update the item quantity by adding back the assigned amount
                    item.Quantity += quantityToReturn;

                    // Ensure quantity doesn't go negative (just in case)
                    if (item.Quantity < 0)
                    {
                        item.Quantity = 0;
                    }

                    _centralDbContext.Items.Update(item);
                    await _centralDbContext.SaveChangesAsync();

                    return Ok(new
                    {
                        item.ItemID,
                        OriginalQuantity = originalMovement.Quantity,
                        NewQuantity = item.Quantity,
                        Message = $"Successfully returned {quantityToReturn} to item quantity"
                    });
                }

                // For non-disposable items, just return success without changing quantity
                return Ok(new
                {
                    item.ItemID,
                    Message = "No quantity change - item is not disposable"
                });
            }
            catch (Exception ex)
            {
                return BadRequest($"Error updating item quantity: {ex.Message}");
            }
        }

        [HttpGet("GetItemMovementById")]
        public async Task<IActionResult> GetItemMovementById(int id)
        {
            try
            {
                var itemMovement = await _centralDbContext.ItemMovements.FindAsync(id);

                if (itemMovement == null)
                {
                    return NotFound("Item movement record not found.");
                }

                return Ok(itemMovement);
            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }
        }
        #endregion ItemMovement

        #region ItemMovementUser

        [HttpPost("ItemMovementUser")]
        public async Task<IActionResult> ItemMovementUser()
        {
            try
            {
                var user = await _userManager.GetUserAsync(User);
                if (user == null)
                {
                    return NotFound("Item movement record not found.");
                }

                var itemMovementUser = await _centralDbContext.ItemMovements
                                        .Include(i => i.Item)
                                        .ThenInclude(i => i.Product)
                                        .Include(i => i.FromStore)
                                        .Include(i => i.FromStation)
                                        .Include(i => i.FromUser)
                                        .Include(i => i.NextStore)
                                        .Include(i => i.NextStation)
                                        .Include(i => i.NextUser)
                                        .Where(i => i.ToUser == user.Id || i.LastUser == user.Id)
                                        .ToListAsync();

                return Json(itemMovementUser.Select(i => new
                    {
                        i.Id,
                        i.ItemId,
                        i.ToStation,
                        i.ToStore,
                        i.ToUser,
                        UniqueID = i.Item?.UniqueID,
                        ProductName = i.Item?.Product?.ProductName,
                        ProductImage = i.Item?.Product?.ImageProduct,
                        LastUserName = i.FromUser?.FullName,
                        LastStoreName = i.FromStore?.StoreName,
                        LastStationName = i.FromStation?.StationName,
                        ToUserName = i.NextUser?.FullName,
                        ToStoreName = i.NextStore?.StoreName,
                        ToStationName = i.NextStation?.StationName,
                        i.ToOther,
                        i.sendDate,
                        i.Action,
                        i.Quantity,
                        i.Remark,
                        i.ConsignmentNote,
                        i.Date,
                        i.LastUser,
                        i.LastStore,
                        i.LastStation,
                        i.LatestStatus,
                        i.receiveDate,
                        i.MovementComplete
                    }));
            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }

        }
        #endregion

        #region ItemRequestUser
        [HttpPost("AddRequest")]
        public async Task<IActionResult> AddRequest([FromBody] RequestModel request)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }
            try
            {
                var findUniqueCode = _centralDbContext.Products.FirstOrDefault(r => r.ProductId == request.ProductId);
                var findUniqueUser = _centralDbContext.Users.FirstOrDefault(r => r.Id == request.UserId);

                if (!string.IsNullOrEmpty(request.Document))
                {

                    var bytes = Convert.FromBase64String(request.Document);
                    string filePath = "";

                    var uniqueAbjad = new string(Enumerable.Range(0, 8).Select(_ => "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"[new Random().Next(36)]).ToArray());


                    if (IsImage(bytes))
                    {
                        filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/media/inventory/request", findUniqueUser.FullName + " " + findUniqueCode.ModelNo + "(" + uniqueAbjad + ") Request.jpg");
                        request.Document = "/media/inventory/request/" + findUniqueUser.FullName + " " + findUniqueCode.ModelNo + "(" + uniqueAbjad + ") Request.jpg";
                    }
                    else if (IsPdf(bytes))
                    {
                        filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/media/inventory/request", findUniqueUser.FullName + " " + findUniqueCode.ModelNo + "_Request.pdf");
                        request.Document = "/media/inventory/request/" + findUniqueUser.FullName + " " + findUniqueCode.ModelNo + "(" + uniqueAbjad + ") Request.pdf";
                    }
                    else
                    {
                        return BadRequest("Unsupported file format.");
                    }

                    await System.IO.File.WriteAllBytesAsync(filePath, bytes);
                }

                _centralDbContext.Requests.Add(request);
                await _centralDbContext.SaveChangesAsync();

                var updatedList = await _centralDbContext.Requests
                                        .Where(r => r.UserId == request.UserId)
                                        .ToListAsync();

                return Json(updatedList.Select(i => new
                {
                    i.ProductId,
                    i.UserId,
                    i.status,
                    i.StationId,
                    i.RequestQuantity,
                    i.requestDate,
                    i.ProductCategory,
                    i.Document,
                    i.approvalDate,
                    i.remarkMasterInv,
                    i.remarkUser,
                }));
            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }
        }
        private bool IsImage(byte[] bytes)
        {
            // JPEG file signature: FF D8 FF
            if (bytes.Length > 2 && bytes[0] == 0xFF && bytes[1] == 0xD8 && bytes[2] == 0xFF)
                return true;

            // PNG file signature: 89 50 4E 47 0D 0A 1A 0A
            if (bytes.Length > 7 && bytes[0] == 0x89 && bytes[1] == 0x50 && bytes[2] == 0x4E && bytes[3] == 0x47)
                return true;

            // GIF file signature: GIF87a or GIF89a
            if (bytes.Length > 5 && bytes[0] == 0x47 && bytes[1] == 0x49 && bytes[2] == 0x46)
                return true;

            return false;
        }

        private bool IsPdf(byte[] bytes)
        {
            // PDF file signature: 25 50 44 46 (ASCII for "%PDF")
            return bytes.Length > 3 && bytes[0] == 0x25 && bytes[1] == 0x50 && bytes[2] == 0x44 && bytes[3] == 0x46;
        }

        [HttpGet("ItemRequestListEachUser/{userId}")]
        public async Task<IActionResult> ItemRequestListEachUser(int userId)
        {
            var requests = await _centralDbContext.Requests
                .Include(i => i.Product).Include(i => i.Station).Where(r => r.UserId == userId).ToListAsync();

            return Json(requests.Select(i => new
            {
                i.requestID,
                i.ProductId,
                productName = i.Product?.ProductName,
                productPicture = i.Product?.ImageProduct,
                i.UserId,
                i.status,
                i.StationId,
                stationName = i.Station?.StationName,
                i.RequestQuantity,
                i.requestDate,
                i.ProductCategory,
                i.Document,
                i.approvalDate,
                i.remarkMasterInv,
                i.remarkUser,
            }));
        }

        [HttpDelete("DeleteRequest/{requestId}")]
        public async Task<IActionResult> DeleteRequest(int requestId)
        {
            var requestApprove = _centralDbContext.Requests.FirstOrDefault(r => r.requestID == requestId && r.approvalDate != null);
            var requestDelete = _centralDbContext.Requests.FirstOrDefault(r => r.requestID == requestId);
            
            if (requestApprove != null)
            {
                return NotFound(new { success = false, message = "Request not found Or Admin Already Approve or Reject" });
            }

            if (requestDelete == null)
            {
                return NotFound(new { success = false, message = "Request not found" });
            }

            _centralDbContext.Requests.Remove(requestDelete);
            await _centralDbContext.SaveChangesAsync();

            return Ok(new { success = true, message = "Request deleted successfully" });
        }

        #endregion

        #region ItemRequestAdmin

        [HttpPost("AddRequestMaster")]
        public async Task<IActionResult> AddRequestMaster([FromBody] RequestModel request)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }
            try
            {
                var findUniqueCode = _centralDbContext.Products.FirstOrDefault(r => r.ProductId == request.ProductId);
                var findUniqueUser = _centralDbContext.Users.FirstOrDefault(r => r.Id == request.UserId);

                if (!string.IsNullOrEmpty(request.Document))
                {

                    var bytes = Convert.FromBase64String(request.Document);
                    string filePath = "";

                    var uniqueAbjad = new string(Enumerable.Range(0, 8).Select(_ => "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"[new Random().Next(36)]).ToArray());


                    if (IsImage(bytes))
                    {
                        filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/media/inventory/request", findUniqueUser.FullName + " " + findUniqueCode.ModelNo + "(" + uniqueAbjad + ") Request.jpg");
                        request.Document = "/media/inventory/request/" + findUniqueUser.FullName + " " + findUniqueCode.ModelNo + "(" + uniqueAbjad + ") Request.jpg";
                    }
                    else if (IsPdf(bytes))
                    {
                        filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/media/inventory/request", findUniqueUser.FullName + " " + findUniqueCode.ModelNo + "_Request.pdf");
                        request.Document = "/media/inventory/request/" + findUniqueUser.FullName + " " + findUniqueCode.ModelNo + "(" + uniqueAbjad + ") Request.pdf";
                    }
                    else
                    {
                        return BadRequest("Unsupported file format.");
                    }

                    await System.IO.File.WriteAllBytesAsync(filePath, bytes);
                }

                _centralDbContext.Requests.Add(request);
                await _centralDbContext.SaveChangesAsync();

                var updatedList = await _centralDbContext.Requests.ToListAsync();

                return Json(updatedList.Select(i => new
                {
                    i.ProductId,
                    i.UserId,
                    i.status,
                    i.StationId,
                    i.RequestQuantity,
                    i.requestDate,
                    i.ProductCategory,
                    i.Document,
                    i.approvalDate,
                    i.remarkMasterInv,
                    i.remarkUser,
                    i.fromStoreItem,
                    i.assignStoreItem,
                }));
            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }
        }

        [HttpGet("ItemRequestList")]
        public async Task<IActionResult> ItemRequestList()
        {

            var itemRequestList = await _centralDbContext.Requests.Include(i => i.Product).Include(i => i.User).Include(i => i.Station).ToListAsync();
            return Json(itemRequestList.Select(i => new
            {
                i.requestID,
                i.UserId,
                productName = i.Product?.ProductName,
                i.ProductId,
                productImage = i.Product?.ImageProduct,
                userName = i.User?.FullName,
                i.status,
                i.StationId,
                stationName = i.Station?.StationName,
                i.RequestQuantity,
                i.requestDate,
                i.ProductCategory,
                i.Document,
                i.approvalDate,
                i.remarkMasterInv,
                i.remarkUser,
                i.assignStoreItem,
                i.fromStoreItem,
               
            }));

        }

        [HttpPost("ApproveRequest/{id}")]
        public async Task<IActionResult> ApproveRequest(int id, [FromBody] RequestModel request)
        {
            var Request = await _centralDbContext.Requests.FindAsync(id);
            if (Request == null)
            {
                return NotFound(new { success = false, message = "Request not found" });
            }

            Request.status = "Approved";
            Request.remarkMasterInv = request.remarkMasterInv;
            Request.approvalDate = DateTime.Now;
            _centralDbContext.SaveChanges();

            return Ok(new { success = true, message = "Request Approved Successfully", data = Request });
        }

        [HttpPost("RejectRequest/{id}")]
        public async Task<IActionResult> RejectRequest(int id, [FromBody] RequestModel request)
        {


            var Request = await _centralDbContext.Requests.FindAsync(id);
            if (Request == null)
            {
                return NotFound(new { success = false, message = "Request not found" });
            }

            Request.status = "Rejected";
            Request.remarkMasterInv = request.remarkMasterInv;
            Request.approvalDate = DateTime.Now;
            _centralDbContext.SaveChanges();

            return Ok(new { success = true, message="Request Rejected Successfully", data=Request });
        }

        #endregion ItemRequestAdmin

        #region ItemReport

        [HttpPost("GetInventoryReport/{deptId}")]
        public async Task<IActionResult> GetInventoryReport(int deptId)
        {
            try{
                var user = await _userManager.GetUserAsync(User);

                var userRole = await _userManager.GetRolesAsync(user ?? new UserModel());
                List<ItemModel> items = new List<ItemModel>();
                if (userRole.Contains("SuperAdmin") && userRole.Contains("SystemAdmin")) 
                {
                    items = await _centralDbContext.Items
                    .Include("CreatedBy")
                    .Include("Department")
                    .Include("Product")
                    .ToListAsync();
                }
                else
                {
                    items = await _centralDbContext.Items
                    .Include("CreatedBy")
                    .Include("Department")
                    .Include("Product")
                    .Where(i => i.DepartmentId == deptId)
                    .ToListAsync();
                }
                var itemListWithDetails = items.Where(i => i.Quantity > 0).Select(item => new
                {
                    item.ItemID,
                    item.UniqueID,
                    item.CompanyId,
                    item.DepartmentId,
                    item.ProductId,
                    item.SerialNumber,
                    item.Quantity,
                    item.Supplier,
                    PurchaseDate = item.PurchaseDate.ToString("dd/MM/yyyy"),
                    item.PONo,
                    item.Currency,
                    item.DefaultPrice,
                    item.CurrencyRate,
                    item.ConvertPrice,
                    item.DODate,
                    item.Warranty,
                    EndWDate = item.EndWDate.ToString("dd/MM/yyyy"),
                    InvoiceDate = item.InvoiceDate?.ToString("dd/MM/yyyy"),
                    item.Department?.DepartmentName,
                    CreatedBy = item.CreatedBy!.UserName,
                    item.Product!.ProductName,
                    item.Product!.ProductShortName,
                    item.Product!.Category,
                    //CurrentUser = item.Movement?.FromUser?.UserName,
                    CurrentUser = item.Movement?.FromUser?.UserName,
                    CurrentStore = item.Movement?.FromStore?.StoreName,
                    CurrentStation = item.Movement?.FromStation?.StationName,

                    QRString = $"{HttpContext.Request.Scheme}://{HttpContext.Request.Host.Value}/I/{item.UniqueID}" // Generate QR String
                }).ToList();

                int itemCountRegistered = items.Count;
                int itemCountStillInStock = items.Where(i => i.Quantity > 0).Count();
                var itemsMovementsThisMonth = _centralDbContext.ItemMovements
                .Where(i => i.Date.Month == DateTime.Now.Month);
                int itemCountRegisteredThisMonth = itemsMovementsThisMonth.Count(i => i.Action == "Register");
                int itemCountStockOutThisMonth = itemsMovementsThisMonth.Count(i => i.Action == "Stock Out");

                var lastMonth = DateTime.Now.AddMonths(-1).Month;
                var itemsMovementsLastMonth = _centralDbContext.ItemMovements
                .Where(i => i.Date.Month == lastMonth);
                int itemCountRegisteredLastMonth = itemsMovementsLastMonth.Count(i => i.Action == "Register");
                int itemCountStockOutLastMonth = itemsMovementsLastMonth.Count(i => i.Action == "Stock Out");

                var report = new
                {
                    itemListWithDetails,
                    itemCountRegistered,
                    itemCountStillInStock,
                    itemCountRegisteredThisMonth,
                    itemCountStockOutThisMonth,
                    itemCountRegisteredLastMonth,
                    itemCountStockOutLastMonth
                };
                return Json(report);
            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }
        }

        #endregion

        #region Station
        [HttpPost("StationList")]
        public async Task<IActionResult> StationList()
        {
            var stationList = await _centralDbContext.Stations.Include(i => i.StationPic).Include(i => i.Department).ToListAsync();
            
            return Json(stationList.Select(i => new
            {
                i.StationId,
                i.StationPicID,
                i.StationName,
                i.DepartmentId,
                i.StationPic?.FullName,
                i.Department?.DepartmentName,
            }));
        }

        [HttpPost("AddStation")]
        public async Task<IActionResult> AddStation([FromBody] StationModel station)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            try
            {
                _centralDbContext.Stations.Add(station);
                await _centralDbContext.SaveChangesAsync();
                var updatedList = await _centralDbContext.Stations.ToListAsync();
                return Json(updatedList);
            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }
        }
        

        [HttpPost("EditStation")]
        public async Task<IActionResult> EditStation([FromBody] StationModel updatedStation)
        {
            var station = await _centralDbContext.Stations.FindAsync(updatedStation.StationId);
            if (station == null)
            {
                return NotFound(new { success = false, message = "Station not found" });
            }

            station.StationId = updatedStation.StationId;
            station.StationPicID = updatedStation.StationPicID;
            station.StationName = updatedStation.StationName;
            station.DepartmentId = updatedStation.DepartmentId;

            _centralDbContext.Stations.Update(station);
            await _centralDbContext.SaveChangesAsync();

            return Ok(new { success = true, message = "Station Updated successfully" });
        }

        [HttpDelete("DeleteStation/{id}")]
        public async Task<IActionResult> DeleteStation(int id)
        {
            var station = await _centralDbContext.Stations.FindAsync(id);
            if (station == null)
            {
                return NotFound(new { success = false, message = "Station not found" });
            }

            _centralDbContext.Stations.Remove(station);
            await _centralDbContext.SaveChangesAsync();

            return Ok(new { success = true, message = "Station deleted successfully" });
        }
        #endregion Station

        #region Store

        [HttpPost("StoreList")]
        public async Task<IActionResult> StoreList()
        {
            var storeList = await _centralDbContext.Stores.ToListAsync();
            return Json(storeList);
        }

        [HttpPost("StoreSpecificMaster/{storeId}")]
        public async Task<IActionResult> StoreSpecificMaster(int storeId)
        {
            var storeList = await _centralDbContext.InventoryMasters.Where(i => i.StoreId == storeId).FirstOrDefaultAsync();
            return Json(storeList);
        }

        [HttpPost("StoreSpecificMasterList/{userId}")]
        public async Task<IActionResult> StoreSpecificMasterList(int userId)
        {
            var storeList = await _centralDbContext.InventoryMasters
                .Where(i => i.UserId == userId)
                .Select(i => i.StoreId) // Extract only StoreIds
                .Distinct() // Avoid duplicate queries
                .ToListAsync();

            var storeSpecific = await _centralDbContext.Stores
                .Where(s => storeList.Contains(s.Id)) // Fetch all relevant stores at once
                .ToListAsync();

            return Json(storeSpecific);
        }

        #endregion Store

        #region AllUser

        [HttpPost("UserList")]
        public async Task<IActionResult> UserList()
        {

            var userList = await _centralDbContext.Users.Include(i => i.Department).ToListAsync();
            return Json(userList.Select(i => new
            {
                i.Id,
                i.FullName,
                i.Department,
                i.Department?.DepartmentName,
            }));
        }

        #endregion AllUser

        #region ScannerUser
        [HttpPost("UpdateItemMovementUser")]
        public async Task<IActionResult> UpdateItemMovementUser([FromBody] ItemMovementModel receiveMovement)
        {

            try
            {

                var updatedList = await _centralDbContext.ItemMovements.FindAsync(receiveMovement.Id);

                if (updatedList == null)
                {
                    return NotFound("Item movement record not found.");
                }
                updatedList.MovementComplete = receiveMovement.MovementComplete;
                updatedList.LatestStatus = receiveMovement.LatestStatus;
                updatedList.receiveDate = receiveMovement.receiveDate;
                updatedList.MovementComplete = receiveMovement.MovementComplete;

                _centralDbContext.ItemMovements.Update(updatedList);
                await _centralDbContext.SaveChangesAsync();

                var receiveItems = await _centralDbContext.Items.FindAsync(receiveMovement.ItemId);

                if (receiveItems != null)
                {
                    receiveItems.ItemStatus = 3;
                    _centralDbContext.Items.Update(receiveItems);

                }

                await _centralDbContext.SaveChangesAsync();

                return Json(updatedList);
            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }
        }

        [HttpPost("ReturnItemMovementUser")]
        public async Task<IActionResult> ReturnItemMovementUser([FromBody] ItemMovementModel returnMovement)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            try
            {
                if (!string.IsNullOrEmpty(returnMovement.ConsignmentNote))
                {
                    var findUniqueCode = _centralDbContext.Items.Include(i => i.Product).FirstOrDefault(r => r.ItemID == returnMovement.ItemId);
                    var findUniqueUser = _centralDbContext.Users.FirstOrDefault(r => r.Id == returnMovement.ToUser);

                    var bytes = Convert.FromBase64String(returnMovement.ConsignmentNote);
                    string filePath = "";

                    var uniqueAbjad = new string(Enumerable.Range(0, 8).Select(_ => "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"[new Random().Next(36)]).ToArray());


                    if (IsImage(bytes))
                    {
                        filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/media/inventory/itemmovement", findUniqueUser.FullName + " " + findUniqueCode.Product?.ModelNo + "(" + uniqueAbjad + ") Return.jpg");
                        returnMovement.ConsignmentNote = "/media/inventory/itemmovement/" + findUniqueUser.FullName + " " + findUniqueCode.Product?.ModelNo + "(" + uniqueAbjad + ") Return.jpg";
                    }
                    else if (IsPdf(bytes))
                    {
                        filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/media/inventory/itemmovement", findUniqueUser.FullName + " " + findUniqueCode.Product?.ModelNo + "Return.pdf");
                        returnMovement.ConsignmentNote = "/media/inventory/itemmovement/" + findUniqueUser.FullName + " " + findUniqueCode.Product?.ModelNo + "(" + uniqueAbjad + ") Return.pdf";
                    }
                    else
                    {
                        return BadRequest("Unsupported file format.");
                    }

                    await System.IO.File.WriteAllBytesAsync(filePath, bytes);
                }

                _centralDbContext.ItemMovements.Add(returnMovement);
                await _centralDbContext.SaveChangesAsync();

                var updateItemIdMovement = await _centralDbContext.ItemMovements
                    .FirstOrDefaultAsync(m => m.Id == returnMovement.Id && m.MovementComplete == false);

                if (updateItemIdMovement != null)
                {
                    var returnItems = await _centralDbContext.Items.FindAsync(updateItemIdMovement.ItemId);

                    if (returnItems != null)
                    {
                        returnItems.MovementId = updateItemIdMovement.Id;
                        returnItems.ItemStatus = 2;
                        _centralDbContext.Items.Update(returnItems);
                        await _centralDbContext.SaveChangesAsync(); // Simpan perubahan
                    }
                }

                return Json(new
                {
                    updateItemIdMovement.Id,
                    updateItemIdMovement.ItemId,
                    updateItemIdMovement.ToStation,
                    updateItemIdMovement.ToStore,
                    updateItemIdMovement.ToUser,
                    updateItemIdMovement.ToOther,
                    updateItemIdMovement.sendDate,
                    updateItemIdMovement.Action,
                    updateItemIdMovement.Quantity,
                    updateItemIdMovement.Remark,
                    updateItemIdMovement.ConsignmentNote,
                    updateItemIdMovement.Date,
                    updateItemIdMovement.LastUser,
                    updateItemIdMovement.LastStore,
                    updateItemIdMovement.LastStation,
                    updateItemIdMovement.LatestStatus,
                    updateItemIdMovement.receiveDate,
                    updateItemIdMovement.MovementComplete
                });

            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }
        }

        [HttpPost("StationItemMovementUser")]
        public async Task<IActionResult> StationItemMovementUser([FromBody] ItemMovementModel stationMovement)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            try
            {
                if (!string.IsNullOrEmpty(stationMovement.ConsignmentNote))
                {
                    var findUniqueCode = _centralDbContext.Items.Include(i => i.Product).FirstOrDefault(r => r.ItemID == stationMovement.ItemId);
                    var findUniqueUser = _centralDbContext.Users.FirstOrDefault(r => r.Id == stationMovement.ToUser);

                    var bytes = Convert.FromBase64String(stationMovement.ConsignmentNote);
                    string filePath = "";

                    var uniqueAbjad = new string(Enumerable.Range(0, 8).Select(_ => "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"[new Random().Next(36)]).ToArray());


                    if (IsImage(bytes))
                    {
                        filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/media/inventory/itemmovement", findUniqueUser.FullName + " " + findUniqueCode.Product?.ModelNo + "(" + uniqueAbjad + ") Station.jpg");
                        stationMovement.ConsignmentNote = "/media/inventory/itemmovement/" + findUniqueUser.FullName + " " + findUniqueCode.Product?.ModelNo + "(" + uniqueAbjad + ") Station.jpg";
                    }
                    else if (IsPdf(bytes))
                    {
                        filePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/media/inventory/itemmovement", findUniqueUser.FullName + " " + findUniqueCode.Product?.ModelNo + "Return.pdf");
                        stationMovement.ConsignmentNote = "/media/inventory/itemmovement/" + findUniqueUser.FullName + " " + findUniqueCode.Product?.ModelNo + "(" + uniqueAbjad + ") Station.pdf";
                    }
                    else
                    {
                        return BadRequest("Unsupported file format.");
                    }

                    await System.IO.File.WriteAllBytesAsync(filePath, bytes);
                }

                _centralDbContext.ItemMovements.Add(stationMovement);
                await _centralDbContext.SaveChangesAsync();

                var updateItemIdMovement = await _centralDbContext.ItemMovements.Include(i => i.Item)
                    .FirstOrDefaultAsync(m => m.Id == stationMovement.Id);


                if (updateItemIdMovement != null)
                {
                    var returnItems = await _centralDbContext.Items.FindAsync(updateItemIdMovement.ItemId);

                    if (returnItems != null)
                    {
                        returnItems.MovementId = updateItemIdMovement.Id;
                        returnItems.ItemStatus = 3;

                        _centralDbContext.Items.Update(returnItems); // Simpan perubahan
                        await _centralDbContext.SaveChangesAsync();
                    }
                }

                return Json(new
                {
                    updateItemIdMovement.Id,
                    updateItemIdMovement.ItemId,
                    updateItemIdMovement.Item?.UniqueID,
                    updateItemIdMovement.ToStation,
                    updateItemIdMovement.ToStore,
                    updateItemIdMovement.ToUser,
                    updateItemIdMovement.ToOther,
                    updateItemIdMovement.sendDate,
                    updateItemIdMovement.Action,
                    updateItemIdMovement.Quantity,
                    updateItemIdMovement.Remark,
                    updateItemIdMovement.ConsignmentNote,
                    updateItemIdMovement.Date,
                    updateItemIdMovement.LastUser,
                    updateItemIdMovement.LastStore,
                    updateItemIdMovement.LastStation,
                    updateItemIdMovement.LatestStatus,
                    updateItemIdMovement.receiveDate,
                    updateItemIdMovement.MovementComplete
                });


            }
            catch (Exception ex)
            {
                return BadRequest(ex.Message);
            }
        }
        
        #endregion
    }
}
