using ClosedXML.Excel;
using System.IO;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.EntityFrameworkCore;
using System.Security.Claims;
using Microsoft.AspNetCore.Mvc.Rendering;
using WarehouseAppSHIPS.Data;
using WarehouseAppSHIPS.Models;
using System.Linq;
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.SignalR;
using WarehouseAppSHIPS.Hubs;

namespace WarehouseAppSHIPS.Controllers
{
    [Authorize]
    public class ProcurementController : Controller
    {
        private readonly ApplicationDbContext _context;
        private readonly IWebHostEnvironment _webHost;
        private readonly IHubContext<NotificationHub> _hubContext;

        public ProcurementController(ApplicationDbContext context, IWebHostEnvironment webHost, IHubContext<NotificationHub> hubContext)
        {
            _context = context;
            _webHost = webHost;
            _hubContext = hubContext;
        }

        public IActionResult Index(string batch)
        {
            var userId = int.Parse(User.FindFirstValue("UserId") ?? "0");
            var query = _context.ProcurementRequests.Include(p => p.Requester).AsQueryable();

            if (!User.IsInRole("MasterAdmin") && !User.IsInRole("Supervisor") && !User.IsInRole("StaffGudang"))
            {
                query = query.Where(p => p.RequesterId == userId);
            }

            if (!string.IsNullOrEmpty(batch))
            {
                query = query.Where(p => p.NomorBatch == batch);
                ViewBag.CurrentBatch = batch;
            }

            var data = query.OrderByDescending(p => p.RequestDate).ToList();
            ViewBag.BatchList = _context.ProcurementRequests.Select(p => p.NomorBatch).Distinct().ToList();
            return View(data);
        }

        [Authorize(Roles = "MasterAdmin,Supervisor,StaffGudang")]
        public IActionResult ApproveRequest(int id, bool approve)
        {
            var req = _context.ProcurementRequests.Find(id);
            if (req != null)
            {
                req.IsApproved = approve;

                string statusTxt = approve ? "DISETUJUI" : "DITOLAK";
                var notif = new AppNotification
                {
                    Title = "Status Pengadaan Diperbarui",
                    Message = $"Request Batch {req.NomorBatch} ({req.ItemRequested}) telah {statusTxt} oleh {User.Identity?.Name}.",
                    ActionUrl = "/Procurement/Index"
                };
                _context.AppNotifications.Add(notif);
                _context.SaveChanges();

                _hubContext.Clients.All.SendAsync("TerimaNotif", notif.Title, notif.Message, notif.ActionUrl);

                TempData["Success"] = approve ? "Permintaan Berhasil DISETUJUI!" : "Permintaan Berhasil DITOLAK!";
            }
            return RedirectToAction("Index");
        }

        [HttpPost]
        [Authorize(Roles = "MasterAdmin,Supervisor,StaffGudang")]
        public IActionResult UpdateStatus(int id, ProcurementStatus status)
        {
            var req = _context.ProcurementRequests.Find(id);
            if (req != null)
            {
                req.Status = status;

                if (status == ProcurementStatus.SedangDibeli && req.TanggalDiproses == null)
                {
                    req.TanggalDiproses = DateTime.Now;
                }
                else if (status == ProcurementStatus.BarangDatang && req.TanggalDatang == null)
                {
                    req.TanggalDatang = DateTime.Now;
                }
                else if (status == ProcurementStatus.BelumDibeli)
                {
                    req.TanggalDiproses = null;
                    req.TanggalDatang = null;
                }

                _context.SaveChanges();
                TempData["Success"] = "Status pengadaan berhasil diperbarui!";
            }
            return RedirectToAction("Index");
        }

