using Domain.Dtos.Sales;
using Domain.Generics;
using System.Net.Http.Json;

namespace phronCare.UIBlazor.Services.Sales.SalesDocuments
{
    public sealed class SalesDocumentService : ISalesDocumentService
    {
        private readonly HttpClient _http;

        public SalesDocumentService(HttpClient http)
        {
            _http = http;
        }

        public async Task<PagedResult<SalesDocumentSummaryDto>> SearchAsync(SalesDocumentSearchParams searchParams)
        {
            ArgumentNullException.ThrowIfNull(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("quoteId", searchParams.QuoteId?.ToString());
            AddParam("documentType", searchParams.DocumentType?.ToString());
            AddParam("status", searchParams.Status?.ToString());
            AddParam("issueDateFrom", searchParams.IssueDateFrom?.ToString("o"));
            AddParam("issueDateTo", searchParams.IssueDateTo?.ToString("o"));
            AddParam("page", searchParams.Page.ToString());
            AddParam("pageSize", searchParams.PageSize.ToString());

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

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


        public async Task<PagedResult<SalesDocumentDeliveryNoteCandidateDto>> SearchDeliveryNoteCandidatesAsync(
            int? customerId,
            string? customerText,
            string? deliveryNoteNumber,
            int? quoteId,
            DateTime? issueDateFrom,
            DateTime? issueDateTo,
            int page = 1,
            int pageSize = 50)
        {
            var queryParams = new List<string>();

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

            AddParam("customerId", customerId?.ToString());
            AddParam("customerText", customerText);
            AddParam("deliveryNoteNumber", deliveryNoteNumber);
            AddParam("quoteId", quoteId?.ToString());
            AddParam("issueDateFrom", issueDateFrom?.ToString("o"));
            AddParam("issueDateTo", issueDateTo?.ToString("o"));
            AddParam("page", page.ToString());
            AddParam("pageSize", pageSize.ToString());

            var url = "/api/SalesDocument/delivery-note-candidates";
            if (queryParams.Any())
                url += "?" + string.Join("&", queryParams);

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

        public async Task<SalesDocumentDto> CreateFromDeliveryNotesAsync(SalesDocumentCreateFromDeliveryNotesRequest request)
        {
            ArgumentNullException.ThrowIfNull(request);

            var response = await _http.PostAsJsonAsync("/api/SalesDocument/from-delivery-notes", request);

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

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

        public async Task<List<SalesDocumentDeliveryNoteItemCandidateDto>> GetDeliveryNoteItemCandidatesAsync(IReadOnlyCollection<int> deliveryNoteIds)
        {
            ArgumentNullException.ThrowIfNull(deliveryNoteIds);

            var queryParams = deliveryNoteIds
                .Where(x => x > 0)
                .Distinct()
                .Select(x => $"deliveryNoteIds={Uri.EscapeDataString(x.ToString())}")
                .ToList();

            var url = "/api/SalesDocument/delivery-note-item-candidates";
            if (queryParams.Any())
                url += "?" + string.Join("&", queryParams);

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

        public async Task<SalesDocumentDto> CreateFromDeliveryNoteItemsAsync(SalesDocumentCreateFromDeliveryNoteItemsRequest request)
        {
            ArgumentNullException.ThrowIfNull(request);

            var response = await _http.PostAsJsonAsync("/api/SalesDocument/from-delivery-note-items", request);

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

            var result = await response.Content.ReadFromJsonAsync<SalesDocumentDto>();
            return result ?? throw new Exception("Respuesta vacia del servidor.");
        }

        public async Task<SalesDocumentDto?> GetByIdAsync(int id)
        {
            return await _http.GetFromJsonAsync<SalesDocumentDto>($"/api/SalesDocument/{id}");
        }

        public async Task<SalesDocumentDraftPreviewDto?> GetDraftPreviewAsync(int id)
        {
            return await _http.GetFromJsonAsync<SalesDocumentDraftPreviewDto>($"/api/SalesDocument/{id}/draft-preview");
        }

        public async Task<SalesDocumentDraftPreviewDto> UpdateDraftReviewAsync(int id, SalesDocumentDraftReviewDto request)
        {
            ArgumentNullException.ThrowIfNull(request);

            var response = await _http.PutAsJsonAsync($"/api/SalesDocument/{id}/draft-review", request);

            if (!response.IsSuccessStatusCode)
            {
                var serverMessage = await response.Content.ReadAsStringAsync();
                throw new Exception(string.IsNullOrWhiteSpace(serverMessage)
                    ? "No se pudo guardar la revision del Sales Document."
                    : serverMessage);
            }

            var result = await response.Content.ReadFromJsonAsync<SalesDocumentDraftPreviewDto>();
            return result ?? throw new Exception("Respuesta vacia del servidor.");
        }

        public async Task<SalesDocumentDraftPreviewDto> ValidateDraftAsync(int id)
        {
            var response = await _http.PostAsync($"/api/SalesDocument/{id}/validate", null);

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

            var result = await response.Content.ReadFromJsonAsync<SalesDocumentDraftPreviewDto>();
            return result ?? throw new Exception("Respuesta vacia del servidor.");
        }

        public async Task<SalesDocumentDto> CreateAsync(SalesDocumentCreateRequest request)
        {
            ArgumentNullException.ThrowIfNull(request);

            var response = await _http.PostAsJsonAsync("/api/SalesDocument", request);

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

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