using Domain.Dtos.Sales;
using Domain.Generics;
using Microsoft.JSInterop;
using System.Net.Http.Json;
using System.Text;
using System.Text.Json;

namespace phronCare.UIBlazor.Services.Sales.DeliveryNotes
{
    public class DeliveryNoteService : IDeliveryNoteService
    {
        private readonly IJSRuntime _js;
        private readonly HttpClient _http;

        public DeliveryNoteService(HttpClient http, IJSRuntime js)
        {
            _http = http;
            _js = js;
        }


        public async Task<PagedResult<DeliveryNoteSummaryDto>> SearchAsync(DeliveryNoteSearchParams searchParams)
        {
            var queryParams = new List<string>();

            void AddParam(string key, string? value)
            {
                if (!string.IsNullOrWhiteSpace(value))
                    queryParams.Add($"{key}={Uri.EscapeDataString(value!)}");
            }

            AddParam("customerId", searchParams.CustomerId?.ToString());
            AddParam("customerText", searchParams.CustomerText);
            AddParam("deliveryNoteNumber", searchParams.DeliveryNoteNumber);
            AddParam("quoteId", searchParams.QuoteId?.ToString());
            AddParam("quoteNumber", searchParams.QuoteNumber);
            AddParam("issueDateFrom", searchParams.IssueDateFrom?.ToString("o"));
            AddParam("issueDateTo", searchParams.IssueDateTo?.ToString("o"));
            AddParam("status", searchParams.Status);
            AddParam("page", searchParams.Page.ToString());
            AddParam("pageSize", searchParams.PageSize.ToString());

            var url = "/api/deliverynote/search";
            if (queryParams.Any())
                url += "?" + string.Join("&", queryParams);

            var result = await _http.GetFromJsonAsync<PagedResult<DeliveryNoteSummaryDto>>(url);
            return result ?? new PagedResult<DeliveryNoteSummaryDto>();
        }

        public async Task<DeliveryNoteDto?> GetByIdAsync(int id)
        {
            try
            {
                return await _http.GetFromJsonAsync<DeliveryNoteDto>($"/api/deliverynote/{id}");
            }
            catch
            {
                return null;
            }
        }

        public async Task<DeliveryNoteDto?> GetByDeliveryNoteNumberAsync(string deliveryNoteNumber)
        {
            try
            {
                return await _http.GetFromJsonAsync<DeliveryNoteDto>($"/api/deliverynote/number/{Uri.EscapeDataString(deliveryNoteNumber)}");
            }
            catch
            {
                return null;
            }
        }

        public async Task<IEnumerable<DeliveryNoteDto>> GetByQuoteIdAsync(int quoteId)
        {
            try
            {
                return await _http.GetFromJsonAsync<IEnumerable<DeliveryNoteDto>>($"/api/deliverynote/by-quote/{quoteId}") ?? Enumerable.Empty<DeliveryNoteDto>();
            }
            catch
            {
                return Enumerable.Empty<DeliveryNoteDto>();
            }
        }

        public async Task<DeliveryNoteCreateResponse> CreateAndIssueAsync(DeliveryNoteCreateRequest request)
        {
            var response = await _http.PostAsJsonAsync("/api/deliverynote/issue", request);

            if (!response.IsSuccessStatusCode)
            {
                var serverMessage = await response.Content.ReadAsStringAsync();
                throw new Exception(string.IsNullOrWhiteSpace(serverMessage)
                    ? "No se pudo emitir el remito."
                    : serverMessage);
            }

            var result = await response.Content.ReadFromJsonAsync<DeliveryNoteCreateResponse>();
            return result ?? throw new Exception("Respuesta vacía del servidor.");
        }

        public async Task ExportPdfAsync(int deliveryNoteId, string deliveryNoteNumber)
        {
            try
            {
                var response = await _http.GetAsync($"/api/deliverynote/{deliveryNoteId}/pdf");

                if (!response.IsSuccessStatusCode)
                {
                    var error = await response.Content.ReadAsStringAsync();
                    throw new Exception($"Error al generar PDF: {error}");
                }

                var bytes = await response.Content.ReadAsByteArrayAsync();
                var base64 = Convert.ToBase64String(bytes);
                var fileName = $"{deliveryNoteNumber}.pdf";

                await _js.InvokeVoidAsync("saveAsFile", fileName, base64);
            }
            catch (Exception ex)
            {
                throw new Exception($"ExportPdfAsync: {ex.Message}", ex);
            }
        }

        public async Task ExportFilteredAsync(DeliveryNoteSearchParams searchParams)
        {
            var content = new StringContent(JsonSerializer.Serialize(searchParams), Encoding.UTF8, "application/json");
            var response = await _http.PostAsync("/api/deliverynote/exportfiltered", content);

            if (!response.IsSuccessStatusCode)
            {
                var serverMessage = await response.Content.ReadAsStringAsync();
                throw new Exception(string.IsNullOrWhiteSpace(serverMessage)
                    ? "No se pudo exportar el Excel de remitos."
                    : serverMessage);
            }

            var bytes = await response.Content.ReadAsByteArrayAsync();
            var base64 = Convert.ToBase64String(bytes);
            var fileName = $"{DateTime.Now:yyyyMMddHHmm}_deliverynotes.xlsx";

            await _js.InvokeVoidAsync("saveAsFile", fileName, base64);
        }
    }
}
