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

namespace LSFE.API.Controllers
{
    public class MaintenanceController : BaseController
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly IWebHostEnvironment _env;
        public MaintenanceController(IUnitOfWork unitOfWork, IWebHostEnvironment env) : base(unitOfWork, env)
        {
            _unitOfWork = unitOfWork;
            _env = env;
        }
        #region Post Put      
        [HttpPost("PostPutArea")]
        public async Task<IActionResult> PostPutArea([FromBody] Areas dto)
        {
            if (dto == null)
                return BadRequest("Invalid doctor data.");

            var response = await _unitOfWork.Areas.AddOrUpdateAsync(dto);
            if (response.Success)
            {
                await _unitOfWork.SaveChangesAsync();
                return Ok(response);
            }

            return BadRequest(response);
        }
        [HttpPost("PostPutDivision")]
        public async Task<IActionResult> PostPutDivision([FromBody] Divisions dto)
        {
            if (dto == null)
                return BadRequest("Invalid doctor data.");

            var response = await _unitOfWork.Divisions.AddOrUpdateAsync(dto);

            if (response.Success)
            {
                await _unitOfWork.SaveChangesAsync();
                return Ok(response);
            }

            return BadRequest(response);
        }
        [HttpPost("PostPutDistrict")]
        public async Task<IActionResult> PostPutDistrict([FromBody] Districts dto)
        {
            if (dto == null)
                return BadRequest("Invalid doctor data.");

            var response = await _unitOfWork.Districts.AddOrUpdateAsync(dto);
            if (response.Success)
            {
                await _unitOfWork.SaveChangesAsync();
                return Ok(response);
            }

            return BadRequest(response);
        }
        [HttpPost("PostPutInstitution")]
        public async Task<IActionResult> PostPutInstitution([FromBody] Institutions dto)
        {
            if (dto == null)
                return BadRequest("Invalid doctor data.");

            var response = await _unitOfWork.Institutions.AddOrUpdateAsync(dto);
            if (response.Success)
            {
                await _unitOfWork.SaveChangesAsync();
                return Ok(response);
            }

            return BadRequest(response);
        }
        [HttpPost("PostPutProduct")]
        public async Task<IActionResult> PostPutProduct([FromForm] Products dto, IFormFile? file)
        {
            if (dto == null)
                return BadRequest("Invalid product data.");

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

            if (file?.Length > 0)
            {
                var savedFileName = $"{Guid.NewGuid()}{Path.GetExtension(file.FileName)}";
                var filePath = Path.Combine(uploadsPath, savedFileName);

                // Save the file
                using var stream = new FileStream(filePath, FileMode.Create);
                await file.CopyToAsync(stream);

                dto.ProductLink = savedFileName;
            }
            else if (dto.ProductId == 0 || dto.ProductId == null)
            {
                dto.ProductLink = Guid.NewGuid().ToString();
            }

            var response = await _unitOfWork.Products.AddOrUpdateAsync(dto);
            if (response.Success)
            {
                await _unitOfWork.SaveChangesAsync();
                return Ok(response);
            }

            return BadRequest(response);
        }

        [HttpPost("PostPutTerritory")]
        public async Task<IActionResult> PostPutTerritory([FromBody] Territories dto)
        {
            if (dto == null)
                return BadRequest("Invalid doctor data.");

            var response = await _unitOfWork.Territories.AddOrUpdateAsync(dto);
            if (response.Success)
            {
                await _unitOfWork.SaveChangesAsync();
                return Ok(response);
            }

            return BadRequest(response);
        }
        [HttpPost("PostPutInstitutionCategory")]
        public async Task<IActionResult> PostPutInstitutionCategory([FromBody] InstitutionCategory dto)
        {
            if (dto == null)
                return BadRequest("Invalid category data.");

            var existing = await _unitOfWork.InstitutionCategories
                .FindAsync(c => c.InstitutionCategoryCode.ToLower() == dto.InstitutionCategoryCode.ToLower()
                                && c.InstitutionCategoryId != dto.InstitutionCategoryId);

            if (existing != null)
                return BadRequest(new { message = $"Institution Category Code {dto.InstitutionCategoryCode} already exists." });

            var response = await _unitOfWork.InstitutionCategories.AddOrUpdateAsync(dto);

            if (response.Success)
            {
                await _unitOfWork.SaveChangesAsync();
                return Ok(response);
            }

            return BadRequest(response);
        }
        #endregion

