using Core.Interfaces;
using Documents.Interfaces;
using Documents.Models;
using Domain.Dtos.Sales;
using Domain.Generics;
using Microsoft.AspNetCore.Mvc;
using System.Reflection;

namespace phronCare.API.Controllers.Sales
{
    [Route("api/[controller]")]
    [ApiController]
    public class DeliveryNoteController : ControllerBase
    {
        private readonly IDocumentTemplateService _documentTemplateService;
        private readonly IDeliveryNoteDom _deliveryNoteService;

        public DeliveryNoteController(
            IDocumentTemplateService documentTemplateService,
            IDeliveryNoteDom deliveryNoteService)
        {
            _documentTemplateService = documentTemplateService ?? throw new ArgumentNullException(nameof(documentTemplateService));
            _deliveryNoteService = deliveryNoteService ?? throw new ArgumentNullException(nameof(deliveryNoteService));
        }

        [HttpGet("search")]
        public async Task<ActionResult<PagedResult<DeliveryNoteSummaryDto>>> Search(
            [FromQuery] int? customerId,
            [FromQuery] string? customerText,
            [FromQuery] string? deliveryNoteNumber,
            [FromQuery] int? quoteId,
            [FromQuery] string? quoteNumber,
            [FromQuery] DateTime? issueDateFrom,
            [FromQuery] DateTime? issueDateTo,
            [FromQuery] string? status,
            [FromQuery] int page = 1,
            [FromQuery] int pageSize = 50)
        {
            try
            {
                var result = await _deliveryNoteService.SearchAsync(
                    customerId,
                    customerText,
                    deliveryNoteNumber,
                    quoteId,
                    quoteNumber,
                    issueDateFrom,
                    issueDateTo,
                    status,
                    page,
                    pageSize);

                return Ok(result);
            }
            catch (Exception ex)
            {
                var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod";
                return StatusCode(500, $"{methodName} Message: {ex.Message}");
            }
        }

        [HttpGet("{id:int}")]
        public async Task<ActionResult<DeliveryNoteDto>> GetById(int id)
        {
            try
            {
                var deliveryNote = await _deliveryNoteService.GetDtoByIdAsync(id);
                if (deliveryNote == null)
                    return NotFound($"Remito con ID {id} no encontrado.");

                return Ok(deliveryNote);
            }
            catch (Exception ex)
            {
                var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod";
                return StatusCode(500, $"{methodName} Message: {ex.Message}");
            }
        }

        [HttpGet("number/{deliveryNoteNumber}")]
        public async Task<ActionResult<DeliveryNoteDto>> GetByDeliveryNoteNumber(string deliveryNoteNumber)
        {
            try
            {
                var deliveryNote = await _deliveryNoteService.GetDtoByDeliveryNoteNumberAsync(deliveryNoteNumber);
                if (deliveryNote == null)
                    return NotFound($"Remito con número {deliveryNoteNumber} no encontrado.");

                return Ok(deliveryNote);
            }
            catch (Exception ex)
            {
                var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod";
                return StatusCode(500, $"{methodName} Message: {ex.Message}");
            }
        }


        [HttpGet("{id:int}/pdf")]
        public async Task<IActionResult> GetDeliveryNotePdf(int id)
        {
            var deliveryNote = await _deliveryNoteService.GetDtoByIdAsync(id);

            if (deliveryNote == null)
                return NotFound($"Remito con ID {id} no encontrado.");

            var pdfBytes = await _documentTemplateService.GenerateDocumentAsync(new DocumentGenerationRequest
            {
                Model = deliveryNote,
                DocumentType = DocumentType.DeliveryNote
            });

            return File(pdfBytes, "application/pdf", $"Remito_{deliveryNote.DeliveryNoteNumber}.pdf");
        }

        [HttpGet("by-quote/{quoteId:int}")]
        public async Task<ActionResult<IEnumerable<DeliveryNoteDto>>> GetByQuoteId(int quoteId)
        {
            try
            {
                var deliveryNotes = await _deliveryNoteService.GetDtosByQuoteIdAsync(quoteId);
                return Ok(deliveryNotes);
            }
            catch (Exception ex)
            {
                var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod";
                return StatusCode(500, $"{methodName} Message: {ex.Message}");
            }
        }

        [HttpPost("issue")]
        public async Task<ActionResult<DeliveryNoteCreateResponse>> Issue([FromBody] DeliveryNoteCreateRequest request)
        {
            try
            {
                var result = await _deliveryNoteService.CreateAndIssueDeliveryNoteAsync(request);
                return Ok(result);
            }
            catch (ArgumentException ex)
            {
                return BadRequest(ex.Message);
            }
            catch (InvalidOperationException ex)
            {
                return BadRequest(ex.Message);
            }
            catch (Exception ex)
            {
                var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod";
                return StatusCode(500, $"{methodName} Message: {ex.Message}");
            }
        }

        [HttpPost("exportfiltered")]
        public async Task<IActionResult> ExportFiltered([FromBody] DeliveryNoteSearchParams searchParams)
        {
            try
            {
                var file = await _deliveryNoteService.ExportFilteredToExcelAsync(searchParams);
                return File(
                    file,
                    "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
                    "Remitos.xlsx");
            }
            catch (ArgumentException ex)
            {
                return BadRequest(ex.Message);
            }
            catch (InvalidOperationException ex)
            {
                return BadRequest(ex.Message);
            }
            catch (Exception ex)
            {
                var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod";
                return BadRequest($"{methodName} Message: {ex.Message}");
            }
        }
    }
}
