using System.Security.Claims;
using LearningMaterialSystem.Data;
using LearningMaterialSystem.Models;
using LearningMaterialSystem.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;

namespace LearningMaterialSystem.Controllers;

[Authorize]
public class HocLieusController : Controller
{
    private readonly ApplicationDbContext _context;
    private readonly IWebHostEnvironment _environment;
    private readonly INhatKyTruyCapService _nhatKy;

    public HocLieusController(ApplicationDbContext context, IWebHostEnvironment environment, INhatKyTruyCapService nhatKy)
    {
        _context = context;
        _environment = environment;
        _nhatKy = nhatKy;
    }

    private int? CurrentUserId => int.TryParse(User.FindFirstValue(ClaimTypes.NameIdentifier), out var id) ? id : null;

    public async Task<IActionResult> Index(string? search, int? monHocId)
    {
        var query = _context.HocLieus.Include(h => h.MonHoc).AsNoTracking();

        if (!string.IsNullOrWhiteSpace(search))
            query = query.Where(h => h.TieuDe.Contains(search) || (h.MoTa != null && h.MoTa.Contains(search)));
        if (monHocId.HasValue)
            query = query.Where(h => h.MonHocId == monHocId.Value);

        var list = await query.OrderByDescending(h => h.NgayTao).ToListAsync();
        ViewBag.MonHocs = new SelectList(await _context.MonHocs.ToListAsync(), "Id", "TenMon", monHocId);
        ViewBag.Search = search;
        ViewBag.MonHocId = monHocId;
        ViewBag.CanEditIds = User.IsInRole("BoPhanChuyenMon")
            ? list.Select(h => h.Id).ToHashSet()
            : (User.IsInRole("GiangVien") ? list.Where(h => h.NguoiDungId == null || h.NguoiDungId == CurrentUserId).Select(h => h.Id).ToHashSet() : new HashSet<int>());
        return View(list);
    }

    public async Task<IActionResult> Details(int id)
    {
        var hocLieu = await _context.HocLieus.Include(h => h.MonHoc).FirstOrDefaultAsync(h => h.Id == id);
        if (hocLieu == null) return NotFound();

        await _nhatKy.GhiLogAsync("View", hocLieu.Id, CurrentUserId, HttpContext);
        return View(hocLieu);
    }

    public async Task<IActionResult> Download(int id)
    {
        var hocLieu = await _context.HocLieus.FindAsync(id);
        if (hocLieu == null || string.IsNullOrEmpty(hocLieu.DuongDanTep)) return NotFound();

        var path = Path.Combine(_environment.WebRootPath, hocLieu.DuongDanTep.TrimStart('/'));
        if (!System.IO.File.Exists(path)) return NotFound();

        await _nhatKy.GhiLogAsync("Download", hocLieu.Id, CurrentUserId, HttpContext);

        var fileName = Path.GetFileName(path);
        var contentType = "application/octet-stream";
        return PhysicalFile(path, contentType, fileName);
    }

