using LSFE.Domain.Contracts;
using LSFE.Domain.Helpers;
using LSFE.Infrastructure.Dto;
using LSFE.Infrastructure.Dto.TimeKeeping;
using LSFE.Infrastructure.Entities;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;

namespace LSFE.API.Controllers.Account
{
    public class TimeKeepingController : BaseController
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly IWebHostEnvironment _env;
        public readonly UserManager<AppsUsers> _userManager;
        public TimeKeepingController(IUnitOfWork unitOfWork, IWebHostEnvironment env, 
            UserManager<AppsUsers> userManager) 
            : base(unitOfWork, env)
        {
            _unitOfWork = unitOfWork;
            _env = env;
            _userManager = userManager;
        }

        #region Post Put
        [HttpPost("PostPutAttendance")]
        [RequestSizeLimit(20_000_000)]
        public async Task<IActionResult> PostPutAttendance(
        [FromForm] AttendanceDto dto,
        IFormFile? photoFileIn,
        IFormFile? photoFileOut)
        {
            if (dto == null)
                return await LogAndReturnBadRequest("Invalid attendance data.", "Unknown");

            try
            {
                var uploadsPath = Path.Combine(_env.WebRootPath, "Content/Uploads", "Attendance");
                Directory.CreateDirectory(uploadsPath);

                // Handle Time-In photo
                if (photoFileIn?.Length > 0)
                {
                    var savedFileName = dto.SignatureFileNameIn ?? $"{Guid.NewGuid()}{Path.GetExtension(photoFileIn.FileName)}";
                    var filePath = Path.Combine(uploadsPath, savedFileName);

                    if (System.IO.File.Exists(filePath))
                    {
                        await LogErrorAsync($"Time-In file already exists, skipping save: {savedFileName}", dto.UserId);
                    }
                    else
                    {
                        using var stream = new FileStream(filePath, FileMode.Create);
                        await photoFileIn.CopyToAsync(stream);
                    }

                    dto.SignatureFileNameIn = savedFileName;
                }

                // Handle Time-Out photo
                if (photoFileOut?.Length > 0)
                {
                    var savedFileName = dto.SignatureFileNameOut ?? $"{Guid.NewGuid()}{Path.GetExtension(photoFileOut.FileName)}";
                    var filePath = Path.Combine(uploadsPath, savedFileName);

                    if (System.IO.File.Exists(filePath))
                    {
                        await LogErrorAsync($"Time-Out file already exists, skipping save: {savedFileName}", dto.UserId);
                    }
                    else
                    {
                        using var stream = new FileStream(filePath, FileMode.Create);
                        await photoFileOut.CopyToAsync(stream);
                    }

                    dto.SignatureFileNameOut = savedFileName;
                }

                var response = await _unitOfWork.Attendances.PostPutAttendance(dto);
                return response.Success ? Ok(response) : BadRequest(response);
            }
            catch (Exception ex)
            {
                return await LogAndReturnBadRequest(ex.ToString(), dto.UserId);
            }
        }
        #endregion

        #region Get 
        [HttpGet("GetAttendanceToday")]
        public async Task<IActionResult> GetAttendanceToday([FromQuery] CredentialDto dto)
        {
            var results = await _unitOfWork.Attendances.GetAttendanceToday(dto);
            return Ok(results);
        }
        [HttpGet("GetAttendanceLogs")]
        public async Task<IActionResult> GetAttendanceLogs([FromQuery] AttendanceDto dto)
        {
            var results = await _unitOfWork.Attendances.GetAttendance(dto);
            return Ok(results);
        }
        [HttpGet("GetAttendancePhoto/{fileName}")]
        [ResponseCache(Duration = 3600)] 
        public async Task<IActionResult> GetAttendancePhoto(string fileName)
        {
            try
            {
                // Validate filename
                if (string.IsNullOrWhiteSpace(fileName) || fileName.Contains(".."))
                {
                    return BadRequest("Invalid file name");
                }

                var uploadsPath = Path.Combine(_env.WebRootPath, "Content/Uploads", "Attendance");
                var filePath = Path.Combine(uploadsPath, fileName);

                ContentTypeHelper.ValidateFile(filePath, uploadsPath);

                // Stream the file instead of loading entirely into memory
                var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
                var contentType = ContentTypeHelper.GetContentType(fileName);

                Response.Headers.Append("Content-Disposition", $"inline; filename=\"{fileName}\"");
                return File(fileStream, contentType, enableRangeProcessing: true);
            }
            catch (Exception ex)
            {
                return StatusCode(500, "Error retrieving file");
            }
        }
        #endregion
    }
}