        #region Get
        [HttpGet("specialization/{companyId:int}")]
        public async Task<IActionResult> GetSpecialization(int companyId)
        {
            var items = await _unitOfWork.Specializations.GetAllAsync();
            var filtered = items.Where(p => p.CompanyId == companyId);

            return Ok(filtered);
        }
        [HttpGet("areas")]
        public async Task<IActionResult> GetAreas()
        {
            var doctors = await _unitOfWork.Areas.GetAllAsync();
            return Ok(doctors);
        }
        [HttpGet("districts")]
        public async Task<IActionResult> GetDistricts()
        {
            var doctors = await _unitOfWork.Districts.GetAllAsync(d=>d.Areas);
            return Ok(doctors);
        }
        [HttpGet("divisions")]
        public async Task<IActionResult> GetDivisions()
        {
            var doctors = await _unitOfWork.Divisions.GetAllAsync();
            return Ok(doctors);
        }
        [HttpGet("institutions")]
        public async Task<IActionResult> GetInstitutions()
        {
            var institutions = await _unitOfWork.Institutions.GetAllAsync(
                                 t => t.InstitutionCategory,
                                 t => t.Territories
                             );
            return Ok(institutions);
        }
        [HttpGet("territories")]
        public async Task<IActionResult> GetTerritories()
        {
            var territories = await _unitOfWork.Territories
                        .GetAllAsync(t => t.Districts); 
            return Ok(territories);
        }
        [HttpGet("institutionCategories")]
        public async Task<IActionResult> GetInstitutionCategory()
        {
            var item = await _unitOfWork.InstitutionCategories.GetAllAsync();
            return Ok(item);
        }
        [HttpGet("products")]
        public async Task<IActionResult> GetProducts([FromQuery] ProductDto dto)
        {
            var items = await _unitOfWork.Products.GetAllAsync();
            var filtered = dto.UserRole == "MEDREP"
                ? items.Where(p => p.UserId == dto.UserId)
                : items;

            return Ok(filtered);
        }

        [HttpGet("productFile/{fileName}")]
        [ResponseCache(Duration = 3600)] 
        public async Task<IActionResult> GetProductFile(string fileName)
        {
            if (string.IsNullOrWhiteSpace(fileName) || fileName.Contains(".."))
            {
                return BadRequest("Invalid file name");
            }

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

            ContentTypeHelper.ValidateFile(filePath, uploadsPath);
            var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
            var contentType = ContentTypeHelper.GetContentType(fileName);

            return File(fileStream, contentType, fileName, enableRangeProcessing: true);
        }
        
        [HttpGet("areas/{id:int}")]
        public async Task<IActionResult> GetAreaById(int id)
        {
            var area = await _unitOfWork.Areas.GetByIdAsync(id);
            if (area == null)
                return NotFound();

            return Ok(area);
        }

        [HttpGet("districts/{id:int}")]
        public async Task<IActionResult> GetDistrictById(int id)
        {
            var district = await _unitOfWork.Districts.GetByIdAsync(id);
            if (district == null)
                return NotFound();

            return Ok(district);
        }
        [HttpGet("division/{id:int}")]
        public async Task<IActionResult> GetDivisionById(int id)
        {
            var division = await _unitOfWork.Divisions.GetByIdAsync(id);
            if (division == null)
                return NotFound();

            return Ok(division);
        }
        [HttpGet("institution/{id:int}")]
        public async Task<IActionResult> GetInstitutionById(int id)
        {
            var institution = await _unitOfWork.Institutions.GetByIdAsync(id);
            if (institution == null)
                return NotFound();

            return Ok(institution);
        }
        [HttpGet("product/{id:int}")]
        public async Task<IActionResult> GetProductById(int id)
        {
            var product = await _unitOfWork.Products.GetByIdAsync(id);
            if (product == null)
                return NotFound();

            return Ok(product);
        }

        [HttpDelete("{id:int}")]
        public async Task<IActionResult> SoftDeleteAsync(int id)
        {
            var result = await _unitOfWork.Doctors.SoftDeleteAsync(id);
            return result.Success ? Ok(result) : BadRequest(result);
        }
        #endregion
    }
}