    [Authorize(Roles = "GiangVien")]
    public IActionResult Create()
    {
        ViewData["MonHocId"] = new SelectList(_context.MonHocs, "Id", "TenMon");
        return View();
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    [Authorize(Roles = "GiangVien")]
    public async Task<IActionResult> Create(HocLieu hocLieu, IFormFile? file)
    {
        if (file == null || file.Length == 0)
            ModelState.AddModelError("", "Vui lòng chọn file học liệu để đăng tải.");
        if (!ModelState.IsValid)
        {
            ViewData["MonHocId"] = new SelectList(_context.MonHocs, "Id", "TenMon", hocLieu.MonHocId);
            return View(hocLieu);
        }

        if (file!.Length > 0)
        {
            var uploadsFolder = Path.Combine(_environment.WebRootPath, "uploads");
            Directory.CreateDirectory(uploadsFolder);
            var fileName = $"{Guid.NewGuid()}_{file.FileName}";
            var filePath = Path.Combine(uploadsFolder, fileName);
            await using (var stream = new FileStream(filePath, FileMode.Create))
                await file.CopyToAsync(stream);
            hocLieu.DuongDanTep = $"/uploads/{fileName}";
        }

        hocLieu.NgayTao = DateTime.UtcNow;
        hocLieu.TrangThai = "ChoDuyet";
        hocLieu.NguoiDungId = CurrentUserId;
        _context.HocLieus.Add(hocLieu);
        await _context.SaveChangesAsync();
        await _nhatKy.GhiLogAsync("Upload", hocLieu.Id, CurrentUserId, HttpContext);
        return RedirectToAction(nameof(Index));
    }

    [Authorize(Roles = "GiangVien")]
    public async Task<IActionResult> Edit(int id)
    {
        var hocLieu = await _context.HocLieus.FindAsync(id);
        if (hocLieu == null) return NotFound();
        if (!CanEditOrDelete(hocLieu))
            return Forbid();
        ViewData["MonHocId"] = new SelectList(_context.MonHocs, "Id", "TenMon", hocLieu.MonHocId);
        return View(hocLieu);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    [Authorize(Roles = "GiangVien")]
    public async Task<IActionResult> Edit(int id, HocLieu hocLieu, IFormFile? file)
    {
        if (id != hocLieu.Id) return NotFound();
        if (!ModelState.IsValid)
        {
            ViewData["MonHocId"] = new SelectList(_context.MonHocs, "Id", "TenMon", hocLieu.MonHocId);
            return View(hocLieu);
        }

        var entity = await _context.HocLieus.FindAsync(id);
        if (entity == null) return NotFound();
        if (!CanEditOrDelete(entity))
            return Forbid();

        entity.TieuDe = hocLieu.TieuDe;
        entity.Loai = hocLieu.Loai;
        entity.MonHocId = hocLieu.MonHocId;
        entity.MoTa = hocLieu.MoTa;

        if (file != null && file.Length > 0)
        {
            var uploadsFolder = Path.Combine(_environment.WebRootPath, "uploads");
            Directory.CreateDirectory(uploadsFolder);
            var fileName = $"{Guid.NewGuid()}_{file.FileName}";
            var filePath = Path.Combine(uploadsFolder, fileName);
            await using (var stream = new FileStream(filePath, FileMode.Create))
                await file.CopyToAsync(stream);
            entity.DuongDanTep = $"/uploads/{fileName}";
        }

        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    [Authorize(Roles = "BoPhanChuyenMon")]
    public async Task<IActionResult> Duyet(int id)
    {
        var hocLieu = await _context.HocLieus.FindAsync(id);
        if (hocLieu == null) return NotFound();
        hocLieu.TrangThai = "DaDuyet";
        await _context.SaveChangesAsync();
        await _nhatKy.GhiLogAsync("Approve", hocLieu.Id, CurrentUserId, HttpContext);
        return RedirectToAction(nameof(Index));
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    [Authorize(Roles = "BoPhanChuyenMon")]
    public async Task<IActionResult> TuChoi(int id)
    {
        var hocLieu = await _context.HocLieus.FindAsync(id);
        if (hocLieu == null) return NotFound();
        hocLieu.TrangThai = "TuChoi";
        await _context.SaveChangesAsync();
        await _nhatKy.GhiLogAsync("Reject", hocLieu.Id, CurrentUserId, HttpContext);
        return RedirectToAction(nameof(Index));
    }

    [Authorize(Roles = "GiangVien")]
    public async Task<IActionResult> Delete(int id)
    {
        var hocLieu = await _context.HocLieus.Include(h => h.MonHoc).FirstOrDefaultAsync(h => h.Id == id);
        if (hocLieu == null) return NotFound();
        if (!CanEditOrDelete(hocLieu))
            return Forbid();
        return View(hocLieu);
    }

    [HttpPost, ActionName("Delete")]
    [ValidateAntiForgeryToken]
    [Authorize(Roles = "GiangVien")]
    public async Task<IActionResult> DeleteConfirmed(int id)
    {
        var hocLieu = await _context.HocLieus.FindAsync(id);
        if (hocLieu == null)
            return RedirectToAction(nameof(Index));

        if (!CanEditOrDelete(hocLieu))
            return Forbid();

        // XÓA LOG TRƯỚC
        var logs = _context.NhatKyTruyCaps.Where(x => x.HocLieuId == id);
        _context.NhatKyTruyCaps.RemoveRange(logs);

        _context.HocLieus.Remove(hocLieu);

        await _context.SaveChangesAsync();

        return RedirectToAction(nameof(Index));
    }

    /// <summary>Học liệu do giảng viên đăng – chỉ Giảng viên.</summary>
    [Authorize(Roles = "GiangVien")]
    public async Task<IActionResult> MyMaterials(string? search, int? monHocId, string? trangThai)
    {
        if (!CurrentUserId.HasValue)
            return RedirectToAction(nameof(Index));
        var query = _context.HocLieus
            .Include(h => h.MonHoc)
            .Where(h => h.NguoiDungId == CurrentUserId)
            .AsNoTracking();
        if (!string.IsNullOrWhiteSpace(search))
            query = query.Where(h => h.TieuDe.Contains(search) || (h.MoTa != null && h.MoTa.Contains(search)));
        if (monHocId.HasValue)
            query = query.Where(h => h.MonHocId == monHocId.Value);
        if (!string.IsNullOrWhiteSpace(trangThai))
            query = query.Where(h => h.TrangThai == trangThai);
        var list = await query.OrderByDescending(h => h.NgayTao).ToListAsync();
        ViewBag.MonHocs = new SelectList(await _context.MonHocs.ToListAsync(), "Id", "TenMon", monHocId);
        ViewBag.Search = search;
        ViewBag.MonHocId = monHocId;
        ViewBag.TrangThai = trangThai;
        return View(list);
    }

    private bool CanEditOrDelete(HocLieu hocLieu)
    {
        if (!CurrentUserId.HasValue) return false;
        if (User.IsInRole("BoPhanChuyenMon")) return true;
        return hocLieu.NguoiDungId == null || hocLieu.NguoiDungId == CurrentUserId;
    }
}