        [Authorize(Roles = "MasterAdmin,Supervisor,StaffGudang")]
        public IActionResult MasukkanKeStok(int id)
        {
            var req = _context.ProcurementRequests.Find(id);
            if (req != null && req.Status == ProcurementStatus.BarangDatang)
            {
                Material? targetMaterial = null;

                if (req.MaterialId.HasValue && req.MaterialId.Value > 0)
                {
                    targetMaterial = _context.Materials.Find(req.MaterialId.Value);
                }
                else if (!string.IsNullOrEmpty(req.ItemRequested))
                {
                    targetMaterial = _context.Materials.FirstOrDefault(m => m.Name.ToLower() == req.ItemRequested.ToLower());
                    if (targetMaterial != null) req.MaterialId = targetMaterial.Id;
                }

                if (targetMaterial != null)
                {
                    targetMaterial.Stock += req.Qty;

                    var userId = int.Parse(User.FindFirstValue("UserId") ?? "1");
                    var inboundLog = new InboundTransaction
                    {
                        TransactionDate = DateTime.Now,
                        MaterialId = targetMaterial.Id,
                        Qty = req.Qty,
                        SupplierName = "Eksternal / CPAN",
                        Remarks = $"[AUTO-INBOUND] Kedatangan Request Eksternal Batch: {req.NomorBatch}",
                        ReceiverId = userId
                    };
                    _context.InboundTransactions.Add(inboundLog);

                    var historyLog = new TransactionHistory
                    {
                        TransactionDate = DateTime.Now,
                        TransactionType = "PENGADAAN CPAN",
                        MaterialName = targetMaterial.Name,
                        AssetCode = targetMaterial.AssetCode ?? "-",
                        Qty = req.Qty,
                        ActorName = User.Identity?.Name ?? "Supervisor",
                        Remarks = $"[AUTO-LOG] Barang Pengadaan Eksternal (CPAN) masuk gudang. Batch: {req.NomorBatch}"
                    };
                    _context.TransactionHistories.Add(historyLog);

                    req.Status = ProcurementStatus.Selesai;
                    _context.SaveChanges();
                    TempData["Success"] = $"SUKSES! Stok '{targetMaterial.Name}' otomatis bertambah {req.Qty} unit.";
                }
                else
                {
                    TempData["Error"] = $"GAGAL DITAMBAHKAN: Barang '{req.ItemRequested}' belum terdaftar di Master Katalog.";
                }
            }
            return RedirectToAction("Index");
        }

        // === INI FUNGSI RETUR YANG UDAH DIREVISI BRAY ===
        [HttpPost]
        [Authorize(Roles = "MasterAdmin,Supervisor,StaffGudang")]
        public IActionResult ReturBarang(int id, string alasanRetur)
        {
            var req = _context.ProcurementRequests.Find(id);
            if (req != null)
            {
                req.Status = ProcurementStatus.Diretur;
                req.CatatanRetur = alasanRetur; // <--- INI KUNCI BIAR ALASANNYA TERSIMPAN

                _context.SaveChanges();

                var notif = new AppNotification
                {
                    Title = "⚠️ BARANG DIRETUR (GUDANG)",
                    Message = $"Batch {req.NomorBatch} ({req.ItemRequested}) DITOLAK oleh Gudang. Alasan: {alasanRetur}",
                    ActionUrl = "/Procurement/Index"
                };
                _context.AppNotifications.Add(notif);
                _context.SaveChanges();

                _hubContext.Clients.All.SendAsync("TerimaNotif", notif.Title, notif.Message, notif.ActionUrl);

                TempData["Error"] = $"Barang berhasil DIRETUR. Notifikasi penolakan telah dikirim ke sistem.";
            }
            return RedirectToAction("Index");
        }

        public IActionResult Create()
        {
            ViewBag.MaterialList = new SelectList(_context.Materials.ToList(), "Id", "Name");
            return View();
        }

        [HttpPost]
        public async Task<IActionResult> Create(ProcurementRequest model, IFormFile? fileUpload)
        {
            var userId = int.Parse(User.FindFirstValue("UserId") ?? "1");
            model.RequesterId = userId;
            model.Status = ProcurementStatus.BelumDibeli;
            model.IsApproved = null;

            if (model.MaterialId.HasValue)
            {
                var m = _context.Materials.Find(model.MaterialId);
                if (m != null) model.ItemRequested = m.Name;
            }

            if (fileUpload != null && fileUpload.Length > 0)
            {
                string uploadDir = Path.Combine(_webHost.WebRootPath, "uploads/procurement");
                if (!Directory.Exists(uploadDir)) Directory.CreateDirectory(uploadDir);

                string fileName = Guid.NewGuid().ToString() + Path.GetExtension(fileUpload.FileName);
                string filePath = Path.Combine(uploadDir, fileName);
                using (var fileStream = new FileStream(filePath, FileMode.Create))
                {
                    await fileUpload.CopyToAsync(fileStream);
                }
                model.DocumentPath = "/uploads/procurement/" + fileName;
            }

            _context.ProcurementRequests.Add(model);

            var notif = new AppNotification
            {
                Title = "Permintaan Pengadaan Baru",
                Message = $"Request pengadaan Batch {model.NomorBatch} untuk {model.ItemRequested} (Qty: {model.Qty}) telah diajukan oleh {User.Identity?.Name}.",
                ActionUrl = "/Procurement/Index"
            };
            _context.AppNotifications.Add(notif);

            await _context.SaveChangesAsync();
            await _hubContext.Clients.All.SendAsync("TerimaNotif", notif.Title, notif.Message, notif.ActionUrl);

            return RedirectToAction("Index");
        }

        [Authorize]
        public IActionResult ExportProcurementExcel()
        {
            var userId = int.Parse(User.FindFirstValue("UserId") ?? "0");
            var query = _context.ProcurementRequests
                .Include(p => p.Requester)
                .AsQueryable();

            if (!User.IsInRole("MasterAdmin") && !User.IsInRole("Supervisor") && !User.IsInRole("StaffGudang"))
            {
                query = query.Where(p => p.RequesterId == userId);
            }

            var dataProcurement = query.OrderByDescending(p => p.RequestDate).ToList();

            using (var workbook = new XLWorkbook())
            {
                var worksheet = workbook.Worksheets.Add("Eksternal Pengadaan");
                var currentRow = 1;

                worksheet.Cell(currentRow, 1).Value = "ID Request";
                worksheet.Cell(currentRow, 2).Value = "Tanggal Request";
                worksheet.Cell(currentRow, 3).Value = "Pemohon";
                worksheet.Cell(currentRow, 4).Value = "Nomor Batch";
                worksheet.Cell(currentRow, 5).Value = "Nama Barang";
                worksheet.Cell(currentRow, 6).Value = "Jumlah (Qty)";
                worksheet.Cell(currentRow, 7).Value = "Persetujuan";
                worksheet.Cell(currentRow, 8).Value = "Status Progress";

                foreach (var item in dataProcurement)
                {
                    currentRow++;
                    worksheet.Cell(currentRow, 1).Value = item.Id;
                    worksheet.Cell(currentRow, 2).Value = item.RequestDate.ToString("dd-MM-yyyy HH:mm");
                    worksheet.Cell(currentRow, 3).Value = item.Requester?.FullName ?? "-";
                    worksheet.Cell(currentRow, 4).Value = item.NomorBatch ?? "-";
                    worksheet.Cell(currentRow, 5).Value = item.ItemRequested ?? "-";
                    worksheet.Cell(currentRow, 6).Value = item.Qty;

                    string statusApprove = "Menunggu";
                    if (item.IsApproved == true) statusApprove = "Disetujui";
                    else if (item.IsApproved == false) statusApprove = "Ditolak";
                    worksheet.Cell(currentRow, 7).Value = statusApprove;

                    worksheet.Cell(currentRow, 8).Value = item.Status.ToString();
                }

                worksheet.Columns().AdjustToContents();

                using (var stream = new MemoryStream())
                {
                    workbook.SaveAs(stream);
                    var content = stream.ToArray();
                    return File(content, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "Data_Eksternal_Pengadaan_SHIPS.xlsx");
                }
            }
        }
    }
}